xref: /template/strap/vendor/antlr/antlr4-php-runtime/src/Tree/ParseTreeWalker.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1*37748cd8SNickeau<?php
2*37748cd8SNickeau
3*37748cd8SNickeaudeclare(strict_types=1);
4*37748cd8SNickeau
5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime\Tree;
6*37748cd8SNickeau
7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\ParserRuleContext;
8*37748cd8SNickeau
9*37748cd8SNickeauclass ParseTreeWalker
10*37748cd8SNickeau{
11*37748cd8SNickeau    public static function default() : self
12*37748cd8SNickeau    {
13*37748cd8SNickeau        static $instance;
14*37748cd8SNickeau
15*37748cd8SNickeau        return $instance ?? ($instance = new self());
16*37748cd8SNickeau    }
17*37748cd8SNickeau
18*37748cd8SNickeau    public function walk(ParseTreeListener $listener, ParseTree $tree) : void
19*37748cd8SNickeau    {
20*37748cd8SNickeau        if ($tree instanceof ErrorNode) {
21*37748cd8SNickeau            $listener->visitErrorNode($tree);
22*37748cd8SNickeau
23*37748cd8SNickeau            return;
24*37748cd8SNickeau        }
25*37748cd8SNickeau
26*37748cd8SNickeau        if ($tree instanceof TerminalNode) {
27*37748cd8SNickeau            $listener->visitTerminal($tree);
28*37748cd8SNickeau
29*37748cd8SNickeau            return;
30*37748cd8SNickeau        }
31*37748cd8SNickeau
32*37748cd8SNickeau        if (!$tree instanceof RuleNode) {
33*37748cd8SNickeau            throw new \RuntimeException('Unexpected tree type.');
34*37748cd8SNickeau        }
35*37748cd8SNickeau
36*37748cd8SNickeau        $this->enterRule($listener, $tree);
37*37748cd8SNickeau
38*37748cd8SNickeau        $count = $tree->getChildCount();
39*37748cd8SNickeau
40*37748cd8SNickeau        for ($i = 0; $i < $count; $i++) {
41*37748cd8SNickeau            $child = $tree->getChild($i);
42*37748cd8SNickeau
43*37748cd8SNickeau            if ($child !== null) {
44*37748cd8SNickeau                $this->walk($listener, $child);
45*37748cd8SNickeau            }
46*37748cd8SNickeau        }
47*37748cd8SNickeau
48*37748cd8SNickeau        $this->exitRule($listener, $tree);
49*37748cd8SNickeau    }
50*37748cd8SNickeau
51*37748cd8SNickeau    /**
52*37748cd8SNickeau     * The discovery of a rule node, involves sending two events: the generic
53*37748cd8SNickeau     * {@see ParseTreeListener::enterEveryRule()} and a
54*37748cd8SNickeau     * {@see RuleContext}-specific event. First we trigger the generic and then
55*37748cd8SNickeau     * the rule specific. We to them in reverse order upon finishing the node.
56*37748cd8SNickeau     */
57*37748cd8SNickeau    protected function enterRule(ParseTreeListener $listener, RuleNode $ruleNode) : void
58*37748cd8SNickeau    {
59*37748cd8SNickeau        /** @var ParserRuleContext $ctx */
60*37748cd8SNickeau        $ctx = $ruleNode->getRuleContext();
61*37748cd8SNickeau
62*37748cd8SNickeau        $listener->enterEveryRule($ctx);
63*37748cd8SNickeau
64*37748cd8SNickeau        $ctx->enterRule($listener);
65*37748cd8SNickeau    }
66*37748cd8SNickeau
67*37748cd8SNickeau    protected function exitRule(ParseTreeListener $listener, RuleNode $ruleNode) : void
68*37748cd8SNickeau    {
69*37748cd8SNickeau        /** @var ParserRuleContext $ctx */
70*37748cd8SNickeau        $ctx = $ruleNode->getRuleContext();
71*37748cd8SNickeau
72*37748cd8SNickeau        $ctx->exitRule($listener);
73*37748cd8SNickeau
74*37748cd8SNickeau        $listener->exitEveryRule($ctx);
75*37748cd8SNickeau    }
76*37748cd8SNickeau}
77