1 | /*!
|
2 | * Copyright 2016 The ANTLR Project. All rights reserved.
|
3 | * Licensed under the BSD-3-Clause license. See LICENSE file in the project root for license information.
|
4 | */
|
5 | import { ANTLRErrorStrategy } from "./ANTLRErrorStrategy";
|
6 | import { FailedPredicateException } from "./FailedPredicateException";
|
7 | import { InputMismatchException } from "./InputMismatchException";
|
8 | import { IntervalSet } from "./misc/IntervalSet";
|
9 | import { NoViableAltException } from "./NoViableAltException";
|
10 | import { Parser } from "./Parser";
|
11 | import { ParserRuleContext } from "./ParserRuleContext";
|
12 | import { RecognitionException } from "./RecognitionException";
|
13 | import { Token } from "./Token";
|
14 | import { TokenSource } from "./TokenSource";
|
15 | /**
|
16 | * This is the default implementation of {@link ANTLRErrorStrategy} used for
|
17 | * error reporting and recovery in ANTLR parsers.
|
18 | */
|
19 | export declare class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
20 | /**
|
21 | * Indicates whether the error strategy is currently "recovering from an
|
22 | * error". This is used to suppress reporting multiple error messages while
|
23 | * attempting to recover from a detected syntax error.
|
24 | *
|
25 | * @see #inErrorRecoveryMode
|
26 | */
|
27 | protected errorRecoveryMode: boolean;
|
28 | /** The index into the input stream where the last error occurred.
|
29 | * This is used to prevent infinite loops where an error is found
|
30 | * but no token is consumed during recovery...another error is found,
|
31 | * ad nauseum. This is a failsafe mechanism to guarantee that at least
|
32 | * one token/tree node is consumed for two errors.
|
33 | */
|
34 | protected lastErrorIndex: number;
|
35 | protected lastErrorStates?: IntervalSet;
|
36 | /**
|
37 | * This field is used to propagate information about the lookahead following
|
38 | * the previous match. Since prediction prefers completing the current rule
|
39 | * to error recovery efforts, error reporting may occur later than the
|
40 | * original point where it was discoverable. The original context is used to
|
41 | * compute the true expected sets as though the reporting occurred as early
|
42 | * as possible.
|
43 | */
|
44 | protected nextTokensContext?: ParserRuleContext;
|
45 | /**
|
46 | * @see #nextTokensContext
|
47 | */
|
48 | protected nextTokensState: number;
|
49 | /**
|
50 | * {@inheritDoc}
|
51 | *
|
52 | * The default implementation simply calls {@link #endErrorCondition} to
|
53 | * ensure that the handler is not in error recovery mode.
|
54 | */
|
55 | reset(recognizer: Parser): void;
|
56 | /**
|
57 | * This method is called to enter error recovery mode when a recognition
|
58 | * exception is reported.
|
59 | *
|
60 | * @param recognizer the parser instance
|
61 | */
|
62 | protected beginErrorCondition(recognizer: Parser): void;
|
63 | /**
|
64 | * {@inheritDoc}
|
65 | */
|
66 | inErrorRecoveryMode(recognizer: Parser): boolean;
|
67 | /**
|
68 | * This method is called to leave error recovery mode after recovering from
|
69 | * a recognition exception.
|
70 | *
|
71 | * @param recognizer
|
72 | */
|
73 | protected endErrorCondition(recognizer: Parser): void;
|
74 | /**
|
75 | * {@inheritDoc}
|
76 | *
|
77 | * The default implementation simply calls {@link #endErrorCondition}.
|
78 | */
|
79 | reportMatch(recognizer: Parser): void;
|
80 | /**
|
81 | * {@inheritDoc}
|
82 | *
|
83 | * The default implementation returns immediately if the handler is already
|
84 | * in error recovery mode. Otherwise, it calls {@link #beginErrorCondition}
|
85 | * and dispatches the reporting task based on the runtime type of `e`
|
86 | * according to the following table.
|
87 | *
|
88 | * * {@link NoViableAltException}: Dispatches the call to
|
89 | * {@link #reportNoViableAlternative}
|
90 | * * {@link InputMismatchException}: Dispatches the call to
|
91 | * {@link #reportInputMismatch}
|
92 | * * {@link FailedPredicateException}: Dispatches the call to
|
93 | * {@link #reportFailedPredicate}
|
94 | * * All other types: calls {@link Parser#notifyErrorListeners} to report
|
95 | * the exception
|
96 | */
|
97 | reportError(recognizer: Parser, e: RecognitionException): void;
|
98 | protected notifyErrorListeners(recognizer: Parser, message: string, e: RecognitionException): void;
|
99 | /**
|
100 | * {@inheritDoc}
|
101 | *
|
102 | * The default implementation resynchronizes the parser by consuming tokens
|
103 | * until we find one in the resynchronization set--loosely the set of tokens
|
104 | * that can follow the current rule.
|
105 | */
|
106 | recover(recognizer: Parser, e: RecognitionException): void;
|
107 | /**
|
108 | * The default implementation of {@link ANTLRErrorStrategy#sync} makes sure
|
109 | * that the current lookahead symbol is consistent with what were expecting
|
110 | * at this point in the ATN. You can call this anytime but ANTLR only
|
111 | * generates code to check before subrules/loops and each iteration.
|
112 | *
|
113 | * Implements Jim Idle's magic sync mechanism in closures and optional
|
114 | * subrules. E.g.,
|
115 | *
|
116 | * ```antlr
|
117 | * a : sync ( stuff sync )* ;
|
118 | * sync : {consume to what can follow sync} ;
|
119 | * ```
|
120 | *
|
121 | * At the start of a sub rule upon error, {@link #sync} performs single
|
122 | * token deletion, if possible. If it can't do that, it bails on the current
|
123 | * rule and uses the default error recovery, which consumes until the
|
124 | * resynchronization set of the current rule.
|
125 | *
|
126 | * If the sub rule is optional (`(...)?`, `(...)*`, or block
|
127 | * with an empty alternative), then the expected set includes what follows
|
128 | * the subrule.
|
129 | *
|
130 | * During loop iteration, it consumes until it sees a token that can start a
|
131 | * sub rule or what follows loop. Yes, that is pretty aggressive. We opt to
|
132 | * stay in the loop as long as possible.
|
133 | *
|
134 | * **ORIGINS**
|
135 | *
|
136 | * Previous versions of ANTLR did a poor job of their recovery within loops.
|
137 | * A single mismatch token or missing token would force the parser to bail
|
138 | * out of the entire rules surrounding the loop. So, for rule
|
139 | *
|
140 | * ```antlr
|
141 | * classDef : 'class' ID '{' member* '}'
|
142 | * ```
|
143 | *
|
144 | * input with an extra token between members would force the parser to
|
145 | * consume until it found the next class definition rather than the next
|
146 | * member definition of the current class.
|
147 | *
|
148 | * This functionality cost a little bit of effort because the parser has to
|
149 | * compare token set at the start of the loop and at each iteration. If for
|
150 | * some reason speed is suffering for you, you can turn off this
|
151 | * functionality by simply overriding this method as a blank { }.
|
152 | */
|
153 | sync(recognizer: Parser): void;
|
154 | /**
|
155 | * This is called by {@link #reportError} when the exception is a
|
156 | * {@link NoViableAltException}.
|
157 | *
|
158 | * @see #reportError
|
159 | *
|
160 | * @param recognizer the parser instance
|
161 | * @param e the recognition exception
|
162 | */
|
163 | protected reportNoViableAlternative(recognizer: Parser, e: NoViableAltException): void;
|
164 | /**
|
165 | * This is called by {@link #reportError} when the exception is an
|
166 | * {@link InputMismatchException}.
|
167 | *
|
168 | * @see #reportError
|
169 | *
|
170 | * @param recognizer the parser instance
|
171 | * @param e the recognition exception
|
172 | */
|
173 | protected reportInputMismatch(recognizer: Parser, e: InputMismatchException): void;
|
174 | /**
|
175 | * This is called by {@link #reportError} when the exception is a
|
176 | * {@link FailedPredicateException}.
|
177 | *
|
178 | * @see #reportError
|
179 | *
|
180 | * @param recognizer the parser instance
|
181 | * @param e the recognition exception
|
182 | */
|
183 | protected reportFailedPredicate(recognizer: Parser, e: FailedPredicateException): void;
|
184 | /**
|
185 | * This method is called to report a syntax error which requires the removal
|
186 | * of a token from the input stream. At the time this method is called, the
|
187 | * erroneous symbol is current `LT(1)` symbol and has not yet been
|
188 | * removed from the input stream. When this method returns,
|
189 | * `recognizer` is in error recovery mode.
|
190 | *
|
191 | * This method is called when {@link #singleTokenDeletion} identifies
|
192 | * single-token deletion as a viable recovery strategy for a mismatched
|
193 | * input error.
|
194 | *
|
195 | * The default implementation simply returns if the handler is already in
|
196 | * error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
|
197 | * enter error recovery mode, followed by calling
|
198 | * {@link Parser#notifyErrorListeners}.
|
199 | *
|
200 | * @param recognizer the parser instance
|
201 | */
|
202 | protected reportUnwantedToken(recognizer: Parser): void;
|
203 | /**
|
204 | * This method is called to report a syntax error which requires the
|
205 | * insertion of a missing token into the input stream. At the time this
|
206 | * method is called, the missing token has not yet been inserted. When this
|
207 | * method returns, `recognizer` is in error recovery mode.
|
208 | *
|
209 | * This method is called when {@link #singleTokenInsertion} identifies
|
210 | * single-token insertion as a viable recovery strategy for a mismatched
|
211 | * input error.
|
212 | *
|
213 | * The default implementation simply returns if the handler is already in
|
214 | * error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
|
215 | * enter error recovery mode, followed by calling
|
216 | * {@link Parser#notifyErrorListeners}.
|
217 | *
|
218 | * @param recognizer the parser instance
|
219 | */
|
220 | protected reportMissingToken(recognizer: Parser): void;
|
221 | /**
|
222 | * {@inheritDoc}
|
223 | *
|
224 | * The default implementation attempts to recover from the mismatched input
|
225 | * by using single token insertion and deletion as described below. If the
|
226 | * recovery attempt fails, this method
|
227 | * {@link InputMismatchException}.
|
228 | *
|
229 | * **EXTRA TOKEN** (single token deletion)
|
230 | *
|
231 | * `LA(1)` is not what we are looking for. If `LA(2)` has the
|
232 | * right token, however, then assume `LA(1)` is some extra spurious
|
233 | * token and delete it. Then consume and return the next token (which was
|
234 | * the `LA(2)` token) as the successful result of the match operation.
|
235 | *
|
236 | * This recovery strategy is implemented by {@link #singleTokenDeletion}.
|
237 | *
|
238 | * **MISSING TOKEN** (single token insertion)
|
239 | *
|
240 | * If current token (at `LA(1)`) is consistent with what could come
|
241 | * after the expected `LA(1)` token, then assume the token is missing
|
242 | * and use the parser's {@link TokenFactory} to create it on the fly. The
|
243 | * "insertion" is performed by returning the created token as the successful
|
244 | * result of the match operation.
|
245 | *
|
246 | * This recovery strategy is implemented by {@link #singleTokenInsertion}.
|
247 | *
|
248 | * **EXAMPLE**
|
249 | *
|
250 | * For example, Input `i=(3;` is clearly missing the `')'`. When
|
251 | * the parser returns from the nested call to `expr`, it will have
|
252 | * call chain:
|
253 | *
|
254 | * ```
|
255 | * stat → expr → atom
|
256 | * ```
|
257 | *
|
258 | * and it will be trying to match the `')'` at this point in the
|
259 | * derivation:
|
260 | *
|
261 | * ```
|
262 | * => ID '=' '(' INT ')' ('+' atom)* ';'
|
263 | * ^
|
264 | * ```
|
265 | *
|
266 | * The attempt to match `')'` will fail when it sees `';'` and
|
267 | * call {@link #recoverInline}. To recover, it sees that `LA(1)==';'`
|
268 | * is in the set of tokens that can follow the `')'` token reference
|
269 | * in rule `atom`. It can assume that you forgot the `')'`.
|
270 | */
|
271 | recoverInline(recognizer: Parser): Token;
|
272 | /**
|
273 | * This method implements the single-token insertion inline error recovery
|
274 | * strategy. It is called by {@link #recoverInline} if the single-token
|
275 | * deletion strategy fails to recover from the mismatched input. If this
|
276 | * method returns `true`, `recognizer` will be in error recovery
|
277 | * mode.
|
278 | *
|
279 | * This method determines whether or not single-token insertion is viable by
|
280 | * checking if the `LA(1)` input symbol could be successfully matched
|
281 | * if it were instead the `LA(2)` symbol. If this method returns
|
282 | * `true`, the caller is responsible for creating and inserting a
|
283 | * token with the correct type to produce this behavior.
|
284 | *
|
285 | * @param recognizer the parser instance
|
286 | * @returns `true` if single-token insertion is a viable recovery
|
287 | * strategy for the current mismatched input, otherwise `false`
|
288 | */
|
289 | protected singleTokenInsertion(recognizer: Parser): boolean;
|
290 | /**
|
291 | * This method implements the single-token deletion inline error recovery
|
292 | * strategy. It is called by {@link #recoverInline} to attempt to recover
|
293 | * from mismatched input. If this method returns `undefined`, the parser and error
|
294 | * handler state will not have changed. If this method returns non-`undefined`,
|
295 | * `recognizer` will *not* be in error recovery mode since the
|
296 | * returned token was a successful match.
|
297 | *
|
298 | * If the single-token deletion is successful, this method calls
|
299 | * {@link #reportUnwantedToken} to report the error, followed by
|
300 | * {@link Parser#consume} to actually "delete" the extraneous token. Then,
|
301 | * before returning {@link #reportMatch} is called to signal a successful
|
302 | * match.
|
303 | *
|
304 | * @param recognizer the parser instance
|
305 | * @returns the successfully matched {@link Token} instance if single-token
|
306 | * deletion successfully recovers from the mismatched input, otherwise
|
307 | * `undefined`
|
308 | */
|
309 | protected singleTokenDeletion(recognizer: Parser): Token | undefined;
|
310 | /** Conjure up a missing token during error recovery.
|
311 | *
|
312 | * The recognizer attempts to recover from single missing
|
313 | * symbols. But, actions might refer to that missing symbol.
|
314 | * For example, x=ID {f($x);}. The action clearly assumes
|
315 | * that there has been an identifier matched previously and that
|
316 | * $x points at that token. If that token is missing, but
|
317 | * the next token in the stream is what we want we assume that
|
318 | * this token is missing and we keep going. Because we
|
319 | * have to return some token to replace the missing token,
|
320 | * we have to conjure one up. This method gives the user control
|
321 | * over the tokens returned for missing tokens. Mostly,
|
322 | * you will want to create something special for identifier
|
323 | * tokens. For literals such as '{' and ',', the default
|
324 | * action in the parser or tree parser works. It simply creates
|
325 | * a CommonToken of the appropriate type. The text will be the token.
|
326 | * If you change what tokens must be created by the lexer,
|
327 | * override this method to create the appropriate tokens.
|
328 | */
|
329 | protected getMissingSymbol(recognizer: Parser): Token;
|
330 | protected constructToken(tokenSource: TokenSource, expectedTokenType: number, tokenText: string, current: Token): Token;
|
331 | protected getExpectedTokens(recognizer: Parser): IntervalSet;
|
332 | /** How should a token be displayed in an error message? The default
|
333 | * is to display just the text, but during development you might
|
334 | * want to have a lot of information spit out. Override in that case
|
335 | * to use t.toString() (which, for CommonToken, dumps everything about
|
336 | * the token). This is better than forcing you to override a method in
|
337 | * your token objects because you don't have to go modify your lexer
|
338 | * so that it creates a new Java type.
|
339 | */
|
340 | protected getTokenErrorDisplay(t: Token | undefined): string;
|
341 | protected getSymbolText(symbol: Token): string | undefined;
|
342 | protected getSymbolType(symbol: Token): number;
|
343 | protected escapeWSAndQuote(s: string): string;
|
344 | protected getErrorRecoverySet(recognizer: Parser): IntervalSet;
|
345 | /** Consume tokens until one matches the given token set. */
|
346 | protected consumeUntil(recognizer: Parser, set: IntervalSet): void;
|
347 | }
|