|
|
@ -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; |
|
|
|