recoverInline method
{@inheritDoc}
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)
{@code LA(1)} is not what we are looking for. If {@code LA(2)} has the right token, however, then assume {@code LA(1)} is some extra spurious token and delete it. Then consume and return the next token (which was the {@code LA(2)} token) as the successful result of the match operation.
This recovery strategy is implemented by {@link #singleTokenDeletion}.
MISSING TOKEN (single token insertion)
If current token (at {@code LA(1)}) is consistent with what could come after the expected {@code 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 {@link #singleTokenInsertion}.
EXAMPLE
For example, Input {@code i=(3;} is clearly missing the {@code ')'}. When the parser returns from the nested call to [expr], it will have call chain:
stat → expr → atom
and it will be trying to match the {@code ')'} at this point in the derivation:
=> ID '=' '(' INT ')' ('+' atom)* ';' ^
The attempt to match {@code ')'} will fail when it sees {@code ';'} and
call {@link #recoverInline}. To recover, it sees that {@code LA(1)==';'}
is in the set of tokens that can follow the {@code ')'} token reference
in rule atom
. It can assume that you forgot the {@code ')'}.
Implementation
@override
Token recoverInline(Parser recognizer) {
// SINGLE TOKEN DELETION
final matchedSymbol = singleTokenDeletion(recognizer);
if (matchedSymbol != null) {
// we have deleted the extra token.
// now, move past ttype token as if all were ok
recognizer.consume();
return matchedSymbol;
}
// SINGLE TOKEN INSERTION
if (singleTokenInsertion(recognizer)) {
return getMissingSymbol(recognizer);
}
// even that didn't work; must throw the exception
InputMismatchException e;
if (nextTokensContext == null) {
e = InputMismatchException(recognizer);
} else {
e = InputMismatchException(
recognizer,
nextTokensState!,
nextTokensContext,
);
}
throw e;
}