1*37748cd8SNickeau<?php 2*37748cd8SNickeau 3*37748cd8SNickeaudeclare(strict_types=1); 4*37748cd8SNickeau 5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime; 6*37748cd8SNickeau 7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Error\Exceptions\RecognitionException; 8*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Tree\ErrorNode; 9*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Tree\ParseTree; 10*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Tree\ParseTreeListener; 11*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Tree\TerminalNode; 12*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Tree\Tree; 13*37748cd8SNickeau 14*37748cd8SNickeau/** 15*37748cd8SNickeau * A rule invocation record for parsing. 16*37748cd8SNickeau * 17*37748cd8SNickeau * Contains all of the information about the current rule not stored 18*37748cd8SNickeau * in the RuleContext. It handles parse tree children list, any ATN state 19*37748cd8SNickeau * tracing, and the default values available for rule invocations: start, stop, 20*37748cd8SNickeau * rule index, current alt number. 21*37748cd8SNickeau * 22*37748cd8SNickeau * Subclasses made for each rule and grammar track the parameters, return values, 23*37748cd8SNickeau * locals, and labels specific to that rule. These are the objects 24*37748cd8SNickeau * that are returned from rules. 25*37748cd8SNickeau * 26*37748cd8SNickeau * Note text is not an actual field of a rule return value; it is computed 27*37748cd8SNickeau * from start and stop using the input stream's toString() method. I could 28*37748cd8SNickeau * add a ctor to this so that we can pass in and store the input stream, 29*37748cd8SNickeau * but I'm not sure we want to do that. It would seem to be undefined to get 30*37748cd8SNickeau * the `text` property anyway if the rule matches tokens from multiple 31*37748cd8SNickeau * input streams. 32*37748cd8SNickeau * 33*37748cd8SNickeau * I do not use getters for fields of objects that are used simply to group 34*37748cd8SNickeau * values such as this aggregate. The getters/setters are there to satisfy 35*37748cd8SNickeau * the superclass interface. 36*37748cd8SNickeau */ 37*37748cd8SNickeauclass ParserRuleContext extends RuleContext 38*37748cd8SNickeau{ 39*37748cd8SNickeau /** 40*37748cd8SNickeau * If we are debugging or building a parse tree for a visitor, 41*37748cd8SNickeau * we need to track all of the tokens and rule invocations associated 42*37748cd8SNickeau * with this rule's context. This is empty for parsing w/o tree constr. 43*37748cd8SNickeau * operation because we don't the need to track the details about 44*37748cd8SNickeau * how we parse this rule. 45*37748cd8SNickeau * 46*37748cd8SNickeau * @var array<ParseTree>|null 47*37748cd8SNickeau */ 48*37748cd8SNickeau public $children; 49*37748cd8SNickeau 50*37748cd8SNickeau /** @var Token|null */ 51*37748cd8SNickeau public $start; 52*37748cd8SNickeau 53*37748cd8SNickeau /** @var Token|null */ 54*37748cd8SNickeau public $stop; 55*37748cd8SNickeau 56*37748cd8SNickeau /** 57*37748cd8SNickeau * The exception that forced this rule to return. If the rule successfully 58*37748cd8SNickeau * completed, this is `null`. 59*37748cd8SNickeau * 60*37748cd8SNickeau * @var RecognitionException|null 61*37748cd8SNickeau */ 62*37748cd8SNickeau public $exception; 63*37748cd8SNickeau 64*37748cd8SNickeau /** 65*37748cd8SNickeau * COPY a context (I'm deliberately not using copy constructor) to avoid 66*37748cd8SNickeau * confusion with creating node with parent. Does not copy children 67*37748cd8SNickeau * (except error leaves). 68*37748cd8SNickeau * 69*37748cd8SNickeau * This is used in the generated parser code to flip a generic XContext 70*37748cd8SNickeau * node for rule X to a YContext for alt label Y. In that sense, it is 71*37748cd8SNickeau * not really a generic copy function. 72*37748cd8SNickeau * 73*37748cd8SNickeau * If we do an error sync() at start of a rule, we might add error nodes 74*37748cd8SNickeau * to the generic XContext so this function must copy those nodes to 75*37748cd8SNickeau * the YContext as well else they are lost! 76*37748cd8SNickeau */ 77*37748cd8SNickeau public function copyFrom(ParserRuleContext $ctx) : void 78*37748cd8SNickeau { 79*37748cd8SNickeau // from RuleContext 80*37748cd8SNickeau $this->parentCtx = $ctx->parentCtx; 81*37748cd8SNickeau $this->invokingState = $ctx->invokingState; 82*37748cd8SNickeau $this->children = null; 83*37748cd8SNickeau $this->start = $ctx->start; 84*37748cd8SNickeau $this->stop = $ctx->stop; 85*37748cd8SNickeau 86*37748cd8SNickeau // copy any error nodes to alt label node 87*37748cd8SNickeau if ($ctx->children) { 88*37748cd8SNickeau $this->children = []; 89*37748cd8SNickeau 90*37748cd8SNickeau // reset parent pointer for any error nodes 91*37748cd8SNickeau foreach ($ctx->children as $child) { 92*37748cd8SNickeau if ($child instanceof ErrorNode) { 93*37748cd8SNickeau $this->addErrorNode($child); 94*37748cd8SNickeau } 95*37748cd8SNickeau } 96*37748cd8SNickeau } 97*37748cd8SNickeau } 98*37748cd8SNickeau 99*37748cd8SNickeau public function enterRule(ParseTreeListener $listener) : void 100*37748cd8SNickeau { 101*37748cd8SNickeau } 102*37748cd8SNickeau 103*37748cd8SNickeau public function exitRule(ParseTreeListener $listener) : void 104*37748cd8SNickeau { 105*37748cd8SNickeau } 106*37748cd8SNickeau 107*37748cd8SNickeau public function addTerminalNode(TerminalNode $t) : ParseTree 108*37748cd8SNickeau { 109*37748cd8SNickeau $t->setParent($this); 110*37748cd8SNickeau 111*37748cd8SNickeau return $this->addChild($t); 112*37748cd8SNickeau } 113*37748cd8SNickeau 114*37748cd8SNickeau public function addErrorNode(ErrorNode $errorNode) : ParseTree 115*37748cd8SNickeau { 116*37748cd8SNickeau $errorNode->setParent($this); 117*37748cd8SNickeau 118*37748cd8SNickeau return $this->addChild($errorNode); 119*37748cd8SNickeau } 120*37748cd8SNickeau 121*37748cd8SNickeau /** 122*37748cd8SNickeau * Add a parse tree node to this as a child. Works for 123*37748cd8SNickeau * internal and leaf nodes. Does not set parent link; 124*37748cd8SNickeau * other add methods must do that. Other addChild methods 125*37748cd8SNickeau * call this. 126*37748cd8SNickeau * 127*37748cd8SNickeau * We cannot set the parent pointer of the incoming node 128*37748cd8SNickeau * because the existing interfaces do not have a `setParent()` 129*37748cd8SNickeau * method and I don't want to break backward compatibility for this. 130*37748cd8SNickeau */ 131*37748cd8SNickeau public function addChild(ParseTree $child) : ParseTree 132*37748cd8SNickeau { 133*37748cd8SNickeau if ($this->children === null) { 134*37748cd8SNickeau $this->children = []; 135*37748cd8SNickeau } 136*37748cd8SNickeau 137*37748cd8SNickeau $this->children[] = $child; 138*37748cd8SNickeau 139*37748cd8SNickeau return $child; 140*37748cd8SNickeau } 141*37748cd8SNickeau 142*37748cd8SNickeau /** 143*37748cd8SNickeau * Used by enterOuterAlt to toss out a RuleContext previously added as 144*37748cd8SNickeau * we entered a rule. If we have # label, we will need to remove 145*37748cd8SNickeau * generic `ruleContext` object. 146*37748cd8SNickeau */ 147*37748cd8SNickeau public function removeLastChild() : void 148*37748cd8SNickeau { 149*37748cd8SNickeau if ($this->children !== null) { 150*37748cd8SNickeau \array_pop($this->children); 151*37748cd8SNickeau } 152*37748cd8SNickeau } 153*37748cd8SNickeau 154*37748cd8SNickeau /** 155*37748cd8SNickeau * @return RuleContext|null 156*37748cd8SNickeau */ 157*37748cd8SNickeau public function getParent() : ?Tree 158*37748cd8SNickeau { 159*37748cd8SNickeau return $this->parentCtx; 160*37748cd8SNickeau } 161*37748cd8SNickeau 162*37748cd8SNickeau /** 163*37748cd8SNickeau * @return ParseTree|null 164*37748cd8SNickeau */ 165*37748cd8SNickeau public function getChild(int $i, ?string $type = null) : ?Tree 166*37748cd8SNickeau { 167*37748cd8SNickeau if ($this->children === null || $i < 0 || $i >= \count($this->children)) { 168*37748cd8SNickeau return null; 169*37748cd8SNickeau } 170*37748cd8SNickeau 171*37748cd8SNickeau if ($type === null) { 172*37748cd8SNickeau return $this->children[$i]; 173*37748cd8SNickeau } 174*37748cd8SNickeau 175*37748cd8SNickeau foreach ($this->children as $child) { 176*37748cd8SNickeau if ($child instanceof $type) { 177*37748cd8SNickeau if ($i === 0) { 178*37748cd8SNickeau return $child; 179*37748cd8SNickeau } 180*37748cd8SNickeau 181*37748cd8SNickeau $i--; 182*37748cd8SNickeau } 183*37748cd8SNickeau } 184*37748cd8SNickeau 185*37748cd8SNickeau return null; 186*37748cd8SNickeau } 187*37748cd8SNickeau 188*37748cd8SNickeau public function getToken(int $ttype, int $i) : ?TerminalNode 189*37748cd8SNickeau { 190*37748cd8SNickeau if ($this->children === null || $i < 0 || $i >= \count($this->children)) { 191*37748cd8SNickeau return null; 192*37748cd8SNickeau } 193*37748cd8SNickeau 194*37748cd8SNickeau foreach ($this->children as $child) { 195*37748cd8SNickeau if ($child instanceof TerminalNode && $child->getSymbol()->getType() === $ttype) { 196*37748cd8SNickeau if ($i === 0) { 197*37748cd8SNickeau return $child; 198*37748cd8SNickeau } 199*37748cd8SNickeau 200*37748cd8SNickeau $i--; 201*37748cd8SNickeau } 202*37748cd8SNickeau } 203*37748cd8SNickeau 204*37748cd8SNickeau return null; 205*37748cd8SNickeau } 206*37748cd8SNickeau 207*37748cd8SNickeau /** 208*37748cd8SNickeau * @return array<TerminalNode> 209*37748cd8SNickeau */ 210*37748cd8SNickeau public function getTokens(int $ttype) : array 211*37748cd8SNickeau { 212*37748cd8SNickeau if ($this->children === null) { 213*37748cd8SNickeau return []; 214*37748cd8SNickeau } 215*37748cd8SNickeau 216*37748cd8SNickeau $tokens = []; 217*37748cd8SNickeau foreach ($this->children as $child) { 218*37748cd8SNickeau if ($child instanceof TerminalNode && $child->getSymbol()->getType() === $ttype) { 219*37748cd8SNickeau $tokens[] = $child; 220*37748cd8SNickeau } 221*37748cd8SNickeau } 222*37748cd8SNickeau 223*37748cd8SNickeau return $tokens; 224*37748cd8SNickeau } 225*37748cd8SNickeau 226*37748cd8SNickeau public function getTypedRuleContext(string $ctxType, int $i) : ?ParseTree 227*37748cd8SNickeau { 228*37748cd8SNickeau return $this->getChild($i, $ctxType); 229*37748cd8SNickeau } 230*37748cd8SNickeau 231*37748cd8SNickeau /** 232*37748cd8SNickeau * @return array<ParseTree> 233*37748cd8SNickeau */ 234*37748cd8SNickeau public function getTypedRuleContexts(string $ctxType) : array 235*37748cd8SNickeau { 236*37748cd8SNickeau if ($this->children=== null) { 237*37748cd8SNickeau return []; 238*37748cd8SNickeau } 239*37748cd8SNickeau 240*37748cd8SNickeau $contexts = []; 241*37748cd8SNickeau foreach ($this->children as $child) { 242*37748cd8SNickeau if ($child instanceof $ctxType) { 243*37748cd8SNickeau $contexts[] = $child; 244*37748cd8SNickeau } 245*37748cd8SNickeau } 246*37748cd8SNickeau 247*37748cd8SNickeau return $contexts; 248*37748cd8SNickeau } 249*37748cd8SNickeau 250*37748cd8SNickeau public function getChildCount() : int 251*37748cd8SNickeau { 252*37748cd8SNickeau return $this->children !== null ? \count($this->children) : 0; 253*37748cd8SNickeau } 254*37748cd8SNickeau 255*37748cd8SNickeau public function getSourceInterval() : Interval 256*37748cd8SNickeau { 257*37748cd8SNickeau if ($this->start === null || $this->stop === null) { 258*37748cd8SNickeau return Interval::invalid(); 259*37748cd8SNickeau } 260*37748cd8SNickeau 261*37748cd8SNickeau return new Interval($this->start->getTokenIndex(), $this->stop->getTokenIndex()); 262*37748cd8SNickeau } 263*37748cd8SNickeau 264*37748cd8SNickeau /** 265*37748cd8SNickeau * Get the initial token in this context. 266*37748cd8SNickeau * 267*37748cd8SNickeau * Note that the range from start to stop is inclusive, so for rules that 268*37748cd8SNickeau * do not consume anything (for example, zero length or error productions) 269*37748cd8SNickeau * this token may exceed stop. 270*37748cd8SNickeau */ 271*37748cd8SNickeau public function getStart() : ?Token 272*37748cd8SNickeau { 273*37748cd8SNickeau return $this->start; 274*37748cd8SNickeau } 275*37748cd8SNickeau 276*37748cd8SNickeau /** 277*37748cd8SNickeau * Get the final token in this context. 278*37748cd8SNickeau * 279*37748cd8SNickeau * Note that the range from start to stop is inclusive, so for rules that 280*37748cd8SNickeau * do not consume anything (for example, zero length or error productions) 281*37748cd8SNickeau * this token may precede start. 282*37748cd8SNickeau */ 283*37748cd8SNickeau public function getStop() : ?Token 284*37748cd8SNickeau { 285*37748cd8SNickeau return $this->stop; 286*37748cd8SNickeau } 287*37748cd8SNickeau} 288