Browse Source

Add function processing and basic !Replace to cfnpp

master
Adam Pippin 3 years ago
parent
commit
f242056156
  1. 11
      app/Dom/Node.php
  2. 95
      app/Engine/Cfnpp.php

11
app/Dom/Node.php

@ -77,6 +77,17 @@ class Node implements \ArrayAccess, \Iterator
return $this->parent;
}
/**
* Set this node's parent.
*
* @param Node $parent
* @return void
*/
public function setParent(Node $parent): void
{
$this->parent = $parent;
}
/**
* Check whether this node has any child nodes.
*

95
app/Engine/Cfnpp.php

@ -6,6 +6,8 @@ namespace App\Engine;
use App\Dom\Document;
use App\Dom\Node;
use App\Dom\NodeFunction;
use App\Dom\NodeFunctionValue;
use App\Dom\NodeValue;
class Cfnpp implements ICompile
@ -13,6 +15,28 @@ class Cfnpp implements ICompile
/** @var Document */
protected $document;
/** @var array<string, callable> */
protected $functions;
public function __construct()
{
$this->functions = [];
$this->registerFunction('Replace', static function(Node $orig_p, Node $tgt_p, Node $t) {
if ($t instanceof NodeFunctionValue)
{
return $t->getValue();
}
return $t->getChildren();
});
}
public function registerFunction(string $name, callable $callback): void
{
$this->functions[$name] = $callback;
}
public function setDocument(Document $document): void
{
$this->document = $document;
@ -25,7 +49,6 @@ class Cfnpp implements ICompile
protected function compileNodes(Node $original, Node $target): void
{
var_dump(get_class($original), get_class($target));
if ($target instanceof NodeValue)
{
if ($original instanceof NodeValue)
@ -39,7 +62,10 @@ class Cfnpp implements ICompile
$parent->addChild($target);
}
}
// TODO: Add nodefunctions
elseif ($target instanceof NodeFunction)
{
$this->resolveFunction($original->getParent(), $target->getParent(), $target);
}
elseif ($target instanceof Node)
{
// if they're both maps, add/overwrite by name
@ -48,13 +74,24 @@ class Cfnpp implements ICompile
foreach ($target as $target_child)
{
$orig_child = $original->getChildByName($target_child->getName());
if (!isset($orig_child))
if ($target_child instanceof NodeFunction)
{
$original->addChild($target_child);
if (!isset($orig_child))
{
$original->addChild($orig_child = new Node($original, $target->getName()));
}
$this->compileNodes($orig_child, $target_child);
}
else
{
$this->compileNodes($orig_child, $target_child);
if (!isset($orig_child))
{
$original->addChild($target_child);
}
else
{
$this->compileNodes($orig_child, $target_child);
}
}
}
}
@ -76,6 +113,54 @@ class Cfnpp implements ICompile
}
}
protected function resolveFunction(Node $original_parent, Node $target_parent, Node $target): void
{
// Execute nodefunction
$function = $target->getName();
if (!isset($this->functions[$function]))
{
throw new \Exception('Unrecognized function: '.$function);
}
$result = $this->functions[$function]($original_parent, $target_parent, $target);
if (is_scalar($result))
{
$original_grandparent = $original_parent->getParent();
$original_grandparent->removeChild($original_parent);
$node = new NodeValue($original_grandparent, $target_parent->getName(), $result);
$original_grandparent->addChild($node);
// Remove processed function
$target_parent->getParent()->removeChild($target_parent);
}
elseif (is_array($result))
{
// Update original _and_ target so we can reprocess sensibly
$original_grandparent = $original_parent->getParent();
$original_grandparent->removeChild($original_parent);
$original_parent = new Node($original_grandparent, $original_parent->getName());
$original_grandparent->addChild($original_parent);
foreach ($result as $node)
{
$original_parent->addChild($node);
$node->setParent($original_parent->getParent());
}
$target_grandparent = $target_parent->getParent();
$target_grandparent->removeChild($target_parent);
$target_parent = new Node($target_grandparent, $target_parent->getName());
$target_grandparent->addChild($target_parent);
foreach ($result as $node)
{
$node = clone $node;
$target_parent->addChild($node);
$node->setParent($target_parent->getParent());
}
$this->compileNodes($original_parent, $target_parent);
}
}
public function getDocument(): Document
{
return $this->document;

Loading…
Cancel
Save