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\Actions\LexerActionType; 9*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerChannelAction; 10*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerCustomAction; 11*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerModeAction; 12*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerMoreAction; 13*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerPopModeAction; 14*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerPushModeAction; 15*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerSkipAction; 16*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Actions\LexerTypeAction; 17*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\ATNState; 18*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\BasicBlockStartState; 19*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\BasicState; 20*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\BlockEndState; 21*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\BlockStartState; 22*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\DecisionState; 23*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\LoopEndState; 24*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\PlusBlockStartState; 25*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\PlusLoopbackState; 26*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\RuleStartState; 27*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\RuleStopState; 28*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\StarBlockStartState; 29*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\StarLoopbackState; 30*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\StarLoopEntryState; 31*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\States\TokensStartState; 32*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\ActionTransition; 33*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\AtomTransition; 34*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\EpsilonTransition; 35*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\NotSetTransition; 36*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\PrecedencePredicateTransition; 37*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\PredicateTransition; 38*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\RangeTransition; 39*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\RuleTransition; 40*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\SetTransition; 41*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\Transition; 42*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\Transitions\WildcardTransition; 43*37748cd8SNickeauuse Antlr\Antlr4\Runtime\IntervalSet; 44*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Token; 45*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Utils\StringUtils; 46*37748cd8SNickeau 47*37748cd8SNickeaufinal class ATNDeserializer 48*37748cd8SNickeau{ 49*37748cd8SNickeau /** 50*37748cd8SNickeau * This value should never change. Updates following this version are 51*37748cd8SNickeau * reflected as change in the unique ID SERIALIZED_UUID. 52*37748cd8SNickeau */ 53*37748cd8SNickeau public const SERIALIZED_VERSION = 3; 54*37748cd8SNickeau 55*37748cd8SNickeau /** 56*37748cd8SNickeau * This is the earliest supported serialized UUID. 57*37748cd8SNickeau * Stick to serialized version for now, we don't need a UUID instance. 58*37748cd8SNickeau */ 59*37748cd8SNickeau private const BASE_SERIALIZED_UUID = 'AADB8D7E-AEEF-4415-AD2B-8204D6CF042E'; 60*37748cd8SNickeau 61*37748cd8SNickeau /** 62*37748cd8SNickeau * This UUID indicates the serialized ATN contains two sets of IntervalSets, 63*37748cd8SNickeau * where the second set's values are encoded as 32-bit integers to support 64*37748cd8SNickeau * the full Unicode SMP range up to U+10FFFF. 65*37748cd8SNickeau */ 66*37748cd8SNickeau private const ADDED_UNICODE_SMP = '59627784-3BE5-417A-B9EB-8131A7286089'; 67*37748cd8SNickeau 68*37748cd8SNickeau /** 69*37748cd8SNickeau * This list contains all of the currently supported UUIDs, ordered by when 70*37748cd8SNickeau * the feature first appeared in this branch. 71*37748cd8SNickeau */ 72*37748cd8SNickeau private const SUPPORTED_UUIDS = [ 73*37748cd8SNickeau self::BASE_SERIALIZED_UUID, 74*37748cd8SNickeau self::ADDED_UNICODE_SMP, 75*37748cd8SNickeau ]; 76*37748cd8SNickeau 77*37748cd8SNickeau /** 78*37748cd8SNickeau * This is the current serialized UUID. 79*37748cd8SNickeau */ 80*37748cd8SNickeau private const SERIALIZED_UUID = self::ADDED_UNICODE_SMP; 81*37748cd8SNickeau 82*37748cd8SNickeau /** @var ATNDeserializationOptions */ 83*37748cd8SNickeau private $deserializationOptions; 84*37748cd8SNickeau 85*37748cd8SNickeau /** @var array<int> */ 86*37748cd8SNickeau private $data = []; 87*37748cd8SNickeau 88*37748cd8SNickeau /** @var int */ 89*37748cd8SNickeau private $pos = 0; 90*37748cd8SNickeau 91*37748cd8SNickeau /** @var string */ 92*37748cd8SNickeau private $uuid = ''; 93*37748cd8SNickeau 94*37748cd8SNickeau /** @var array<int, callable|null>|null */ 95*37748cd8SNickeau private $stateFactories; 96*37748cd8SNickeau 97*37748cd8SNickeau /** @var array<int, callable|null>|null */ 98*37748cd8SNickeau private $actionFactories; 99*37748cd8SNickeau 100*37748cd8SNickeau public function __construct(?ATNDeserializationOptions $options = null) 101*37748cd8SNickeau { 102*37748cd8SNickeau $this->deserializationOptions = $options ?? ATNDeserializationOptions::defaultOptions(); 103*37748cd8SNickeau } 104*37748cd8SNickeau 105*37748cd8SNickeau /** 106*37748cd8SNickeau * Determines if a particular serialized representation of an ATN supports 107*37748cd8SNickeau * a particular feature, identified by the {@see UUID} used for serializing 108*37748cd8SNickeau * the ATN at the time the feature was first introduced. 109*37748cd8SNickeau * 110*37748cd8SNickeau * @param string $feature The {@see UUID} marking the first time the 111*37748cd8SNickeau * feature was supported in the serialized ATN. 112*37748cd8SNickeau * @param string $actualUuid The {@see UUID} of the actual serialized ATN 113*37748cd8SNickeau * which is currently being deserialized. 114*37748cd8SNickeau * 115*37748cd8SNickeau * @return bool `true` if the `actualUuid` value represents a serialized 116*37748cd8SNickeau * ATN at or after the feature identified by `feature` was 117*37748cd8SNickeau * introduced; otherwise, `false`. 118*37748cd8SNickeau */ 119*37748cd8SNickeau protected function isFeatureSupported(string $feature, string $actualUuid) : bool 120*37748cd8SNickeau { 121*37748cd8SNickeau $featureIndex = \array_search($feature, self::SUPPORTED_UUIDS, true); 122*37748cd8SNickeau 123*37748cd8SNickeau if ($featureIndex === false) { 124*37748cd8SNickeau return false; 125*37748cd8SNickeau } 126*37748cd8SNickeau 127*37748cd8SNickeau $actualUuidIndex = \array_search($actualUuid, self::SUPPORTED_UUIDS, true); 128*37748cd8SNickeau 129*37748cd8SNickeau return $actualUuidIndex >= $featureIndex; 130*37748cd8SNickeau } 131*37748cd8SNickeau 132*37748cd8SNickeau public function deserialize(string $data) : ATN 133*37748cd8SNickeau { 134*37748cd8SNickeau $this->reset($data); 135*37748cd8SNickeau $this->checkVersion(); 136*37748cd8SNickeau $this->checkUUID(); 137*37748cd8SNickeau $atn = $this->readATN(); 138*37748cd8SNickeau $this->readStates($atn); 139*37748cd8SNickeau $this->readRules($atn); 140*37748cd8SNickeau $this->readModes($atn); 141*37748cd8SNickeau $sets = []; 142*37748cd8SNickeau 143*37748cd8SNickeau // First, deserialize sets with 16-bit arguments <= U+FFFF. 144*37748cd8SNickeau $this->readSets($sets, function () { 145*37748cd8SNickeau return $this->readInt(); 146*37748cd8SNickeau }); 147*37748cd8SNickeau 148*37748cd8SNickeau // Next, if the ATN was serialized with the Unicode SMP feature, 149*37748cd8SNickeau // deserialize sets with 32-bit arguments <= U+10FFFF. 150*37748cd8SNickeau 151*37748cd8SNickeau if ($this->isFeatureSupported(self::ADDED_UNICODE_SMP, $this->uuid)) { 152*37748cd8SNickeau $this->readSets($sets, function () { 153*37748cd8SNickeau return $this->readInt32(); 154*37748cd8SNickeau }); 155*37748cd8SNickeau } 156*37748cd8SNickeau 157*37748cd8SNickeau $this->readEdges($atn, $sets); 158*37748cd8SNickeau $this->readDecisions($atn); 159*37748cd8SNickeau $this->readLexerActions($atn); 160*37748cd8SNickeau $this->markPrecedenceDecisions($atn); 161*37748cd8SNickeau $this->verifyATN($atn); 162*37748cd8SNickeau 163*37748cd8SNickeau if ($atn->grammarType === ATN::ATN_TYPE_PARSER 164*37748cd8SNickeau && $this->deserializationOptions->isGenerateRuleBypassTransitions()) { 165*37748cd8SNickeau $this->generateRuleBypassTransitions($atn); 166*37748cd8SNickeau // re-verify after modification 167*37748cd8SNickeau $this->verifyATN($atn); 168*37748cd8SNickeau } 169*37748cd8SNickeau 170*37748cd8SNickeau return $atn; 171*37748cd8SNickeau } 172*37748cd8SNickeau 173*37748cd8SNickeau private function reset(string $data) : void 174*37748cd8SNickeau { 175*37748cd8SNickeau $characters = \preg_split('//u', $data, -1, \PREG_SPLIT_NO_EMPTY); 176*37748cd8SNickeau 177*37748cd8SNickeau if ($characters === false) { 178*37748cd8SNickeau return; 179*37748cd8SNickeau } 180*37748cd8SNickeau 181*37748cd8SNickeau $this->data = [StringUtils::codePoint($characters[0])]; 182*37748cd8SNickeau for ($i = 1, $length = \count($characters); $i < $length; $i++) { 183*37748cd8SNickeau $code = StringUtils::codePoint($characters[$i]); 184*37748cd8SNickeau $this->data[] = $code > 1 ? $code - 2 : $code + 65533; 185*37748cd8SNickeau } 186*37748cd8SNickeau 187*37748cd8SNickeau $this->pos = 0; 188*37748cd8SNickeau } 189*37748cd8SNickeau 190*37748cd8SNickeau 191*37748cd8SNickeau private function checkVersion() : void 192*37748cd8SNickeau { 193*37748cd8SNickeau $version = $this->readInt(); 194*37748cd8SNickeau 195*37748cd8SNickeau if ($version !== self::SERIALIZED_VERSION) { 196*37748cd8SNickeau throw new \InvalidArgumentException(\sprintf( 197*37748cd8SNickeau 'Could not deserialize ATN with version %d (expected %d).', 198*37748cd8SNickeau $version, 199*37748cd8SNickeau self::SERIALIZED_VERSION 200*37748cd8SNickeau )); 201*37748cd8SNickeau } 202*37748cd8SNickeau } 203*37748cd8SNickeau 204*37748cd8SNickeau private function checkUUID() : void 205*37748cd8SNickeau { 206*37748cd8SNickeau $uuid = $this->readUUID(); 207*37748cd8SNickeau 208*37748cd8SNickeau if (!\in_array($uuid, self::SUPPORTED_UUIDS, true)) { 209*37748cd8SNickeau throw new \InvalidArgumentException(\sprintf( 210*37748cd8SNickeau 'Could not deserialize ATN with UUID: %s (expected %s or a legacy UUID).', 211*37748cd8SNickeau $uuid, 212*37748cd8SNickeau self::SERIALIZED_UUID 213*37748cd8SNickeau )); 214*37748cd8SNickeau } 215*37748cd8SNickeau 216*37748cd8SNickeau $this->uuid = $uuid; 217*37748cd8SNickeau } 218*37748cd8SNickeau 219*37748cd8SNickeau private function readATN() : ATN 220*37748cd8SNickeau { 221*37748cd8SNickeau $grammarType = $this->readInt(); 222*37748cd8SNickeau $maxTokenType = $this->readInt(); 223*37748cd8SNickeau 224*37748cd8SNickeau return new ATN($grammarType, $maxTokenType); 225*37748cd8SNickeau } 226*37748cd8SNickeau 227*37748cd8SNickeau private function readStates(ATN $atn) : void 228*37748cd8SNickeau { 229*37748cd8SNickeau $loopBackStateNumbers = []; 230*37748cd8SNickeau $endStateNumbers = []; 231*37748cd8SNickeau $nstates = $this->readInt(); 232*37748cd8SNickeau 233*37748cd8SNickeau for ($i=0; $i < $nstates; $i++) { 234*37748cd8SNickeau $stype = $this->readInt(); 235*37748cd8SNickeau 236*37748cd8SNickeau // ignore bad type of states 237*37748cd8SNickeau if ($stype === ATNState::INVALID_TYPE) { 238*37748cd8SNickeau $atn->addState(null); 239*37748cd8SNickeau 240*37748cd8SNickeau continue; 241*37748cd8SNickeau } 242*37748cd8SNickeau 243*37748cd8SNickeau $ruleIndex = $this->readInt(); 244*37748cd8SNickeau 245*37748cd8SNickeau if ($ruleIndex === 0xFFFF) { 246*37748cd8SNickeau $ruleIndex = -1; 247*37748cd8SNickeau } 248*37748cd8SNickeau 249*37748cd8SNickeau $s = $this->stateFactory($stype, $ruleIndex); 250*37748cd8SNickeau 251*37748cd8SNickeau if ($stype === ATNState::LOOP_END) { 252*37748cd8SNickeau // special case 253*37748cd8SNickeau $loopBackStateNumber = $this->readInt(); 254*37748cd8SNickeau 255*37748cd8SNickeau if (!$s instanceof LoopEndState) { 256*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 257*37748cd8SNickeau } 258*37748cd8SNickeau 259*37748cd8SNickeau $loopBackStateNumbers[] = [$s, $loopBackStateNumber]; 260*37748cd8SNickeau } elseif ($s instanceof BlockStartState) { 261*37748cd8SNickeau $endStateNumber = $this->readInt(); 262*37748cd8SNickeau 263*37748cd8SNickeau $endStateNumbers[] = [$s, $endStateNumber]; 264*37748cd8SNickeau } 265*37748cd8SNickeau 266*37748cd8SNickeau $atn->addState($s); 267*37748cd8SNickeau } 268*37748cd8SNickeau 269*37748cd8SNickeau // delay the assignment of loop back and end states until we know all the 270*37748cd8SNickeau // state instances have been initialized 271*37748cd8SNickeau foreach ($loopBackStateNumbers as $pair) { 272*37748cd8SNickeau $pair[0]->loopBackState = $atn->states[$pair[1]]; 273*37748cd8SNickeau } 274*37748cd8SNickeau 275*37748cd8SNickeau foreach ($endStateNumbers as $pair) { 276*37748cd8SNickeau $endState = $atn->states[$pair[1]]; 277*37748cd8SNickeau 278*37748cd8SNickeau if (!$endState instanceof BlockEndState) { 279*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 280*37748cd8SNickeau } 281*37748cd8SNickeau 282*37748cd8SNickeau $pair[0]->endState = $endState; 283*37748cd8SNickeau } 284*37748cd8SNickeau 285*37748cd8SNickeau $numNonGreedyStates = $this->readInt(); 286*37748cd8SNickeau 287*37748cd8SNickeau for ($j=0; $j < $numNonGreedyStates; $j++) { 288*37748cd8SNickeau $decisionState = $atn->states[$this->readInt()]; 289*37748cd8SNickeau 290*37748cd8SNickeau if (!$decisionState instanceof DecisionState) { 291*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 292*37748cd8SNickeau } 293*37748cd8SNickeau 294*37748cd8SNickeau $decisionState->nonGreedy = true; 295*37748cd8SNickeau } 296*37748cd8SNickeau 297*37748cd8SNickeau $numPrecedenceStates = $this->readInt(); 298*37748cd8SNickeau 299*37748cd8SNickeau for ($j=0; $j < $numPrecedenceStates; $j++) { 300*37748cd8SNickeau $ruleStartState = $atn->states[$this->readInt()]; 301*37748cd8SNickeau 302*37748cd8SNickeau if (!$ruleStartState instanceof RuleStartState) { 303*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 304*37748cd8SNickeau } 305*37748cd8SNickeau 306*37748cd8SNickeau $ruleStartState->isLeftRecursiveRule = true; 307*37748cd8SNickeau } 308*37748cd8SNickeau } 309*37748cd8SNickeau 310*37748cd8SNickeau private function readRules(ATN $atn) : void 311*37748cd8SNickeau { 312*37748cd8SNickeau $nRules = $this->readInt(); 313*37748cd8SNickeau 314*37748cd8SNickeau $atn->ruleToTokenType = []; 315*37748cd8SNickeau $atn->ruleToStartState = []; 316*37748cd8SNickeau for ($i=0; $i < $nRules; $i++) { 317*37748cd8SNickeau $s = $this->readInt(); 318*37748cd8SNickeau $startState = $atn->states[$s]; 319*37748cd8SNickeau 320*37748cd8SNickeau if (!$startState instanceof RuleStartState) { 321*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 322*37748cd8SNickeau } 323*37748cd8SNickeau 324*37748cd8SNickeau $atn->ruleToStartState[$i] = $startState; 325*37748cd8SNickeau 326*37748cd8SNickeau if ($atn->grammarType === ATN::ATN_TYPE_LEXER) { 327*37748cd8SNickeau $tokenType = $this->readInt(); 328*37748cd8SNickeau 329*37748cd8SNickeau if ($tokenType === 0xFFFF) { 330*37748cd8SNickeau $tokenType = Token::EOF; 331*37748cd8SNickeau } 332*37748cd8SNickeau 333*37748cd8SNickeau $atn->ruleToTokenType[$i] = $tokenType; 334*37748cd8SNickeau } 335*37748cd8SNickeau } 336*37748cd8SNickeau 337*37748cd8SNickeau $atn->ruleToStopState = []; 338*37748cd8SNickeau foreach ($atn->states as $state) { 339*37748cd8SNickeau if (!$state instanceof RuleStopState) { 340*37748cd8SNickeau continue; 341*37748cd8SNickeau } 342*37748cd8SNickeau 343*37748cd8SNickeau $atn->ruleToStopState[$state->ruleIndex] = $state; 344*37748cd8SNickeau $atn->ruleToStartState[$state->ruleIndex]->stopState = $state; 345*37748cd8SNickeau } 346*37748cd8SNickeau } 347*37748cd8SNickeau 348*37748cd8SNickeau private function readModes(ATN $atn) : void 349*37748cd8SNickeau { 350*37748cd8SNickeau $nmodes = $this->readInt(); 351*37748cd8SNickeau 352*37748cd8SNickeau for ($i=0; $i < $nmodes; $i++) { 353*37748cd8SNickeau $tokensStartState = $atn->states[$this->readInt()]; 354*37748cd8SNickeau 355*37748cd8SNickeau if (!$tokensStartState instanceof TokensStartState) { 356*37748cd8SNickeau throw new \RuntimeException('Unexpected ATN State'); 357*37748cd8SNickeau } 358*37748cd8SNickeau 359*37748cd8SNickeau $atn->modeToStartState[] = $tokensStartState; 360*37748cd8SNickeau } 361*37748cd8SNickeau } 362*37748cd8SNickeau 363*37748cd8SNickeau /** 364*37748cd8SNickeau * @param array<IntervalSet> $sets 365*37748cd8SNickeau */ 366*37748cd8SNickeau private function readSets(array &$sets, callable $readUnicode) : void 367*37748cd8SNickeau { 368*37748cd8SNickeau $m = $this->readInt(); 369*37748cd8SNickeau 370*37748cd8SNickeau for ($i=0; $i < $m; $i++) { 371*37748cd8SNickeau $iset = new IntervalSet(); 372*37748cd8SNickeau 373*37748cd8SNickeau $sets[] = $iset; 374*37748cd8SNickeau $n = $this->readInt(); 375*37748cd8SNickeau $containsEof = $this->readInt(); 376*37748cd8SNickeau 377*37748cd8SNickeau if ($containsEof !== 0) { 378*37748cd8SNickeau $iset->addOne(-1); 379*37748cd8SNickeau } 380*37748cd8SNickeau 381*37748cd8SNickeau for ($j=0; $j < $n; $j++) { 382*37748cd8SNickeau $i1 = $readUnicode(); 383*37748cd8SNickeau $i2 = $readUnicode(); 384*37748cd8SNickeau $iset->addRange($i1, $i2); 385*37748cd8SNickeau } 386*37748cd8SNickeau } 387*37748cd8SNickeau } 388*37748cd8SNickeau 389*37748cd8SNickeau /** 390*37748cd8SNickeau * @param array<IntervalSet> $sets 391*37748cd8SNickeau */ 392*37748cd8SNickeau private function readEdges(ATN $atn, array &$sets) : void 393*37748cd8SNickeau { 394*37748cd8SNickeau $nEdges = $this->readInt(); 395*37748cd8SNickeau 396*37748cd8SNickeau for ($i=0; $i < $nEdges; $i++) { 397*37748cd8SNickeau $src = $this->readInt(); 398*37748cd8SNickeau $trg = $this->readInt(); 399*37748cd8SNickeau $ttype = $this->readInt(); 400*37748cd8SNickeau $arg1 = $this->readInt(); 401*37748cd8SNickeau $arg2 = $this->readInt(); 402*37748cd8SNickeau $arg3 = $this->readInt(); 403*37748cd8SNickeau $trans = $this->edgeFactory($atn, $ttype, $src, $trg, $arg1, $arg2, $arg3, $sets); 404*37748cd8SNickeau $srcState = $atn->states[$src]; 405*37748cd8SNickeau $srcState->addTransition($trans); 406*37748cd8SNickeau } 407*37748cd8SNickeau 408*37748cd8SNickeau // edges for rule stop states can be derived, so they aren't serialized 409*37748cd8SNickeau foreach ($atn->states as $state) { 410*37748cd8SNickeau foreach ($state->getTransitions() as $t) { 411*37748cd8SNickeau if (!$t instanceof RuleTransition) { 412*37748cd8SNickeau continue; 413*37748cd8SNickeau } 414*37748cd8SNickeau 415*37748cd8SNickeau $outermostPrecedenceReturn = -1; 416*37748cd8SNickeau if ($atn->ruleToStartState[$t->target->ruleIndex]->isLeftRecursiveRule) { 417*37748cd8SNickeau if ($t->precedence === 0) { 418*37748cd8SNickeau $outermostPrecedenceReturn = $t->target->ruleIndex; 419*37748cd8SNickeau } 420*37748cd8SNickeau } 421*37748cd8SNickeau 422*37748cd8SNickeau $trans = new EpsilonTransition($t->followState, $outermostPrecedenceReturn); 423*37748cd8SNickeau $atn->ruleToStopState[$t->target->ruleIndex]->addTransition($trans); 424*37748cd8SNickeau } 425*37748cd8SNickeau } 426*37748cd8SNickeau 427*37748cd8SNickeau foreach ($atn->states as $state) { 428*37748cd8SNickeau if ($state instanceof BlockStartState) { 429*37748cd8SNickeau // we need to know the end state to set its start state 430*37748cd8SNickeau if ($state->endState === null) { 431*37748cd8SNickeau throw new \RuntimeException('Unexpected null EndState.'); 432*37748cd8SNickeau } 433*37748cd8SNickeau 434*37748cd8SNickeau // block end states can only be associated to a single block start state 435*37748cd8SNickeau if ($state->endState->startState !== null) { 436*37748cd8SNickeau throw new \RuntimeException('Unexpected null StartState.'); 437*37748cd8SNickeau } 438*37748cd8SNickeau 439*37748cd8SNickeau $state->endState->startState = $state; 440*37748cd8SNickeau } 441*37748cd8SNickeau 442*37748cd8SNickeau if ($state instanceof PlusLoopbackState) { 443*37748cd8SNickeau foreach ($state->getTransitions() as $t) { 444*37748cd8SNickeau $target = $t->target; 445*37748cd8SNickeau 446*37748cd8SNickeau if ($target instanceof PlusBlockStartState) { 447*37748cd8SNickeau $target->loopBackState = $state; 448*37748cd8SNickeau } 449*37748cd8SNickeau } 450*37748cd8SNickeau } elseif ($state instanceof StarLoopbackState) { 451*37748cd8SNickeau foreach ($state->getTransitions() as $t) { 452*37748cd8SNickeau $target = $t->target; 453*37748cd8SNickeau 454*37748cd8SNickeau if ($target instanceof StarLoopEntryState) { 455*37748cd8SNickeau $target->loopBackState = $state; 456*37748cd8SNickeau } 457*37748cd8SNickeau } 458*37748cd8SNickeau } 459*37748cd8SNickeau } 460*37748cd8SNickeau } 461*37748cd8SNickeau 462*37748cd8SNickeau private function readDecisions(ATN $atn) : void 463*37748cd8SNickeau { 464*37748cd8SNickeau $decisions = $this->readInt(); 465*37748cd8SNickeau 466*37748cd8SNickeau for ($i = 0; $i < $decisions; $i++) { 467*37748cd8SNickeau $s = $this->readInt(); 468*37748cd8SNickeau /** @var DecisionState $decState */ 469*37748cd8SNickeau $decState = $atn->states[$s]; 470*37748cd8SNickeau 471*37748cd8SNickeau $atn->decisionToState[] = $decState; 472*37748cd8SNickeau 473*37748cd8SNickeau $decState->decision = $i; 474*37748cd8SNickeau } 475*37748cd8SNickeau } 476*37748cd8SNickeau 477*37748cd8SNickeau private function readLexerActions(ATN $atn) : void 478*37748cd8SNickeau { 479*37748cd8SNickeau if ($atn->grammarType === ATN::ATN_TYPE_LEXER) { 480*37748cd8SNickeau $count = $this->readInt(); 481*37748cd8SNickeau 482*37748cd8SNickeau $atn->lexerActions = []; 483*37748cd8SNickeau for ($i = 0; $i < $count; $i++) { 484*37748cd8SNickeau $actionType = $this->readInt(); 485*37748cd8SNickeau $data1 = $this->readInt(); 486*37748cd8SNickeau 487*37748cd8SNickeau if ($data1 === 0xFFFF) { 488*37748cd8SNickeau $data1 = -1; 489*37748cd8SNickeau } 490*37748cd8SNickeau 491*37748cd8SNickeau $data2 = $this->readInt(); 492*37748cd8SNickeau 493*37748cd8SNickeau if ($data2 === 0xFFFF) { 494*37748cd8SNickeau $data2 = -1; 495*37748cd8SNickeau } 496*37748cd8SNickeau 497*37748cd8SNickeau $lexerAction = $this->lexerActionFactory($actionType, $data1, $data2); 498*37748cd8SNickeau $atn->lexerActions[$i] = $lexerAction; 499*37748cd8SNickeau } 500*37748cd8SNickeau } 501*37748cd8SNickeau } 502*37748cd8SNickeau 503*37748cd8SNickeau private function generateRuleBypassTransitions(ATN $atn) : void 504*37748cd8SNickeau { 505*37748cd8SNickeau $count = \count($atn->ruleToStartState); 506*37748cd8SNickeau 507*37748cd8SNickeau for ($i = 0; $i < $count; $i++) { 508*37748cd8SNickeau $atn->ruleToTokenType[$i] = $atn->maxTokenType + $i + 1; 509*37748cd8SNickeau } 510*37748cd8SNickeau 511*37748cd8SNickeau for ($i = 0; $i < $count; $i++) { 512*37748cd8SNickeau $this->generateRuleBypassTransition($atn, $i); 513*37748cd8SNickeau } 514*37748cd8SNickeau } 515*37748cd8SNickeau 516*37748cd8SNickeau private function generateRuleBypassTransition(ATN $atn, int $idx) : void 517*37748cd8SNickeau { 518*37748cd8SNickeau $bypassStart = new BasicBlockStartState(); 519*37748cd8SNickeau $bypassStart->ruleIndex = $idx; 520*37748cd8SNickeau $atn->addState($bypassStart); 521*37748cd8SNickeau 522*37748cd8SNickeau $bypassStop = new BlockEndState(); 523*37748cd8SNickeau $bypassStop->ruleIndex = $idx; 524*37748cd8SNickeau $atn->addState($bypassStop); 525*37748cd8SNickeau 526*37748cd8SNickeau $bypassStart->endState = $bypassStop; 527*37748cd8SNickeau $atn->defineDecisionState($bypassStart); 528*37748cd8SNickeau 529*37748cd8SNickeau $bypassStop->startState = $bypassStart; 530*37748cd8SNickeau 531*37748cd8SNickeau $excludeTransition = null; 532*37748cd8SNickeau if ($atn->ruleToStartState[$idx]->isLeftRecursiveRule) { 533*37748cd8SNickeau // wrap from the beginning of the rule to the StarLoopEntryState 534*37748cd8SNickeau $endState = null; 535*37748cd8SNickeau 536*37748cd8SNickeau foreach ($atn->states as $state) { 537*37748cd8SNickeau if ($this->stateIsEndStateFor($state, $idx)) { 538*37748cd8SNickeau $endState = $state; 539*37748cd8SNickeau 540*37748cd8SNickeau if (!$state instanceof LoopEndState) { 541*37748cd8SNickeau throw new \RuntimeException('Unexpected state type.'); 542*37748cd8SNickeau } 543*37748cd8SNickeau 544*37748cd8SNickeau if ($state->loopBackState === null) { 545*37748cd8SNickeau throw new \RuntimeException('Unexpected null loop back state.'); 546*37748cd8SNickeau } 547*37748cd8SNickeau 548*37748cd8SNickeau $excludeTransition = $state->loopBackState->getTransition(0); 549*37748cd8SNickeau 550*37748cd8SNickeau break; 551*37748cd8SNickeau } 552*37748cd8SNickeau } 553*37748cd8SNickeau 554*37748cd8SNickeau if ($excludeTransition === null) { 555*37748cd8SNickeau throw new \RuntimeException('Couldn\'t identify final state of the precedence rule prefix section.'); 556*37748cd8SNickeau } 557*37748cd8SNickeau } else { 558*37748cd8SNickeau $endState = $atn->ruleToStopState[$idx]; 559*37748cd8SNickeau } 560*37748cd8SNickeau 561*37748cd8SNickeau // all non-excluded transitions that currently target end state need to target blockEnd instead 562*37748cd8SNickeau // TODO:looks like a bug 563*37748cd8SNickeau foreach ($atn->states as $state) { 564*37748cd8SNickeau foreach ($state->getTransitions() as $transition) { 565*37748cd8SNickeau if ($excludeTransition !== null && $transition->equals($excludeTransition)) { 566*37748cd8SNickeau continue; 567*37748cd8SNickeau } 568*37748cd8SNickeau 569*37748cd8SNickeau if ($endState !== null && $transition->target->equals($endState)) { 570*37748cd8SNickeau $transition->target = $bypassStop; 571*37748cd8SNickeau } 572*37748cd8SNickeau } 573*37748cd8SNickeau } 574*37748cd8SNickeau 575*37748cd8SNickeau // all transitions leaving the rule start state need to leave blockStart instead 576*37748cd8SNickeau $ruleToStartState = $atn->ruleToStartState[$idx]; 577*37748cd8SNickeau $count = $ruleToStartState->getNumberOfTransitions(); 578*37748cd8SNickeau 579*37748cd8SNickeau while ($count > 0) { 580*37748cd8SNickeau $bypassStart->addTransition($ruleToStartState->getTransition($count-1)); 581*37748cd8SNickeau $ruleToStartState->setTransitions(\array_slice($ruleToStartState->getTransitions(), -1)); 582*37748cd8SNickeau } 583*37748cd8SNickeau 584*37748cd8SNickeau // link the new states 585*37748cd8SNickeau $atn->ruleToStartState[$idx]->addTransition(new EpsilonTransition($bypassStart)); 586*37748cd8SNickeau 587*37748cd8SNickeau if ($endState === null) { 588*37748cd8SNickeau throw new \RuntimeException('Unexpected null end state.'); 589*37748cd8SNickeau } 590*37748cd8SNickeau 591*37748cd8SNickeau $bypassStop->addTransition(new EpsilonTransition($endState)); 592*37748cd8SNickeau 593*37748cd8SNickeau $matchState = new BasicState(); 594*37748cd8SNickeau $atn->addState($matchState); 595*37748cd8SNickeau $matchState->addTransition(new AtomTransition($bypassStop, $atn->ruleToTokenType[$idx] ?? 0)); 596*37748cd8SNickeau $bypassStart->addTransition(new EpsilonTransition($matchState)); 597*37748cd8SNickeau } 598*37748cd8SNickeau 599*37748cd8SNickeau private function stateIsEndStateFor(ATNState $state, int $idx) : ?ATNState 600*37748cd8SNickeau { 601*37748cd8SNickeau if ($state->ruleIndex !== $idx) { 602*37748cd8SNickeau return null; 603*37748cd8SNickeau } 604*37748cd8SNickeau 605*37748cd8SNickeau if (!$state instanceof StarLoopEntryState) { 606*37748cd8SNickeau return null; 607*37748cd8SNickeau } 608*37748cd8SNickeau 609*37748cd8SNickeau $maybeLoopEndState = $state->getTransition($state->getNumberOfTransitions() - 1)->target; 610*37748cd8SNickeau 611*37748cd8SNickeau if (!$maybeLoopEndState instanceof LoopEndState) { 612*37748cd8SNickeau return null; 613*37748cd8SNickeau } 614*37748cd8SNickeau 615*37748cd8SNickeau if ($maybeLoopEndState->epsilonOnlyTransitions 616*37748cd8SNickeau && $maybeLoopEndState->getTransition(0)->target instanceof RuleStopState) { 617*37748cd8SNickeau return $state; 618*37748cd8SNickeau } 619*37748cd8SNickeau 620*37748cd8SNickeau return null; 621*37748cd8SNickeau } 622*37748cd8SNickeau 623*37748cd8SNickeau /** 624*37748cd8SNickeau * Analyze the {@see StarLoopEntryState} states in the specified ATN to set 625*37748cd8SNickeau * the {@see StarLoopEntryState::$isPrecedenceDecision} field to the correct 626*37748cd8SNickeau * value. 627*37748cd8SNickeau * 628*37748cd8SNickeau * @param ATN $atn The ATN. 629*37748cd8SNickeau */ 630*37748cd8SNickeau private function markPrecedenceDecisions(ATN $atn) : void 631*37748cd8SNickeau { 632*37748cd8SNickeau foreach ($atn->states as $state) { 633*37748cd8SNickeau if (!$state instanceof StarLoopEntryState) { 634*37748cd8SNickeau continue; 635*37748cd8SNickeau } 636*37748cd8SNickeau 637*37748cd8SNickeau // We analyze the ATN to determine if this ATN decision state is the 638*37748cd8SNickeau // decision for the closure block that determines whether a 639*37748cd8SNickeau // precedence rule should continue or complete. 640*37748cd8SNickeau if ($atn->ruleToStartState[$state->ruleIndex]->isLeftRecursiveRule) { 641*37748cd8SNickeau $maybeLoopEndState = $state->getTransition($state->getNumberOfTransitions() - 1)->target; 642*37748cd8SNickeau 643*37748cd8SNickeau if ($maybeLoopEndState instanceof LoopEndState) { 644*37748cd8SNickeau if ($maybeLoopEndState->epsilonOnlyTransitions 645*37748cd8SNickeau && $maybeLoopEndState->getTransition(0)->target instanceof RuleStopState) { 646*37748cd8SNickeau $state->isPrecedenceDecision = true; 647*37748cd8SNickeau } 648*37748cd8SNickeau } 649*37748cd8SNickeau } 650*37748cd8SNickeau } 651*37748cd8SNickeau } 652*37748cd8SNickeau 653*37748cd8SNickeau private function verifyATN(ATN $atn) : void 654*37748cd8SNickeau { 655*37748cd8SNickeau if (!$this->deserializationOptions->isVerifyATN()) { 656*37748cd8SNickeau return; 657*37748cd8SNickeau } 658*37748cd8SNickeau 659*37748cd8SNickeau // verify assumptions 660*37748cd8SNickeau foreach ($atn->states as $state) { 661*37748cd8SNickeau $this->checkCondition($state->epsilonOnlyTransitions || $state->getNumberOfTransitions() <= 1); 662*37748cd8SNickeau 663*37748cd8SNickeau switch (true) { 664*37748cd8SNickeau case $state instanceof PlusBlockStartState: 665*37748cd8SNickeau $this->checkCondition($state->loopBackState !== null); 666*37748cd8SNickeau 667*37748cd8SNickeau break; 668*37748cd8SNickeau 669*37748cd8SNickeau case $state instanceof StarLoopEntryState: 670*37748cd8SNickeau $this->checkCondition($state->loopBackState !== null); 671*37748cd8SNickeau $this->checkCondition($state->getNumberOfTransitions() === 2); 672*37748cd8SNickeau 673*37748cd8SNickeau if ($state->getTransition(0)->target instanceof StarBlockStartState) { 674*37748cd8SNickeau $this->checkCondition($state->getTransition(1)->target instanceof LoopEndState); 675*37748cd8SNickeau $this->checkCondition(!$state->nonGreedy); 676*37748cd8SNickeau } elseif ($state->getTransition(0)->target instanceof LoopEndState) { 677*37748cd8SNickeau $this->checkCondition($state->getTransition(1)->target instanceof StarBlockStartState); 678*37748cd8SNickeau $this->checkCondition($state->nonGreedy); 679*37748cd8SNickeau } else { 680*37748cd8SNickeau throw new \InvalidArgumentException('IllegalState'); 681*37748cd8SNickeau } 682*37748cd8SNickeau 683*37748cd8SNickeau break; 684*37748cd8SNickeau 685*37748cd8SNickeau case $state instanceof StarLoopbackState: 686*37748cd8SNickeau $this->checkCondition($state->getNumberOfTransitions() === 1); 687*37748cd8SNickeau $this->checkCondition($state->getTransition(0)->target instanceof StarLoopEntryState); 688*37748cd8SNickeau 689*37748cd8SNickeau break; 690*37748cd8SNickeau 691*37748cd8SNickeau case $state instanceof LoopEndState: 692*37748cd8SNickeau $this->checkCondition($state->loopBackState !== null); 693*37748cd8SNickeau 694*37748cd8SNickeau break; 695*37748cd8SNickeau 696*37748cd8SNickeau case $state instanceof RuleStartState: 697*37748cd8SNickeau $this->checkCondition($state->stopState !== null); 698*37748cd8SNickeau 699*37748cd8SNickeau break; 700*37748cd8SNickeau 701*37748cd8SNickeau case $state instanceof BlockStartState: 702*37748cd8SNickeau $this->checkCondition($state->endState !== null); 703*37748cd8SNickeau 704*37748cd8SNickeau break; 705*37748cd8SNickeau 706*37748cd8SNickeau case $state instanceof BlockEndState: 707*37748cd8SNickeau $this->checkCondition($state->startState !== null); 708*37748cd8SNickeau 709*37748cd8SNickeau break; 710*37748cd8SNickeau 711*37748cd8SNickeau case $state instanceof DecisionState: 712*37748cd8SNickeau $this->checkCondition($state->getNumberOfTransitions() <= 1 || $state->decision >= 0); 713*37748cd8SNickeau 714*37748cd8SNickeau break; 715*37748cd8SNickeau 716*37748cd8SNickeau default: 717*37748cd8SNickeau $this->checkCondition($state->getNumberOfTransitions() <= 1 || $state instanceof RuleStopState); 718*37748cd8SNickeau } 719*37748cd8SNickeau } 720*37748cd8SNickeau } 721*37748cd8SNickeau 722*37748cd8SNickeau private function checkCondition(?bool $condition, $message = 'IllegalState') : void 723*37748cd8SNickeau { 724*37748cd8SNickeau if ($condition === null) { 725*37748cd8SNickeau throw new \InvalidArgumentException($message); 726*37748cd8SNickeau } 727*37748cd8SNickeau } 728*37748cd8SNickeau 729*37748cd8SNickeau private function readInt() : int 730*37748cd8SNickeau { 731*37748cd8SNickeau return $this->data[$this->pos++]; 732*37748cd8SNickeau } 733*37748cd8SNickeau 734*37748cd8SNickeau private function readInt32() : int 735*37748cd8SNickeau { 736*37748cd8SNickeau $low = $this->readInt(); 737*37748cd8SNickeau $high = $this->readInt(); 738*37748cd8SNickeau 739*37748cd8SNickeau return $low | ($high << 16); 740*37748cd8SNickeau } 741*37748cd8SNickeau 742*37748cd8SNickeau private function readUUID() : string 743*37748cd8SNickeau { 744*37748cd8SNickeau $bb = []; 745*37748cd8SNickeau for ($i=0; $i < 8; $i++) { 746*37748cd8SNickeau $int = $this->readInt(); 747*37748cd8SNickeau $bb[] = $int & 0xFF; 748*37748cd8SNickeau $bb[] = ($int >> 8) & 0xFF; 749*37748cd8SNickeau } 750*37748cd8SNickeau 751*37748cd8SNickeau $bb = \array_reverse($bb); 752*37748cd8SNickeau $hex = \strtoupper(\bin2hex(\implode(\array_map('chr', $bb)))); 753*37748cd8SNickeau 754*37748cd8SNickeau return \vsprintf('%s%s-%s-%s-%s-%s%s%s', \str_split($hex, 4)); 755*37748cd8SNickeau } 756*37748cd8SNickeau 757*37748cd8SNickeau /** 758*37748cd8SNickeau * @param array<IntervalSet> $sets 759*37748cd8SNickeau */ 760*37748cd8SNickeau private function edgeFactory( 761*37748cd8SNickeau ATN $atn, 762*37748cd8SNickeau int $type, 763*37748cd8SNickeau int $src, 764*37748cd8SNickeau int $trg, 765*37748cd8SNickeau int $arg1, 766*37748cd8SNickeau int $arg2, 767*37748cd8SNickeau int $arg3, 768*37748cd8SNickeau array $sets 769*37748cd8SNickeau ) : Transition { 770*37748cd8SNickeau $target = $atn->states[$trg]; 771*37748cd8SNickeau 772*37748cd8SNickeau switch ($type) { 773*37748cd8SNickeau case Transition::EPSILON: 774*37748cd8SNickeau return new EpsilonTransition($target); 775*37748cd8SNickeau 776*37748cd8SNickeau case Transition::RANGE: 777*37748cd8SNickeau return $arg3 !== 0 ? 778*37748cd8SNickeau new RangeTransition($target, Token::EOF, $arg2) : 779*37748cd8SNickeau new RangeTransition($target, $arg1, $arg2); 780*37748cd8SNickeau 781*37748cd8SNickeau case Transition::RULE: 782*37748cd8SNickeau $ruleStart = $atn->states[$arg1]; 783*37748cd8SNickeau 784*37748cd8SNickeau if (!$ruleStart instanceof RuleStartState) { 785*37748cd8SNickeau throw new \RuntimeException('Unexpected transition type.'); 786*37748cd8SNickeau } 787*37748cd8SNickeau 788*37748cd8SNickeau return new RuleTransition($ruleStart, $arg2, $arg3, $target); 789*37748cd8SNickeau 790*37748cd8SNickeau case Transition::PREDICATE: 791*37748cd8SNickeau return new PredicateTransition($target, $arg1, $arg2, $arg3 !== 0); 792*37748cd8SNickeau 793*37748cd8SNickeau case Transition::PRECEDENCE: 794*37748cd8SNickeau return new PrecedencePredicateTransition($target, $arg1); 795*37748cd8SNickeau 796*37748cd8SNickeau case Transition::ATOM: 797*37748cd8SNickeau return $arg3 !== 0 ? new AtomTransition($target, Token::EOF) : new AtomTransition($target, $arg1); 798*37748cd8SNickeau 799*37748cd8SNickeau case Transition::ACTION: 800*37748cd8SNickeau return new ActionTransition($target, $arg1, $arg2, $arg3 !== 0); 801*37748cd8SNickeau 802*37748cd8SNickeau case Transition::SET: 803*37748cd8SNickeau return new SetTransition($target, $sets[$arg1]); 804*37748cd8SNickeau 805*37748cd8SNickeau case Transition::NOT_SET: 806*37748cd8SNickeau return new NotSetTransition($target, $sets[$arg1]); 807*37748cd8SNickeau 808*37748cd8SNickeau case Transition::WILDCARD: 809*37748cd8SNickeau return new WildcardTransition($target); 810*37748cd8SNickeau 811*37748cd8SNickeau default: 812*37748cd8SNickeau throw new \InvalidArgumentException(\sprintf( 813*37748cd8SNickeau 'The specified transition type: %d is not valid.', 814*37748cd8SNickeau $type 815*37748cd8SNickeau )); 816*37748cd8SNickeau } 817*37748cd8SNickeau } 818*37748cd8SNickeau 819*37748cd8SNickeau private function stateFactory(int $type, int $ruleIndex) : ?ATNState 820*37748cd8SNickeau { 821*37748cd8SNickeau switch ($type) { 822*37748cd8SNickeau case ATNState::INVALID_TYPE: 823*37748cd8SNickeau return null; 824*37748cd8SNickeau 825*37748cd8SNickeau case ATNState::BASIC: 826*37748cd8SNickeau $s = new BasicState(); 827*37748cd8SNickeau 828*37748cd8SNickeau break; 829*37748cd8SNickeau 830*37748cd8SNickeau case ATNState::RULE_START: 831*37748cd8SNickeau $s = new RuleStartState(); 832*37748cd8SNickeau 833*37748cd8SNickeau break; 834*37748cd8SNickeau 835*37748cd8SNickeau case ATNState::BLOCK_START: 836*37748cd8SNickeau $s = new BasicBlockStartState(); 837*37748cd8SNickeau 838*37748cd8SNickeau break; 839*37748cd8SNickeau 840*37748cd8SNickeau case ATNState::PLUS_BLOCK_START: 841*37748cd8SNickeau $s = new PlusBlockStartState(); 842*37748cd8SNickeau 843*37748cd8SNickeau break; 844*37748cd8SNickeau 845*37748cd8SNickeau case ATNState::STAR_BLOCK_START: 846*37748cd8SNickeau $s = new StarBlockStartState(); 847*37748cd8SNickeau 848*37748cd8SNickeau break; 849*37748cd8SNickeau 850*37748cd8SNickeau case ATNState::TOKEN_START: 851*37748cd8SNickeau $s = new TokensStartState(); 852*37748cd8SNickeau 853*37748cd8SNickeau break; 854*37748cd8SNickeau 855*37748cd8SNickeau case ATNState::RULE_STOP: 856*37748cd8SNickeau $s = new RuleStopState(); 857*37748cd8SNickeau 858*37748cd8SNickeau break; 859*37748cd8SNickeau 860*37748cd8SNickeau case ATNState::BLOCK_END: 861*37748cd8SNickeau $s = new BlockEndState(); 862*37748cd8SNickeau 863*37748cd8SNickeau break; 864*37748cd8SNickeau 865*37748cd8SNickeau case ATNState::STAR_LOOP_BACK: 866*37748cd8SNickeau $s = new StarLoopbackState(); 867*37748cd8SNickeau 868*37748cd8SNickeau break; 869*37748cd8SNickeau 870*37748cd8SNickeau case ATNState::STAR_LOOP_ENTRY: 871*37748cd8SNickeau $s = new StarLoopEntryState(); 872*37748cd8SNickeau 873*37748cd8SNickeau break; 874*37748cd8SNickeau 875*37748cd8SNickeau case ATNState::PLUS_LOOP_BACK: 876*37748cd8SNickeau $s = new PlusLoopbackState(); 877*37748cd8SNickeau 878*37748cd8SNickeau break; 879*37748cd8SNickeau 880*37748cd8SNickeau case ATNState::LOOP_END: 881*37748cd8SNickeau $s = new LoopEndState(); 882*37748cd8SNickeau 883*37748cd8SNickeau break; 884*37748cd8SNickeau 885*37748cd8SNickeau default: 886*37748cd8SNickeau throw new \InvalidArgumentException(\sprintf( 887*37748cd8SNickeau 'The specified state type %d is not valid.', 888*37748cd8SNickeau $type 889*37748cd8SNickeau )); 890*37748cd8SNickeau } 891*37748cd8SNickeau 892*37748cd8SNickeau $s->ruleIndex = $ruleIndex; 893*37748cd8SNickeau 894*37748cd8SNickeau return $s; 895*37748cd8SNickeau } 896*37748cd8SNickeau 897*37748cd8SNickeau private function lexerActionFactory(int $type, int $data1, int $data2) : LexerAction 898*37748cd8SNickeau { 899*37748cd8SNickeau switch ($type) { 900*37748cd8SNickeau case LexerActionType::CHANNEL: 901*37748cd8SNickeau return new LexerChannelAction($data1); 902*37748cd8SNickeau 903*37748cd8SNickeau case LexerActionType::CUSTOM: 904*37748cd8SNickeau return new LexerCustomAction($data1, $data2); 905*37748cd8SNickeau 906*37748cd8SNickeau case LexerActionType::MODE: 907*37748cd8SNickeau return new LexerModeAction($data1); 908*37748cd8SNickeau 909*37748cd8SNickeau case LexerActionType::MORE: 910*37748cd8SNickeau return LexerMoreAction::instance(); 911*37748cd8SNickeau 912*37748cd8SNickeau case LexerActionType::POP_MODE: 913*37748cd8SNickeau return LexerPopModeAction::instance(); 914*37748cd8SNickeau 915*37748cd8SNickeau case LexerActionType::PUSH_MODE: 916*37748cd8SNickeau return new LexerPushModeAction($data1); 917*37748cd8SNickeau 918*37748cd8SNickeau case LexerActionType::SKIP: 919*37748cd8SNickeau return LexerSkipAction::instance(); 920*37748cd8SNickeau 921*37748cd8SNickeau case LexerActionType::TYPE: 922*37748cd8SNickeau return new LexerTypeAction($data1); 923*37748cd8SNickeau 924*37748cd8SNickeau default: 925*37748cd8SNickeau throw new \InvalidArgumentException(\sprintf( 926*37748cd8SNickeau 'The specified lexer action type %d is not valid.', 927*37748cd8SNickeau $type 928*37748cd8SNickeau )); 929*37748cd8SNickeau } 930*37748cd8SNickeau } 931*37748cd8SNickeau} 932