xref: /plugin/combo/vendor/antlr/antlr4-php-runtime/src/Atn/ATNDeserializer.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
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