protected function buildTree(int $i = 0, array &$children = [])
    {
        $max = \count($this->trace);

        while ($i < $max) {
            $trace = $this->trace[$i];

            if ($trace instanceof Entry) {
                $ruleName = $trace->getRule();
                $rule = $this->grammar->fetch($ruleName);
                $isRule = $trace->isTransitional() === false;
                $nextTrace = $this->trace[$i + 1];
                $id = $rule->getNodeId();

                // Optimization: Skip empty trace sequence.
                if ($nextTrace instanceof Escape && $ruleName === $nextTrace->getRule()) {
                    $i += 2;

                    continue;
                }

                if ($isRule === true) {
                    $children[] = $ruleName;
                }

                if ($id !== null) {
                    $children[] = [$id];
                }

                $i = $this->buildTree($i + 1, $children);

                if ($isRule === false) {
                    continue;
                }

                $handle = [];
                $childId = null;

                do {
                    $pop = \array_pop($children);

                    if (\is_object($pop) === true) {
                        $handle[] = $pop;
                    } elseif (\is_array($pop) && $childId === null) {
                        $childId = \reset($pop);
                    } elseif ($ruleName === $pop) {
                        break;
                    }
                } while ($pop !== null);

                if ($childId === null) {
                    $childId = $rule->getDefaultId();
                }

                if ($childId === null) {
                    for ($j = \count($handle) - 1; $j >= 0; --$j) {
                        $children[] = $handle[$j];
                    }

                    continue;
                }

                $children[] = $this->getRule(
                    (string)($id ?: $childId),
                    \array_reverse($handle),
                    $trace->getOffset()
                );
            } elseif ($trace instanceof Escape) {
                return $i + 1;
            } else {
                if (! $trace->isKept()) {
                    ++$i;
                    continue;
                }

                $children[] = new Leaf($trace->getToken());
                ++$i;
            }
        }

        return $children[0];
    }
protected function buildTree(int $i = 0, array &$children = [])
    {
        $max = \count($this->trace);

        while ($i < $max) {
            $trace = $this->trace[$i];

            if ($trace instanceof Entry) {
                $ruleName = $trace->getRule();
                $rule = $this->grammar->fetch($ruleName);
                $isRule = $trace->isTransitional() === false;
                $nextTrace = $this->trace[$i + 1];
                $id = $rule->getNodeId();

                // Optimization: Skip empty trace sequence.
                if ($nextTrace instanceof Escape && $ruleName === $nextTrace->getRule()) {
                    $i += 2;

                    continue;
                }

                if ($isRule === true) {
                    $children[] = $ruleName;
                }

                if ($id !== null) {
                    $children[] = [$id];
                }

                $i = $this->buildTree($i + 1, $children);

                if ($isRule === false) {
                    continue;
                }

                $handle = [];
                $childId = null;

                do {
                    $pop = \array_pop($children);

                    if (\is_object($pop) === true) {
                        $handle[] = $pop;
                    } elseif (\is_array($pop) && $childId === null) {
                        $childId = \reset($pop);
                    } elseif ($ruleName === $pop) {
                        break;
                    }
                } while ($pop !== null);

                if ($childId === null) {
                    $childId = $rule->getDefaultId();
                }

                if ($childId === null) {
                    for ($j = \count($handle) - 1; $j >= 0; --$j) {
                        $children[] = $handle[$j];
                    }

                    continue;
                }

                $children[] = $this->getRule(
                    (string)($id ?: $childId),
                    \array_reverse($handle),
                    $trace->getOffset()
                );
            } elseif ($trace instanceof Escape) {
                return $i + 1;
            } else {
                if (! $trace->isKept()) {
                    ++$i;
                    continue;
                }

                $children[] = new Leaf($trace->getToken());
                ++$i;
            }
        }

        return $children[0];
    }
protected function buildTree ( int $ i = 0 , array & $ children = [ ] ) { $ max = \ count ( $ this -> trace ) ; while ( $ i < $ max ) { $ trace = $ this -> trace [ $ i ] ; if ( $ trace instanceof Entry ) { $ ruleName = $ trace -> getRule ( ) ; $ rule = $ this -> grammar -> fetch ( $ ruleName ) ; $ isRule = $ trace -> isTransitional ( ) === false ; $ nextTrace = $ this -> trace [ $ i + 1 ] ; $ id = $ rule -> getNodeId ( ) ; // Optimization: Skip empty trace sequence. if ( $ nextTrace instanceof Escape && $ ruleName === $ nextTrace -> getRule ( ) ) { $ i += 2 ; continue ; } if ( $ isRule === true ) { $ children [ ] = $ ruleName ; } if ( $ id !== null ) { $ children [ ] = [ $ id ] ; } $ i = $ this -> buildTree ( $ i + 1 , $ children ) ; if ( $ isRule === false ) { continue ; } $ handle = [ ] ; $ childId = null ; do { $ pop = \ array_pop ( $ children ) ; if ( \ is_object ( $ pop ) === true ) { $ handle [ ] = $ pop ; } elseif ( \ is_array ( $ pop ) && $ childId === null ) { $ childId = \ reset ( $ pop ) ; } elseif ( $ ruleName === $ pop ) { break ; } } while ( $ pop !== null ) ; if ( $ childId === null ) { $ childId = $ rule -> getDefaultId ( ) ; } if ( $ childId === null ) { for ( $ j = \ count ( $ handle ) - 1 ; $ j >= 0 ; -- $ j ) { $ children [ ] = $ handle [ $ j ] ; } continue ; } $ children [ ] = $ this -> getRule ( ( string ) ( $ id ? : $ childId ) , \ array_reverse ( $ handle ) , $ trace -> getOffset ( ) ) ; } elseif ( $ trace instanceof Escape ) { return $ i + 1 ; } else { if ( ! $ trace -> isKept ( ) ) { ++ $ i ; continue ; } $ children [ ] = new Leaf ( $ trace -> getToken ( ) ) ; ++ $ i ; } } return $ children [ 0 ] ; }
Build AST from trace.
Walk through the trace iteratively and recursively.

@param int $i Current trace index.
@param array &$children Collected children.
@return Node|int
@throws \LogicException
Build AST from trace . Walk through the trace iteratively and recursively .