1*37748cd8SNickeau<?php 2*37748cd8SNickeau 3*37748cd8SNickeaudeclare(strict_types=1); 4*37748cd8SNickeau 5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime\Atn; 6*37748cd8SNickeau 7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerAction; 8*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\ATNState; 9*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\DecisionState; 10*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\RuleStartState; 11*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\RuleStopState; 12*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\TokensStartState; 13*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\RuleTransition; 14*37748cd8SNickeauuse Antlr\Antlr4\Runtime\IntervalSet; 15*37748cd8SNickeauuse Antlr\Antlr4\Runtime\LL1Analyzer; 16*37748cd8SNickeauuse Antlr\Antlr4\Runtime\ParserRuleContext; 17*37748cd8SNickeauuse Antlr\Antlr4\Runtime\RuleContext; 18*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Token; 19*37748cd8SNickeau 20*37748cd8SNickeaufinal class ATN 21*37748cd8SNickeau{ 22*37748cd8SNickeau public const INVALID_ALT_NUMBER = 0; 23*37748cd8SNickeau public const ATN_TYPE_LEXER = 0; 24*37748cd8SNickeau public const ATN_TYPE_PARSER = 1; 25*37748cd8SNickeau 26*37748cd8SNickeau /** @var array<ATNState> */ 27*37748cd8SNickeau public $states = []; 28*37748cd8SNickeau 29*37748cd8SNickeau /** 30*37748cd8SNickeau * Each subrule/rule is a decision point and we must track them so we 31*37748cd8SNickeau * can go back later and build DFA predictors for them. This includes 32*37748cd8SNickeau * all the rules, subrules, optional blocks, ()+, ()* etc... 33*37748cd8SNickeau * 34*37748cd8SNickeau * @var array<DecisionState> 35*37748cd8SNickeau */ 36*37748cd8SNickeau public $decisionToState = []; 37*37748cd8SNickeau 38*37748cd8SNickeau /** 39*37748cd8SNickeau * Maps from rule index to starting state number. 40*37748cd8SNickeau * 41*37748cd8SNickeau * @var array<RuleStartState> 42*37748cd8SNickeau */ 43*37748cd8SNickeau public $ruleToStartState = []; 44*37748cd8SNickeau 45*37748cd8SNickeau /** 46*37748cd8SNickeau * Maps from rule index to stop state number. 47*37748cd8SNickeau * 48*37748cd8SNickeau * @var array<RuleStopState> 49*37748cd8SNickeau */ 50*37748cd8SNickeau public $ruleToStopState = []; 51*37748cd8SNickeau 52*37748cd8SNickeau /** @var array<TokensStartState> */ 53*37748cd8SNickeau public $modeNameToStartState = []; 54*37748cd8SNickeau 55*37748cd8SNickeau /** 56*37748cd8SNickeau * The type of the ATN. 57*37748cd8SNickeau * 58*37748cd8SNickeau * @var int 59*37748cd8SNickeau */ 60*37748cd8SNickeau public $grammarType; 61*37748cd8SNickeau 62*37748cd8SNickeau /** 63*37748cd8SNickeau * The maximum value for any symbol recognized by a transition in the ATN. 64*37748cd8SNickeau * 65*37748cd8SNickeau * @var int 66*37748cd8SNickeau */ 67*37748cd8SNickeau public $maxTokenType; 68*37748cd8SNickeau 69*37748cd8SNickeau /** 70*37748cd8SNickeau * For lexer ATNs, this maps the rule index to the resulting token type. 71*37748cd8SNickeau * For parser ATNs, this maps the rule index to the generated bypass token 72*37748cd8SNickeau * type if the 73*37748cd8SNickeau * {@see ATNDeserializationOptions::isGenerateRuleBypassTransitions()} 74*37748cd8SNickeau * deserialization option was specified; otherwise, this is `null`. 75*37748cd8SNickeau * 76*37748cd8SNickeau * @var array<int|null> 77*37748cd8SNickeau */ 78*37748cd8SNickeau public $ruleToTokenType = []; 79*37748cd8SNickeau 80*37748cd8SNickeau /** 81*37748cd8SNickeau * For lexer ATNs, this is an array of {@see LexerAction} objects which may 82*37748cd8SNickeau * be referenced by action transitions in the ATN. 83*37748cd8SNickeau * 84*37748cd8SNickeau * @var array<LexerAction> 85*37748cd8SNickeau */ 86*37748cd8SNickeau public $lexerActions = []; 87*37748cd8SNickeau 88*37748cd8SNickeau /** @var array<TokensStartState> */ 89*37748cd8SNickeau public $modeToStartState = []; 90*37748cd8SNickeau 91*37748cd8SNickeau /** 92*37748cd8SNickeau * Used for runtime deserialization of ATNs from strings 93*37748cd8SNickeau */ 94*37748cd8SNickeau public function __construct(int $grammarType, int $maxTokenType) 95*37748cd8SNickeau { 96*37748cd8SNickeau $this->grammarType = $grammarType; 97*37748cd8SNickeau $this->maxTokenType = $maxTokenType; 98*37748cd8SNickeau } 99*37748cd8SNickeau 100*37748cd8SNickeau /** 101*37748cd8SNickeau * Compute the set of valid tokens that can occur starting in state `state`. 102*37748cd8SNickeau * If `context` is null, the set of tokens will not include what can follow 103*37748cd8SNickeau * the rule surrounding `state`. In other words, the set will be 104*37748cd8SNickeau * restricted to tokens reachable staying within `state`'s rule. 105*37748cd8SNickeau */ 106*37748cd8SNickeau public function nextTokensInContext(ATNState $state, ?RuleContext $context) : IntervalSet 107*37748cd8SNickeau { 108*37748cd8SNickeau return (new LL1Analyzer($this))->look($state, null, $context); 109*37748cd8SNickeau } 110*37748cd8SNickeau 111*37748cd8SNickeau /** 112*37748cd8SNickeau * Compute the set of valid tokens that can occur starting in `state` and 113*37748cd8SNickeau * staying in same rule. {@see Token::EPSILON} is in set if we reach end of 114*37748cd8SNickeau * rule. 115*37748cd8SNickeau */ 116*37748cd8SNickeau public function nextTokens(ATNState $state) : IntervalSet 117*37748cd8SNickeau { 118*37748cd8SNickeau if ($state->nextTokenWithinRule !== null) { 119*37748cd8SNickeau return $state->nextTokenWithinRule; 120*37748cd8SNickeau } 121*37748cd8SNickeau 122*37748cd8SNickeau $state->nextTokenWithinRule = $this->nextTokensInContext($state, null); 123*37748cd8SNickeau $state->nextTokenWithinRule->setReadOnly(true); 124*37748cd8SNickeau 125*37748cd8SNickeau return $state->nextTokenWithinRule; 126*37748cd8SNickeau } 127*37748cd8SNickeau 128*37748cd8SNickeau public function addState(?ATNState $state) : void 129*37748cd8SNickeau { 130*37748cd8SNickeau if ($state === null) { 131*37748cd8SNickeau return; 132*37748cd8SNickeau } 133*37748cd8SNickeau 134*37748cd8SNickeau $state->atn = $this; 135*37748cd8SNickeau $state->stateNumber = \count($this->states); 136*37748cd8SNickeau 137*37748cd8SNickeau $this->states[] = $state; 138*37748cd8SNickeau } 139*37748cd8SNickeau 140*37748cd8SNickeau public function removeState(ATNState $state) : void 141*37748cd8SNickeau { 142*37748cd8SNickeau // just free mem, don't shift states in list 143*37748cd8SNickeau unset($this->states[$state->stateNumber]); 144*37748cd8SNickeau } 145*37748cd8SNickeau 146*37748cd8SNickeau public function defineDecisionState(DecisionState $s) : int 147*37748cd8SNickeau { 148*37748cd8SNickeau $this->decisionToState[] = $s; 149*37748cd8SNickeau 150*37748cd8SNickeau $s->decision = \count($this->decisionToState) - 1; 151*37748cd8SNickeau 152*37748cd8SNickeau return $s->decision; 153*37748cd8SNickeau } 154*37748cd8SNickeau 155*37748cd8SNickeau public function getDecisionState(int $decision) : ?DecisionState 156*37748cd8SNickeau { 157*37748cd8SNickeau if (\count($this->decisionToState) === 0) { 158*37748cd8SNickeau return null; 159*37748cd8SNickeau } 160*37748cd8SNickeau 161*37748cd8SNickeau return $this->decisionToState[$decision]; 162*37748cd8SNickeau } 163*37748cd8SNickeau 164*37748cd8SNickeau public function getNumberOfDecisions() : int 165*37748cd8SNickeau { 166*37748cd8SNickeau return \count($this->decisionToState); 167*37748cd8SNickeau } 168*37748cd8SNickeau 169*37748cd8SNickeau /** 170*37748cd8SNickeau * Computes the set of input symbols which could follow ATN state number 171*37748cd8SNickeau * `stateNumber` in the specified full `context`. This method 172*37748cd8SNickeau * considers the complete parser context, but does not evaluate semantic 173*37748cd8SNickeau * predicates (i.e. all predicates encountered during the calculation are 174*37748cd8SNickeau * assumed true). If a path in the ATN exists from the starting state to the 175*37748cd8SNickeau * {@see RuleStopState} of the outermost context without matching any 176*37748cd8SNickeau * symbols, {@see Token::EOF} is added to the returned set. 177*37748cd8SNickeau * 178*37748cd8SNickeau * If `context` is `null`, it is treated as {@see ParserRuleContext::EMPTY}. 179*37748cd8SNickeau * 180*37748cd8SNickeau * @param int $stateNumber The ATN state number 181*37748cd8SNickeau * @param RuleContext $context The full parse context 182*37748cd8SNickeau * 183*37748cd8SNickeau * @return IntervalSet The set of potentially valid input symbols which could 184*37748cd8SNickeau * follow the specified state in the specified context. 185*37748cd8SNickeau * 186*37748cd8SNickeau * @throws \RuntimeException 187*37748cd8SNickeau */ 188*37748cd8SNickeau public function getExpectedTokens(int $stateNumber, ?RuleContext $context) : IntervalSet 189*37748cd8SNickeau { 190*37748cd8SNickeau if ($stateNumber < 0 || $stateNumber >= \count($this->states)) { 191*37748cd8SNickeau throw new \InvalidArgumentException('Invalid state number.'); 192*37748cd8SNickeau } 193*37748cd8SNickeau 194*37748cd8SNickeau $s = $this->states[$stateNumber]; 195*37748cd8SNickeau $following = $this->nextTokens($s); 196*37748cd8SNickeau 197*37748cd8SNickeau if (!$following->contains(Token::EPSILON)) { 198*37748cd8SNickeau return $following; 199*37748cd8SNickeau } 200*37748cd8SNickeau 201*37748cd8SNickeau $expected = new IntervalSet(); 202*37748cd8SNickeau 203*37748cd8SNickeau $expected->addSet($following); 204*37748cd8SNickeau $expected->removeOne(Token::EPSILON); 205*37748cd8SNickeau 206*37748cd8SNickeau if ($context === null) { 207*37748cd8SNickeau $context = ParserRuleContext::emptyContext(); 208*37748cd8SNickeau } 209*37748cd8SNickeau 210*37748cd8SNickeau while ($context !== null && $context->invokingState >= 0 && $following->contains(Token::EPSILON)) { 211*37748cd8SNickeau $invokingState = $this->states[$context->invokingState]; 212*37748cd8SNickeau $transition = $invokingState->getTransition(0); 213*37748cd8SNickeau 214*37748cd8SNickeau if (!$transition instanceof RuleTransition) { 215*37748cd8SNickeau throw new \RuntimeException('Unexpected transition type.'); 216*37748cd8SNickeau } 217*37748cd8SNickeau 218*37748cd8SNickeau $following = $this->nextTokens($transition->followState); 219*37748cd8SNickeau 220*37748cd8SNickeau $expected->addSet($following); 221*37748cd8SNickeau $expected->removeOne(Token::EPSILON); 222*37748cd8SNickeau 223*37748cd8SNickeau $context = $context->getParent(); 224*37748cd8SNickeau } 225*37748cd8SNickeau 226*37748cd8SNickeau if ($following->contains(Token::EPSILON)) { 227*37748cd8SNickeau $expected->addOne(Token::EOF); 228*37748cd8SNickeau } 229*37748cd8SNickeau 230*37748cd8SNickeau return $expected; 231*37748cd8SNickeau } 232*37748cd8SNickeau} 233