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