Poison

recoverInline

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
/**
* {@inheritDoc}
*
* <p>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
* {@link InputMismatchException}.</p>
*
* <p><strong>EXTRA TOKEN</strong> (single token deletion)</p>
*
* <p>{@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.</p>
*
* <p>This recovery strategy is implemented by {@link #singleTokenDeletion}.</p>
*
* <p><strong>MISSING TOKEN</strong> (single token insertion)</p>
*
* <p>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 {@link TokenFactory} to create it on the fly. The
* "insertion" is performed by returning the created token as the successful
* result of the match operation.</p>
*
* <p>This recovery strategy is implemented by {@link #singleTokenInsertion}.</p>
*
* <p><strong>EXAMPLE</strong></p>
*
* <p>For example, Input {@code i=(3;} is clearly missing the {@code ')'}. When
* the parser returns from the nested call to {@code expr}, it will have
* call chain:</p>
*
* <pre>
* stat &rarr; expr &rarr; atom
* </pre>
*
* and it will be trying to match the {@code ')'} at this point in the
* derivation:
*
* <pre>
* =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
* ^
* </pre>
*
* 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 {@code atom}. It can assume that you forgot the {@code ')'}.
*/
@Override
public Token recoverInline(Parser recognizer)
throws RecognitionException
{
// SINGLE TOKEN DELETION
Token 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 = new InputMismatchException(recognizer);
} else {
e = new InputMismatchException(recognizer, nextTokensState, nextTokensContext);
}

throw e;
}

ANTLR4 主要使用单词法符号移除和单词法符号不全来尝试从错误中恢复。在某些场景下,我们不需要这样的错误恢复策略时可以覆写以上方法然后根据需求进行调整。

Reference

antlr4/DefaultErrorStrategy.java at 4.9.2 · antlr/antlr4 · GitHub