/**
  * 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);
 }
Exemple #2
0
 /**
  * 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;
 }