public static class GrammarParserInterpreter.BailButConsumeErrorStrategy extends DefaultErrorStrategy
BailErrorStrategy
as consume() constructs trees. We make sure
to create an error node during recovery with this strategy. We
consume() 1 token during the "bail out of rule" mechanism in recover()
and let it fall out of the rule to finish constructing trees. For
recovery in line, we throw InputMismatchException to engage recover().Modifier and Type | Field and Description |
---|---|
int |
firstErrorTokenIndex |
errorRecoveryMode, lastErrorIndex, lastErrorStates
Constructor and Description |
---|
BailButConsumeErrorStrategy() |
Modifier and Type | Method and Description |
---|---|
void |
recover(Parser recognizer,
RecognitionException e)
This method is called to recover from exception
e . |
Token |
recoverInline(Parser recognizer)
This method is called when an unexpected symbol is encountered during an
inline match operation, such as
Parser.match(int) . |
void |
sync(Parser recognizer)
The default implementation of
ANTLRErrorStrategy.sync(org.antlr.v4.runtime.Parser) makes sure
that the current lookahead symbol is consistent with what were expecting
at this point in the ATN. |
beginErrorCondition, consumeUntil, endErrorCondition, escapeWSAndQuote, getErrorRecoverySet, getExpectedTokens, getMissingSymbol, getSymbolText, getSymbolType, getTokenErrorDisplay, inErrorRecoveryMode, reportError, reportFailedPredicate, reportInputMismatch, reportMatch, reportMissingToken, reportNoViableAlternative, reportUnwantedToken, reset, singleTokenDeletion, singleTokenInsertion
public void recover(Parser recognizer, RecognitionException e)
DefaultErrorStrategy
e
. This method is
called after ANTLRErrorStrategy.reportError(org.antlr.v4.runtime.Parser, org.antlr.v4.runtime.RecognitionException)
by the default exception handler
generated for a rule method.
The default implementation resynchronizes the parser by consuming tokens until we find one in the resynchronization set--loosely the set of tokens that can follow the current rule.
recover
in interface ANTLRErrorStrategy
recover
in class DefaultErrorStrategy
recognizer
- the parser instancee
- the recognition exception to recover fromANTLRErrorStrategy.reportError(org.antlr.v4.runtime.Parser, org.antlr.v4.runtime.RecognitionException)
public Token recoverInline(Parser recognizer) throws RecognitionException
DefaultErrorStrategy
Parser.match(int)
. If the error
strategy successfully recovers from the match failure, this method
returns the Token
instance which should be treated as the
successful result of the match.
This method handles the consumption of any tokens - the caller should
not call Parser.consume()
after a successful recovery.
Note that the calling code will not report an error if this method
returns successfully. The error strategy implementation is responsible
for calling Parser.notifyErrorListeners(java.lang.String)
as appropriate.
The default implementation attempts to recover from the mismatched input
by using single token insertion and deletion as described below. If the
recovery attempt fails, this method throws an
InputMismatchException
.
EXTRA TOKEN (single token deletion)
LA(1)
is not what we are looking for. If LA(2)
has the
right token, however, then assume LA(1)
is some extra spurious
token and delete it. Then consume and return the next token (which was
the LA(2)
token) as the successful result of the match operation.
This recovery strategy is implemented by DefaultErrorStrategy.singleTokenDeletion(org.antlr.v4.runtime.Parser)
.
MISSING TOKEN (single token insertion)
If current token (at LA(1)
) is consistent with what could come
after the expected LA(1)
token, then assume the token is missing
and use the parser's TokenFactory
to create it on the fly. The
"insertion" is performed by returning the created token as the successful
result of the match operation.
This recovery strategy is implemented by DefaultErrorStrategy.singleTokenInsertion(org.antlr.v4.runtime.Parser)
.
EXAMPLE
For example, Input i=(3;
is clearly missing the ')'
. When
the parser returns from the nested call to expr
, it will have
call chain:
stat → expr → atomand it will be trying to match the
')'
at this point in the
derivation:
=> ID '=' '(' INT ')' ('+' atom)* ';' ^The attempt to match
')'
will fail when it sees ';'
and
call DefaultErrorStrategy.recoverInline(org.antlr.v4.runtime.Parser)
. To recover, it sees that LA(1)==';'
is in the set of tokens that can follow the ')'
token reference
in rule atom
. It can assume that you forgot the ')'
.recoverInline
in interface ANTLRErrorStrategy
recoverInline
in class DefaultErrorStrategy
recognizer
- the parser instanceRecognitionException
- if the error strategy was not able to
recover from the unexpected input symbolpublic void sync(Parser recognizer)
DefaultErrorStrategy
ANTLRErrorStrategy.sync(org.antlr.v4.runtime.Parser)
makes sure
that the current lookahead symbol is consistent with what were expecting
at this point in the ATN. You can call this anytime but ANTLR only
generates code to check before subrules/loops and each iteration.
Implements Jim Idle's magic sync mechanism in closures and optional subrules. E.g.,
a : sync ( stuff sync )* ; sync : {consume to what can follow sync} ;At the start of a sub rule upon error,
DefaultErrorStrategy.sync(org.antlr.v4.runtime.Parser)
performs single
token deletion, if possible. If it can't do that, it bails on the current
rule and uses the default error recovery, which consumes until the
resynchronization set of the current rule.
If the sub rule is optional ((...)?
, (...)*
, or block
with an empty alternative), then the expected set includes what follows
the subrule.
During loop iteration, it consumes until it sees a token that can start a sub rule or what follows loop. Yes, that is pretty aggressive. We opt to stay in the loop as long as possible.
ORIGINS
Previous versions of ANTLR did a poor job of their recovery within loops. A single mismatch token or missing token would force the parser to bail out of the entire rules surrounding the loop. So, for rule
classDef : 'class' ID '{' member* '}'input with an extra token between members would force the parser to consume until it found the next class definition rather than the next member definition of the current class.
This functionality cost a little bit of effort because the parser has to compare token set at the start of the loop and at each iteration. If for some reason speed is suffering for you, you can turn off this functionality by simply overriding this method as a blank { }.
sync
in interface ANTLRErrorStrategy
sync
in class DefaultErrorStrategy
recognizer
- the parser instanceDefaultErrorStrategy.sync(org.antlr.v4.runtime.Parser)
Copyright © 1992–2020 ANTLR. All rights reserved.