/** * Walks the tree to restore left-associativity of some operators * * @param TreeNode $root AST root node */ private function fixOperatorAssociativity(TreeNode &$root) { switch ($root->getChildrenNumber()) { case 0: // Leaf nodes can't be rotated, and have no childs return; case 2: // We only want to rotate tree contained in the left associative // subset of operators $rootType = $root->getId(); if (!in_array($rootType, self::$leftAssociativeOperators)) { break; } // Do not break operator precedence $pivot = $root->getChild(1); if ($pivot->getId() !== $rootType) { break; } $this->leftRotateTree($root); break; } // Recursively fix tree branches $children = $root->getChildren(); foreach ($children as $index => $_) { $this->fixOperatorAssociativity($children[$index]); } $root->setChildren($children); }
/** * Merge recursively. * Please, see self::mergeTree() to know the context. * * @param \Hoa\Compiler\Llk\TreeNode $node Node that receives. * @param \Hoa\Compiler\Llk\TreeNode $newNode Node to merge. * @return void */ protected function mergeTreeRecursive(TreeNode $node, TreeNode $newNode) { $nNId = $newNode->getId(); if ('token' === $nNId) { $node->appendChild($newNode); $newNode->setParent($node); return; } $children = $node->getChildren(); end($children); $last = current($children); if ($last->getId() !== $nNId) { $node->appendChild($newNode); $newNode->setParent($node); return; } foreach ($newNode->getChildren() as $child) { $this->mergeTreeRecursive($last, $child); } return; }