aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/antlr4_cpp_runtime/src/Parser.h
blob: f490b00c38fadfe2ac3f0234bf23af6c47b7fe3a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

#pragma once

#include "Recognizer.h"
#include "tree/ParseTreeListener.h"
#include "tree/ParseTree.h"
#include "TokenStream.h"
#include "TokenSource.h"
#include "misc/Interval.h"

namespace antlr4 {

  /// This is all the parsing support code essentially; most of it is error recovery stuff.
  class ANTLR4CPP_PUBLIC Parser : public Recognizer {
  public:

    class TraceListener : public tree::ParseTreeListener {
    public:
      TraceListener(Parser *outerInstance);
      virtual ~TraceListener();

      virtual void enterEveryRule(ParserRuleContext *ctx) override;
      virtual void visitTerminal(tree::TerminalNode *node) override;
      virtual void visitErrorNode(tree::ErrorNode *node) override;
      virtual void exitEveryRule(ParserRuleContext *ctx) override;

    private:
      Parser *const outerInstance;
    };

    class TrimToSizeListener : public tree::ParseTreeListener {
    public:
      static TrimToSizeListener INSTANCE;

      virtual ~TrimToSizeListener();

      virtual void enterEveryRule(ParserRuleContext *ctx) override;
      virtual void visitTerminal(tree::TerminalNode *node) override;
      virtual void visitErrorNode(tree::ErrorNode *node) override;
      virtual void exitEveryRule(ParserRuleContext *ctx) override;
    };

    Parser(TokenStream *input);
    virtual ~Parser();

    /// reset the parser's state
    virtual void reset();

    /// <summary>
    /// Match current input symbol against {@code ttype}. If the symbol type
    /// matches, <seealso cref="ANTLRErrorStrategy#reportMatch"/> and <seealso cref="#consume"/> are
    /// called to complete the match process.
    ///
    /// If the symbol type does not match,
    /// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is called on the current error
    /// strategy to attempt recovery. If <seealso cref="#getBuildParseTree"/> is
    /// {@code true} and the token index of the symbol returned by
    /// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is -1, the symbol is added to
    /// the parse tree by calling {@link #createErrorNode(ParserRuleContext, Token)} then
    /// {@link ParserRuleContext#addErrorNode(ErrorNode)}.
    /// </summary>
    /// <param name="ttype"> the token type to match </param>
    /// <returns> the matched symbol </returns>
    /// <exception cref="RecognitionException"> if the current input symbol did not match
    /// {@code ttype} and the error strategy could not recover from the
    /// mismatched symbol </exception>
    virtual Token* match(size_t ttype);

    /// <summary>
    /// Match current input symbol as a wildcard. If the symbol type matches
    /// (i.e. has a value greater than 0), <seealso cref="ANTLRErrorStrategy#reportMatch"/>
    /// and <seealso cref="#consume"/> are called to complete the match process.
    /// <p/>
    /// If the symbol type does not match,
    /// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is called on the current error
    /// strategy to attempt recovery. If <seealso cref="#getBuildParseTree"/> is
    /// {@code true} and the token index of the symbol returned by
    /// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is -1, the symbol is added to
    /// the parse tree by calling <seealso cref="ParserRuleContext#addErrorNode"/>.
    /// </summary>
    /// <returns> the matched symbol </returns>
    /// <exception cref="RecognitionException"> if the current input symbol did not match
    /// a wildcard and the error strategy could not recover from the mismatched
    /// symbol </exception>
    virtual Token* matchWildcard();

    /// <summary>
    /// Track the <seealso cref="ParserRuleContext"/> objects during the parse and hook
    /// them up using the <seealso cref="ParserRuleContext#children"/> list so that it
    /// forms a parse tree. The <seealso cref="ParserRuleContext"/> returned from the start
    /// rule represents the root of the parse tree.
    /// <p/>
    /// Note that if we are not building parse trees, rule contexts only point
    /// upwards. When a rule exits, it returns the context but that gets garbage
    /// collected if nobody holds a reference. It points upwards but nobody
    /// points at it.
    /// <p/>
    /// When we build parse trees, we are adding all of these contexts to
    /// <seealso cref="ParserRuleContext#children"/> list. Contexts are then not candidates
    /// for garbage collection.
    /// </summary>
    virtual void setBuildParseTree(bool buildParseTrees);

    /// <summary>
    /// Gets whether or not a complete parse tree will be constructed while
    /// parsing. This property is {@code true} for a newly constructed parser.
    /// </summary>
    /// <returns> {@code true} if a complete parse tree will be constructed while
    /// parsing, otherwise {@code false} </returns>
    virtual bool getBuildParseTree();

    /// <summary>
    /// Trim the internal lists of the parse tree during parsing to conserve memory.
    /// This property is set to {@code false} by default for a newly constructed parser.
    /// </summary>
    /// <param name="trimParseTrees"> {@code true} to trim the capacity of the <seealso cref="ParserRuleContext#children"/>
    /// list to its size after a rule is parsed. </param>
    virtual void setTrimParseTree(bool trimParseTrees);

    /// <returns> {@code true} if the <seealso cref="ParserRuleContext#children"/> list is trimmed
    /// using the default <seealso cref="Parser.TrimToSizeListener"/> during the parse process. </returns>
    virtual bool getTrimParseTree();

    virtual std::vector<tree::ParseTreeListener *> getParseListeners();

    /// <summary>
    /// Registers {@code listener} to receive events during the parsing process.
    /// <p/>
    /// To support output-preserving grammar transformations (including but not
    /// limited to left-recursion removal, automated left-factoring, and
    /// optimized code generation), calls to listener methods during the parse
    /// may differ substantially from calls made by
    /// <seealso cref="ParseTreeWalker#DEFAULT"/> used after the parse is complete. In
    /// particular, rule entry and exit events may occur in a different order
    /// during the parse than after the parser. In addition, calls to certain
    /// rule entry methods may be omitted.
    /// <p/>
    /// With the following specific exceptions, calls to listener events are
    /// <em>deterministic</em>, i.e. for identical input the calls to listener
    /// methods will be the same.
    ///
    /// <ul>
    /// <li>Alterations to the grammar used to generate code may change the
    /// behavior of the listener calls.</li>
    /// <li>Alterations to the command line options passed to ANTLR 4 when
    /// generating the parser may change the behavior of the listener calls.</li>
    /// <li>Changing the version of the ANTLR Tool used to generate the parser
    /// may change the behavior of the listener calls.</li>
    /// </ul>
    /// </summary>
    /// <param name="listener"> the listener to add
    /// </param>
    /// <exception cref="NullPointerException"> if {@code} listener is {@code null} </exception>
    virtual void addParseListener(tree::ParseTreeListener *listener);

    /// <summary>
    /// Remove {@code listener} from the list of parse listeners.
    /// <p/>
    /// If {@code listener} is {@code null} or has not been added as a parse
    /// listener, this method does nothing.
    /// </summary>
    /// <seealso cref= #addParseListener
    /// </seealso>
    /// <param name="listener"> the listener to remove </param>
    virtual void removeParseListener(tree::ParseTreeListener *listener);

    /// <summary>
    /// Remove all parse listeners.
    /// </summary>
    /// <seealso cref= #addParseListener </seealso>
    virtual void removeParseListeners();

    /// <summary>
    /// Notify any parse listeners of an enter rule event.
    /// </summary>
    /// <seealso cref= #addParseListener </seealso>
    virtual void triggerEnterRuleEvent();

    /// <summary>
    /// Notify any parse listeners of an exit rule event.
    /// </summary>
    /// <seealso cref= #addParseListener </seealso>
    virtual void triggerExitRuleEvent();

    /// <summary>
    /// Gets the number of syntax errors reported during parsing. This value is
    /// incremented each time <seealso cref="#notifyErrorListeners"/> is called.
    /// </summary>
    /// <seealso cref= #notifyErrorListeners </seealso>
    virtual size_t getNumberOfSyntaxErrors();

    virtual TokenFactory<CommonToken>* getTokenFactory() override;

    /// <summary>
    /// Tell our token source and error strategy about a new way to create tokens. </summary>
    template<typename T1>
    void setTokenFactory(TokenFactory<T1> *factory)  {
      _input->getTokenSource()->setTokenFactory(factory);
    }

    /// The ATN with bypass alternatives is expensive to create so we create it
    /// lazily. The ATN is owned by us.
    virtual const atn::ATN& getATNWithBypassAlts();

    /// <summary>
    /// The preferred method of getting a tree pattern. For example, here's a
    /// sample use:
    ///
    /// <pre>
    /// ParseTree t = parser.expr();
    /// ParseTreePattern p = parser.compileParseTreePattern("<ID>+0", MyParser.RULE_expr);
    /// ParseTreeMatch m = p.match(t);
    /// String id = m.get("ID");
    /// </pre>
    /// </summary>
    virtual tree::pattern::ParseTreePattern compileParseTreePattern(const std::string &pattern, int patternRuleIndex);

    /// <summary>
    /// The same as <seealso cref="#compileParseTreePattern(String, int)"/> but specify a
    /// <seealso cref="Lexer"/> rather than trying to deduce it from this parser.
    /// </summary>
    virtual tree::pattern::ParseTreePattern compileParseTreePattern(const std::string &pattern, int patternRuleIndex,
                                                                    Lexer *lexer);

    virtual Ref<ANTLRErrorStrategy> getErrorHandler();
    virtual void setErrorHandler(Ref<ANTLRErrorStrategy> const& handler);

    virtual IntStream* getInputStream() override;
    void setInputStream(IntStream *input) override;

    virtual TokenStream* getTokenStream();

    /// Set the token stream and reset the parser.
    virtual void setTokenStream(TokenStream *input);

    /// <summary>
    /// Match needs to return the current input symbol, which gets put
    ///  into the label for the associated token ref; e.g., x=ID.
    /// </summary>
    virtual Token* getCurrentToken();

    void notifyErrorListeners(const std::string &msg);

    virtual void notifyErrorListeners(Token *offendingToken, const std::string &msg, std::exception_ptr e);

    /// Consume and return the <seealso cref="#getCurrentToken current symbol"/>.
    /// <p/>
    /// E.g., given the following input with {@code A} being the current
    /// lookahead symbol, this function moves the cursor to {@code B} and returns
    /// {@code A}.
    ///
    /// <pre>
    ///  A B
    ///  ^
    /// </pre>
    ///
    /// If the parser is not in error recovery mode, the consumed symbol is added
    /// to the parse tree using <seealso cref="ParserRuleContext#addChild(TerminalNode)"/>, and
    /// <seealso cref="ParseTreeListener#visitTerminal"/> is called on any parse listeners.
    /// If the parser <em>is</em> in error recovery mode, the consumed symbol is
    /// added to the parse tree using {@link #createErrorNode(ParserRuleContext, Token)} then
    /// {@link ParserRuleContext#addErrorNode(ErrorNode)} and
    /// <seealso cref="ParseTreeListener#visitErrorNode"/> is called on any parse
    /// listeners.
    virtual Token* consume();

    /// Always called by generated parsers upon entry to a rule. Access field
    /// <seealso cref="#_ctx"/> get the current context.
    virtual void enterRule(ParserRuleContext *localctx, size_t state, size_t ruleIndex);

    void exitRule();

    virtual void enterOuterAlt(ParserRuleContext *localctx, size_t altNum);

    /**
     * Get the precedence level for the top-most precedence rule.
     *
     * @return The precedence level for the top-most precedence rule, or -1 if
     * the parser context is not nested within a precedence rule.
     */
    int getPrecedence() const;

    /// @deprecated Use
    /// <seealso cref="#enterRecursionRule(ParserRuleContext, int, int, int)"/> instead.
    virtual void enterRecursionRule(ParserRuleContext *localctx, size_t ruleIndex);
    virtual void enterRecursionRule(ParserRuleContext *localctx, size_t state, size_t ruleIndex, int precedence);

    /** Like {@link #enterRule} but for recursive rules.
     *  Make the current context the child of the incoming localctx.
     */
    virtual void pushNewRecursionContext(ParserRuleContext *localctx, size_t state, size_t ruleIndex);
    virtual void unrollRecursionContexts(ParserRuleContext *parentctx);
    virtual ParserRuleContext* getInvokingContext(size_t ruleIndex);
    virtual ParserRuleContext* getContext();
    virtual void setContext(ParserRuleContext *ctx);
    virtual bool precpred(RuleContext *localctx, int precedence) override;
    virtual bool inContext(const std::string &context);

    /// <summary>
    /// Checks whether or not {@code symbol} can follow the current state in the
    /// ATN. The behavior of this method is equivalent to the following, but is
    /// implemented such that the complete context-sensitive follow set does not
    /// need to be explicitly constructed.
    ///
    /// <pre>
    /// return getExpectedTokens().contains(symbol);
    /// </pre>
    /// </summary>
    /// <param name="symbol"> the symbol type to check </param>
    /// <returns> {@code true} if {@code symbol} can follow the current state in
    /// the ATN, otherwise {@code false}. </returns>
    virtual bool isExpectedToken(size_t symbol);

    bool isMatchedEOF() const;

    /// <summary>
    /// Computes the set of input symbols which could follow the current parser
    /// state and context, as given by <seealso cref="#getState"/> and <seealso cref="#getContext"/>,
    /// respectively.
    /// </summary>
    /// <seealso cref= ATN#getExpectedTokens(int, RuleContext) </seealso>
    virtual misc::IntervalSet getExpectedTokens();

    virtual misc::IntervalSet getExpectedTokensWithinCurrentRule();

    /// Get a rule's index (i.e., {@code RULE_ruleName} field) or INVALID_INDEX if not found.
    virtual size_t getRuleIndex(const std::string &ruleName);

    virtual ParserRuleContext* getRuleContext();

    /// <summary>
    /// Return List&lt;String&gt; of the rule names in your parser instance
    ///  leading up to a call to the current rule.  You could override if
    ///  you want more details such as the file/line info of where
    ///  in the ATN a rule is invoked.
    ///
    ///  This is very useful for error messages.
    /// </summary>
    virtual std::vector<std::string> getRuleInvocationStack();

    virtual std::vector<std::string> getRuleInvocationStack(RuleContext *p);

    /// <summary>
    /// For debugging and other purposes. </summary>
    virtual std::vector<std::string> getDFAStrings();

    /// <summary>
    /// For debugging and other purposes. </summary>
    virtual void dumpDFA();

    virtual std::string getSourceName();

    atn::ParseInfo getParseInfo() const;

    /**
     * @since 4.3
     */
    void setProfile(bool profile);

    /// <summary>
    /// During a parse is sometimes useful to listen in on the rule entry and exit
    ///  events as well as token matches. This is for quick and dirty debugging.
    /// </summary>
    virtual void setTrace(bool trace);

    /**
     * Gets whether a {@link TraceListener} is registered as a parse listener
     * for the parser.
     *
     * @see #setTrace(boolean)
     */
    bool isTrace() const;

    tree::ParseTreeTracker& getTreeTracker() { return _tracker; }

    /** How to create a token leaf node associated with a parent.
     *  Typically, the terminal node to create is not a function of the parent
     *  but this method must still set the parent pointer of the terminal node
     *  returned. I would prefer having {@link ParserRuleContext#addAnyChild(ParseTree)}
     *  set the parent pointer, but the parent pointer is implementation dependent
     *  and currently there is no setParent() in {@link TerminalNode} (and can't
     *  add method in Java 1.7 without breaking backward compatibility).
     *
     * @since 4.7
     */
    tree::TerminalNode *createTerminalNode(Token *t);

    /** How to create an error node, given a token, associated with a parent.
       *  Typically, the error node to create is not a function of the parent
       *  but this method must still set the parent pointer of the terminal node
       *  returned. I would prefer having {@link ParserRuleContext#addAnyChild(ParseTree)}
       *  set the parent pointer, but the parent pointer is implementation dependent
       *  and currently there is no setParent() in {@link ErrorNode} (and can't
       *  add method in Java 1.7 without breaking backward compatibility).
       *
       * @since 4.7
       */
    tree::ErrorNode *createErrorNode(Token *t);

  protected:
    /// The ParserRuleContext object for the currently executing rule.
    /// This is always non-null during the parsing process.
    // ml: this is one of the contexts tracked in _allocatedContexts.
    ParserRuleContext *_ctx;

    /// The error handling strategy for the parser. The default is DefaultErrorStrategy.
    /// See also getErrorHandler.
    Ref<ANTLRErrorStrategy> _errHandler;

    /// <summary>
    /// The input stream.
    /// </summary>
    /// <seealso cref= #getInputStream </seealso>
    /// <seealso cref= #setInputStream </seealso>
    TokenStream *_input;

    std::vector<int> _precedenceStack;

    /// <summary>
    /// Specifies whether or not the parser should construct a parse tree during
    /// the parsing process. The default value is {@code true}.
    /// </summary>
    /// <seealso cref= #getBuildParseTree </seealso>
    /// <seealso cref= #setBuildParseTree </seealso>
    bool _buildParseTrees;

    /// The list of <seealso cref="ParseTreeListener"/> listeners registered to receive
    /// events during the parse.
    /// <seealso cref= #addParseListener </seealso>
    std::vector<tree::ParseTreeListener *> _parseListeners;

    /// <summary>
    /// The number of syntax errors reported during parsing. This value is
    /// incremented each time <seealso cref="#notifyErrorListeners"/> is called.
    /// </summary>
    size_t _syntaxErrors;

    /** Indicates parser has match()ed EOF token. See {@link #exitRule()}. */
    bool _matchedEOF;

    virtual void addContextToParseTree();

    // All rule contexts created during a parse run. This is cleared when calling reset().
    tree::ParseTreeTracker _tracker;

  private:
    /// When setTrace(true) is called, a reference to the
    /// TraceListener is stored here so it can be easily removed in a
    /// later call to setTrace(false). The listener itself is
    /// implemented as a parser listener so this field is not directly used by
    /// other parser methods.
    TraceListener *_tracer;

    void InitializeInstanceFields();
  };

} // namespace antlr4