xref: /plugin/combo/vendor/antlr/antlr4-php-runtime/src/Recognizer.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1*37748cd8SNickeau<?php
2*37748cd8SNickeau
3*37748cd8SNickeaudeclare(strict_types=1);
4*37748cd8SNickeau
5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime;
6*37748cd8SNickeau
7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\ATN;
8*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Atn\ATNSimulator;
9*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Error\Exceptions\RecognitionException;
10*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Error\Listeners\ANTLRErrorListener;
11*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Error\Listeners\ProxyErrorListener;
12*37748cd8SNickeau
13*37748cd8SNickeauabstract class Recognizer
14*37748cd8SNickeau{
15*37748cd8SNickeau    public const EOF = -1;
16*37748cd8SNickeau
17*37748cd8SNickeau    /** @var array<string> */
18*37748cd8SNickeau    public $log = [];
19*37748cd8SNickeau
20*37748cd8SNickeau    /** @var array<string, array<string, int>> */
21*37748cd8SNickeau    private static $tokenTypeMapCache = [];
22*37748cd8SNickeau
23*37748cd8SNickeau    /** @var array<string, array<int, string>> */
24*37748cd8SNickeau    private static $ruleIndexMapCache = [];
25*37748cd8SNickeau
26*37748cd8SNickeau    /** @var array<ANTLRErrorListener> */
27*37748cd8SNickeau    private $listeners;
28*37748cd8SNickeau
29*37748cd8SNickeau    /** @var ATNSimulator|null */
30*37748cd8SNickeau    protected $interp;
31*37748cd8SNickeau
32*37748cd8SNickeau    /** @var int */
33*37748cd8SNickeau    private $stateNumber = -1;
34*37748cd8SNickeau
35*37748cd8SNickeau    public function __construct()
36*37748cd8SNickeau    {
37*37748cd8SNickeau        $this->listeners = [];
38*37748cd8SNickeau    }
39*37748cd8SNickeau
40*37748cd8SNickeau    /**
41*37748cd8SNickeau     * Get the vocabulary used by the recognizer.
42*37748cd8SNickeau     *
43*37748cd8SNickeau     * @return Vocabulary A {@see Vocabulary} instance providing information
44*37748cd8SNickeau     *                    about the vocabulary used by the grammar.
45*37748cd8SNickeau     */
46*37748cd8SNickeau    abstract public function getVocabulary() : Vocabulary;
47*37748cd8SNickeau
48*37748cd8SNickeau    /**
49*37748cd8SNickeau     * Get a map from token names to token types.
50*37748cd8SNickeau     *
51*37748cd8SNickeau     * Used for XPath and tree pattern compilation.
52*37748cd8SNickeau     *
53*37748cd8SNickeau     * @return array<string, int>
54*37748cd8SNickeau     */
55*37748cd8SNickeau    public function getTokenTypeMap() : array
56*37748cd8SNickeau    {
57*37748cd8SNickeau        $vocabulary = $this->getVocabulary();
58*37748cd8SNickeau
59*37748cd8SNickeau        $key = \spl_object_hash($vocabulary);
60*37748cd8SNickeau        $result = self::$tokenTypeMapCache[$key] ?? null;
61*37748cd8SNickeau
62*37748cd8SNickeau        if ($result === null) {
63*37748cd8SNickeau            $result = [];
64*37748cd8SNickeau
65*37748cd8SNickeau            for ($i = 0; $i <= $this->getATN()->maxTokenType; $i++) {
66*37748cd8SNickeau                $literalName = $vocabulary->getLiteralName($i);
67*37748cd8SNickeau
68*37748cd8SNickeau                if ($literalName !== null) {
69*37748cd8SNickeau                    $result[$literalName] = $i;
70*37748cd8SNickeau                }
71*37748cd8SNickeau
72*37748cd8SNickeau                $symbolicName = $vocabulary->getSymbolicName($i);
73*37748cd8SNickeau
74*37748cd8SNickeau                if ($symbolicName !== null) {
75*37748cd8SNickeau                    $result[$symbolicName] = $i;
76*37748cd8SNickeau                }
77*37748cd8SNickeau            }
78*37748cd8SNickeau
79*37748cd8SNickeau            $result['EOF'] = Token::EOF;
80*37748cd8SNickeau
81*37748cd8SNickeau            self::$tokenTypeMapCache[$key] = $result;
82*37748cd8SNickeau        }
83*37748cd8SNickeau
84*37748cd8SNickeau        return $result;
85*37748cd8SNickeau    }
86*37748cd8SNickeau
87*37748cd8SNickeau    /**
88*37748cd8SNickeau     * Get a map from rule names to rule indexes.
89*37748cd8SNickeau     *
90*37748cd8SNickeau     * Used for XPath and tree pattern compilation.
91*37748cd8SNickeau     *
92*37748cd8SNickeau     * @return array<int, string>|null
93*37748cd8SNickeau     */
94*37748cd8SNickeau    public function getRuleIndexMap() : ?array
95*37748cd8SNickeau    {
96*37748cd8SNickeau        $result = self::$ruleIndexMapCache[static::class] ?? null;
97*37748cd8SNickeau
98*37748cd8SNickeau        if ($result === null) {
99*37748cd8SNickeau            self::$ruleIndexMapCache[static::class] = $this->getRuleNames();
100*37748cd8SNickeau        }
101*37748cd8SNickeau
102*37748cd8SNickeau        return $result;
103*37748cd8SNickeau    }
104*37748cd8SNickeau
105*37748cd8SNickeau    public function getTokenType(string $tokenName) : int
106*37748cd8SNickeau    {
107*37748cd8SNickeau        $map = $this->getTokenTypeMap();
108*37748cd8SNickeau
109*37748cd8SNickeau        return $map[$tokenName] ?? Token::INVALID_TYPE;
110*37748cd8SNickeau    }
111*37748cd8SNickeau
112*37748cd8SNickeau    /**
113*37748cd8SNickeau     * If this recognizer was generated, it will have a serialized ATN
114*37748cd8SNickeau     * representation of the grammar. For interpreters, we don't know
115*37748cd8SNickeau     * their serialized ATN despite having created the interpreter from it.
116*37748cd8SNickeau     */
117*37748cd8SNickeau    public function getSerializedATN() : string
118*37748cd8SNickeau    {
119*37748cd8SNickeau        throw new \InvalidArgumentException('there is no serialized ATN');
120*37748cd8SNickeau    }
121*37748cd8SNickeau
122*37748cd8SNickeau    /**
123*37748cd8SNickeau     * Get the ATN interpreter used by the recognizer for prediction.
124*37748cd8SNickeau     *
125*37748cd8SNickeau     * @return ATNSimulator|null The ATN interpreter used by the recognizer
126*37748cd8SNickeau     *                           for prediction.
127*37748cd8SNickeau     */
128*37748cd8SNickeau    public function getInterpreter() : ?ATNSimulator
129*37748cd8SNickeau    {
130*37748cd8SNickeau        return $this->interp;
131*37748cd8SNickeau    }
132*37748cd8SNickeau
133*37748cd8SNickeau    protected function interpreter() : ATNSimulator
134*37748cd8SNickeau    {
135*37748cd8SNickeau        if ($this->interp === null) {
136*37748cd8SNickeau            throw new \RuntimeException('Unexpected null interpreter.');
137*37748cd8SNickeau        }
138*37748cd8SNickeau
139*37748cd8SNickeau        return $this->interp;
140*37748cd8SNickeau    }
141*37748cd8SNickeau
142*37748cd8SNickeau    /**
143*37748cd8SNickeau     * Set the ATN interpreter used by the recognizer for prediction.
144*37748cd8SNickeau     *
145*37748cd8SNickeau     * @param ATNSimulator|null $interpreter The ATN interpreter used
146*37748cd8SNickeau     *                                       by the recognizer for prediction.
147*37748cd8SNickeau     */
148*37748cd8SNickeau    public function setInterpreter(?ATNSimulator $interpreter) : void
149*37748cd8SNickeau    {
150*37748cd8SNickeau        $this->interp = $interpreter;
151*37748cd8SNickeau    }
152*37748cd8SNickeau
153*37748cd8SNickeau    /**
154*37748cd8SNickeau     * What is the error header, normally line/character position information?
155*37748cd8SNickeau     */
156*37748cd8SNickeau    public function getErrorHeader(RecognitionException $e) : string
157*37748cd8SNickeau    {
158*37748cd8SNickeau        $token = $e->getOffendingToken();
159*37748cd8SNickeau
160*37748cd8SNickeau        if ($token === null) {
161*37748cd8SNickeau            return '';
162*37748cd8SNickeau        }
163*37748cd8SNickeau
164*37748cd8SNickeau        return \sprintf('line %d:%d', $token->getLine(), $token->getCharPositionInLine());
165*37748cd8SNickeau    }
166*37748cd8SNickeau
167*37748cd8SNickeau    public function addErrorListener(ANTLRErrorListener $listener) : void
168*37748cd8SNickeau    {
169*37748cd8SNickeau        $this->listeners[] = $listener;
170*37748cd8SNickeau    }
171*37748cd8SNickeau
172*37748cd8SNickeau    public function removeErrorListeners() : void
173*37748cd8SNickeau    {
174*37748cd8SNickeau        $this->listeners = [];
175*37748cd8SNickeau    }
176*37748cd8SNickeau
177*37748cd8SNickeau    public function getErrorListenerDispatch() : ANTLRErrorListener
178*37748cd8SNickeau    {
179*37748cd8SNickeau        return new ProxyErrorListener($this->listeners);
180*37748cd8SNickeau    }
181*37748cd8SNickeau
182*37748cd8SNickeau    /**
183*37748cd8SNickeau     * Subclass needs to override these if there are sempreds or actions
184*37748cd8SNickeau     * that the ATN interp needs to execute
185*37748cd8SNickeau     */
186*37748cd8SNickeau    public function sempred(?RuleContext $localctx, int $ruleIndex, int $actionIndex) : bool
187*37748cd8SNickeau    {
188*37748cd8SNickeau        return true;
189*37748cd8SNickeau    }
190*37748cd8SNickeau
191*37748cd8SNickeau    public function precpred(RuleContext $localctx, int $precedence) : bool
192*37748cd8SNickeau    {
193*37748cd8SNickeau        return true;
194*37748cd8SNickeau    }
195*37748cd8SNickeau
196*37748cd8SNickeau    public function action(?RuleContext $localctx, int $ruleIndex, int $actionIndex) : void
197*37748cd8SNickeau    {
198*37748cd8SNickeau    }
199*37748cd8SNickeau
200*37748cd8SNickeau    public function getState() : int
201*37748cd8SNickeau    {
202*37748cd8SNickeau        return $this->stateNumber;
203*37748cd8SNickeau    }
204*37748cd8SNickeau
205*37748cd8SNickeau    /**
206*37748cd8SNickeau     * Indicate that the recognizer has changed internal state that is
207*37748cd8SNickeau     * consistent with the ATN state passed in. This way we always know
208*37748cd8SNickeau     * where we are in the ATN as the parser goes along. The rule
209*37748cd8SNickeau     * context objects form a stack that lets us see the stack of
210*37748cd8SNickeau     * invoking rules. Combine this and we have complete ATN
211*37748cd8SNickeau     * configuration information.
212*37748cd8SNickeau     */
213*37748cd8SNickeau    public function setState(int $atnState) : void
214*37748cd8SNickeau    {
215*37748cd8SNickeau        $this->stateNumber = $atnState;
216*37748cd8SNickeau    }
217*37748cd8SNickeau
218*37748cd8SNickeau    abstract public function getInputStream() : ?IntStream;
219*37748cd8SNickeau    abstract public function setInputStream(IntStream $input) : void;
220*37748cd8SNickeau    abstract public function getTokenFactory() : TokenFactory;
221*37748cd8SNickeau    abstract public function setTokenFactory(TokenFactory $input) : void;
222*37748cd8SNickeau
223*37748cd8SNickeau    /**
224*37748cd8SNickeau     * @return array<int, string>
225*37748cd8SNickeau     */
226*37748cd8SNickeau    abstract public function getRuleNames() : array;
227*37748cd8SNickeau
228*37748cd8SNickeau    /**
229*37748cd8SNickeau     * Get the {@see ATN} used by the recognizer for prediction.
230*37748cd8SNickeau     *
231*37748cd8SNickeau     * @return ATN The {@see ATN} used by the recognizer for prediction.
232*37748cd8SNickeau     */
233*37748cd8SNickeau    abstract public function getATN() : ATN;
234*37748cd8SNickeau}
235