use of org.antlr.v4.runtime.Recognizer in project antlr4 by antlr.
the class DefaultErrorStrategy method sync.
/**
* The default implementation of {@link ANTLRErrorStrategy#sync} 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.
*
* <p>Implements Jim Idle's magic sync mechanism in closures and optional
* subrules. E.g.,</p>
*
* <pre>
* a : sync ( stuff sync )* ;
* sync : {consume to what can follow sync} ;
* </pre>
*
* At the start of a sub rule upon error, {@link #sync} 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.
*
* <p>If the sub rule is optional ({@code (...)?}, {@code (...)*}, or block
* with an empty alternative), then the expected set includes what follows
* the subrule.</p>
*
* <p>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.</p>
*
* <p><strong>ORIGINS</strong></p>
*
* <p>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</p>
*
* <pre>
* classDef : 'class' ID '{' member* '}'
* </pre>
*
* 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.
*
* <p>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 { }.</p>
*/
@Override
public void sync(Parser recognizer) throws RecognitionException {
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer.getState());
// If already recovering, don't try to sync
if (inErrorRecoveryMode(recognizer)) {
return;
}
TokenStream tokens = recognizer.getInputStream();
int la = tokens.LA(1);
// try cheaper subset first; might get lucky. seems to shave a wee bit off
IntervalSet nextTokens = recognizer.getATN().nextTokens(s);
if (nextTokens.contains(la)) {
// We are sure the token matches
nextTokensContext = null;
nextTokensState = ATNState.INVALID_STATE_NUMBER;
return;
}
if (nextTokens.contains(Token.EPSILON)) {
if (nextTokensContext == null) {
// It's possible the next token won't match; information tracked
// by sync is restricted for performance.
nextTokensContext = recognizer.getContext();
nextTokensState = recognizer.getState();
}
return;
}
switch(s.getStateType()) {
case ATNState.BLOCK_START:
case ATNState.STAR_BLOCK_START:
case ATNState.PLUS_BLOCK_START:
case ATNState.STAR_LOOP_ENTRY:
// report error and recover if possible
if (singleTokenDeletion(recognizer) != null) {
return;
}
throw new InputMismatchException(recognizer);
case ATNState.PLUS_LOOP_BACK:
case ATNState.STAR_LOOP_BACK:
// System.err.println("at loop back: "+s.getClass().getSimpleName());
reportUnwantedToken(recognizer);
IntervalSet expecting = recognizer.getExpectedTokens();
IntervalSet whatFollowsLoopIterationOrRule = expecting.or(getErrorRecoverySet(recognizer));
consumeUntil(recognizer, whatFollowsLoopIterationOrRule);
break;
default:
// do nothing if we can't identify the exact kind of ATN state
break;
}
}
use of org.antlr.v4.runtime.Recognizer in project batfish by batfish.
the class BatfishANTLRErrorStrategy method sync.
@Override
public void sync(Parser recognizer) throws RecognitionException {
/*
* BEGIN: Copied from super
*/
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer.getState());
if (inErrorRecoveryMode(recognizer)) {
return;
}
TokenStream tokens = recognizer.getInputStream();
int la = tokens.LA(1);
IntervalSet nextTokens = recognizer.getATN().nextTokens(s);
if (nextTokens.contains(Token.EPSILON) || nextTokens.contains(la)) {
return;
}
/*
* END: Copied from super
*/
boolean topLevel = recognizer.getContext().parent == null;
switch(s.getStateType()) {
case ATNState.BLOCK_START:
case ATNState.STAR_BLOCK_START:
case ATNState.PLUS_BLOCK_START:
case ATNState.STAR_LOOP_ENTRY:
case ATNState.PLUS_LOOP_BACK:
case ATNState.STAR_LOOP_BACK:
if (topLevel) {
/*
* When at top level, we cannot pop up. So consume every "line" until we have one that
* starts with a token acceptable at the top level.
*/
reportUnwantedToken(recognizer);
consumeBlocksUntilWanted(recognizer);
return;
} else {
/*
* If not at the top level, error out to pop up a level. This may repeat until the next
* token is acceptable at the given level.
*/
throw new InputMismatchException(recognizer);
}
default:
return;
}
}
use of org.antlr.v4.runtime.Recognizer in project batfish by batfish.
the class BatfishANTLRErrorStrategy method createErrorNode.
/**
* Create an error node with the text of the current line and insert it into parse tree
*
* @param recognizer The recognizer with which to create the error node
* @param separator The token that ends the unrecognized link. This is also used to determine the
* index of the line to return in error messages.
* @return The token contained in the error node
*/
private Token createErrorNode(Parser recognizer, ParserRuleContext ctx, Token separator) {
if (_recoveredAtEof) {
_recoveredAtEof = false;
throw new BatfishRecognitionException(recognizer, recognizer.getInputStream(), ctx);
}
if (separator.getType() == Lexer.EOF) {
_recoveredAtEof = true;
}
String lineText = _lines[separator.getLine() - 1] + separator.getText();
Token lineToken = recognizer.getTokenFactory().create(new Pair<>(null, null), BatfishLexer.UNRECOGNIZED_LINE_TOKEN, lineText, Lexer.DEFAULT_TOKEN_CHANNEL, -1, -1, separator.getLine(), 0);
ErrorNode errorNode = recognizer.createErrorNode(ctx, lineToken);
ctx.addErrorNode(errorNode);
return lineToken;
}
use of org.antlr.v4.runtime.Recognizer in project batfish by batfish.
the class BatfishANTLRErrorStrategy method recoverInCurrentNode.
/**
* Recover from adaptive prediction failure (when more than one token is needed for rule
* prediction, and the first token by itself is insufficient to determine an error has occured) by
* throwing away lines until adaptive prediction succeeds or there is nothing left to throw away.
* Each discarded line is inserted as a child of the current rule as an {@link ErrorNode}.
*
* @param recognizer The {@link Parser} for whom adaptive prediction has failed
*/
public void recoverInCurrentNode(Parser recognizer) {
beginErrorCondition(recognizer);
lastErrorIndex = recognizer.getInputStream().index();
if (lastErrorStates == null) {
lastErrorStates = new IntervalSet();
}
lastErrorStates.add(recognizer.getState());
consumeUntilEndOfLine(recognizer);
// Get the line number and separator text from the separator token
Token separatorToken = recognizer.getCurrentToken();
ParserRuleContext ctx = recognizer.getContext();
recognizer.consume();
createErrorNode(recognizer, ctx, separatorToken);
endErrorCondition(recognizer);
if (recognizer.getInputStream().LA(1) == Lexer.EOF) {
recover(recognizer);
}
}
use of org.antlr.v4.runtime.Recognizer in project batfish by batfish.
the class BatfishLexerErrorListener method syntaxError.
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
if (!_settings.getDisableUnrecognized()) {
return;
}
StringBuilder sb = new StringBuilder();
BatfishParser parser = _combinedParser.getParser();
BatfishLexer lexer = _combinedParser.getLexer();
List<String> ruleNames = Arrays.asList(parser.getRuleNames());
ParserRuleContext ctx = parser.getContext();
String ruleStack = ctx.toString(ruleNames);
sb.append("lexer: " + _grammarName + ": line " + line + ":" + charPositionInLine + ": " + msg + "\n");
sb.append("Current rule stack: '" + ruleStack + "'.\n");
if (ctx.getStart() != null) {
sb.append("Current rule starts at: line: " + ctx.getStart().getLine() + ", col " + ctx.getStart().getCharPositionInLine() + "\n");
}
sb.append("Parse tree for current rule:\n");
sb.append(ParseTreePrettyPrinter.print(ctx, _combinedParser) + "\n");
sb.append("Lexer mode: " + lexer.getMode() + "\n");
sb.append("Lexer state variables:\n");
sb.append(lexer.printStateVariables());
// collect context from text
String text = _combinedParser.getInput();
String[] lines = text.split("\n", -1);
int errorLineIndex = line - 1;
int errorContextStartLine = Math.max(errorLineIndex - _settings.getMaxParserContextLines(), 0);
int errorContextEndLine = Math.min(errorLineIndex + _settings.getMaxParserContextLines(), lines.length);
sb.append("Error context lines:\n");
for (int i = errorContextStartLine; i < errorLineIndex; i++) {
sb.append(String.format("%-11s%s\n", " " + (i + 1) + ":", lines[i]));
}
sb.append(String.format("%-11s%s\n", ">>>" + (errorLineIndex + 1) + ":", lines[errorLineIndex]));
for (int i = errorLineIndex + 1; i <= errorContextEndLine && i < lines.length; i++) {
sb.append(String.format("%-11s%s\n", " " + (i + 1) + ":", lines[i]));
}
String error = sb.toString();
if (_settings.getThrowOnLexerError()) {
throw new DebugBatfishException("\n" + error);
} else {
_combinedParser.getErrors().add(error);
}
}
Aggregations