1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\Atn\States;
6
7use Antlr\Antlr4\Runtime\Atn\ATN;
8use Antlr\Antlr4\Runtime\Atn\Transitions\Transition;
9use Antlr\Antlr4\Runtime\Comparison\Hashable;
10use Antlr\Antlr4\Runtime\IntervalSet;
11
12abstract class ATNState implements Hashable
13{
14    public const INVALID_TYPE = 0;
15    public const BASIC = 1;
16    public const RULE_START = 2;
17    public const BLOCK_START = 3;
18    public const PLUS_BLOCK_START = 4;
19    public const STAR_BLOCK_START = 5;
20    public const TOKEN_START = 6;
21    public const RULE_STOP = 7;
22    public const BLOCK_END = 8;
23    public const STAR_LOOP_BACK = 9;
24    public const STAR_LOOP_ENTRY = 10;
25    public const PLUS_LOOP_BACK = 11;
26    public const LOOP_END = 12;
27
28    public const SERIALIZATION_NAMES = [
29        'INVALID',
30        'BASIC',
31        'RULE_START',
32        'BLOCK_START',
33        'PLUS_BLOCK_START',
34        'STAR_BLOCK_START',
35        'TOKEN_START',
36        'RULE_STOP',
37        'BLOCK_END',
38        'STAR_LOOP_BACK',
39        'STAR_LOOP_ENTRY',
40        'PLUS_LOOP_BACK',
41        'LOOP_END',
42    ];
43
44    public const INVALID_STATE_NUMBER = -1;
45
46    /**
47     * Which ATN are we in?
48     *
49     * @var ATN|null
50     */
51    public $atn;
52
53    /** @var int */
54    public $stateNumber = self::INVALID_STATE_NUMBER;
55
56    /**
57     * Initially, at runtime, we don't have Rule objects.
58     *
59     * @var int
60     */
61    public $ruleIndex = 0;
62
63    /** @var bool */
64    public $epsilonOnlyTransitions = false;
65
66    /**
67     * Track the transitions emanating from this ATN state.
68     *
69     * @var array<Transition>
70     */
71    protected $transitions = [];
72
73    /**
74     * Used to cache lookahead during parsing, not used during construction.
75     *
76     * @var IntervalSet|null
77     */
78    public $nextTokenWithinRule;
79
80    public function equals(object $other) : bool
81    {
82        if ($this === $other) {
83            return true;
84        }
85
86        return $other instanceof static
87            && $this->stateNumber === $other->stateNumber;
88    }
89
90    public function isNonGreedyExitState() : bool
91    {
92        return false;
93    }
94
95    /**
96     * @return array<Transition>
97     */
98    public function getTransitions() : array
99    {
100        return $this->transitions;
101    }
102
103    public function getNumberOfTransitions() : int
104    {
105        return \count($this->transitions);
106    }
107
108    public function addTransition(Transition $trans, int $index = -1) : void
109    {
110        if (\count($this->transitions) === 0) {
111            $this->epsilonOnlyTransitions = $trans->isEpsilon();
112        } elseif ($this->epsilonOnlyTransitions !== $trans->isEpsilon()) {
113            $this->epsilonOnlyTransitions = false;
114        }
115
116        if ($index === -1) {
117            $this->transitions[] = $trans;
118        } else {
119            \array_splice($this->transitions, $index, 1, [$trans]);
120        }
121    }
122
123    public function getTransition(int $index) : Transition
124    {
125        return $this->transitions[$index];
126    }
127
128    public function setTransition(Transition $trans, int $index) : void
129    {
130        $this->transitions[$index] = $trans;
131    }
132
133    /**
134     * @param array<Transition> $transitions
135     */
136    public function setTransitions(array $transitions) : void
137    {
138        $this->transitions = $transitions;
139    }
140
141    public function removeTransition(int $index) : void
142    {
143        \array_splice($this->transitions, $index, 1);
144    }
145
146    public function onlyHasEpsilonTransitions() : bool
147    {
148        return $this->epsilonOnlyTransitions;
149    }
150
151    public function setRuleIndex(int $ruleIndex) : void
152    {
153        $this->ruleIndex = $ruleIndex;
154    }
155
156    public function __toString() : string
157    {
158        return (string) $this->stateNumber;
159    }
160
161    public function hashCode() : int
162    {
163        return $this->getStateType();
164    }
165
166    abstract public function getStateType() : int;
167}
168