diff --git a/runtime/Java/src/org/antlr/v4/runtime/ParserInterpreter.java b/runtime/Java/src/org/antlr/v4/runtime/ParserInterpreter.java index 4e52cfcd7..f8f68f721 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/ParserInterpreter.java +++ b/runtime/Java/src/org/antlr/v4/runtime/ParserInterpreter.java @@ -218,7 +218,7 @@ public class ParserInterpreter extends Parser { setState(atn.ruleToStopState[p.ruleIndex].stateNumber); getContext().exception = e; getErrorHandler().reportError(this, e); - getErrorHandler().recover(this, e); + recover(e); } break; @@ -271,7 +271,7 @@ public class ParserInterpreter extends Parser { case Transition.SET: case Transition.NOT_SET: if (!transition.matches(_input.LA(1), Token.MIN_USER_TOKEN_TYPE, 65535)) { - _errHandler.recoverInline(this); + recoverInline(); } matchWildcard(); break; @@ -404,4 +404,46 @@ public class ParserInterpreter extends Parser { overrideDecisionInputIndex = tokenIndex; overrideDecisionAlt = forcedAlt; } + + /** Rely on the error handler for this parser but, if no tokens are consumed + * to recover, add an error node. Otherwise, nothing is seen in the parse + * tree. + */ + protected void recover(RecognitionException e) { + int i = _input.index(); + getErrorHandler().recover(this, e); + if ( _input.index()==i ) { + // no input consumed, better add an error node + if ( e instanceof InputMismatchException ) { + InputMismatchException ime = (InputMismatchException)e; + Token tok = e.getOffendingToken(); + int expectedTokenType = ime.getExpectedTokens().getMinElement(); // get any element + String tokenText; + if ( expectedTokenType== Token.EOF ) tokenText = ""; + else tokenText = ""; + + Token errToken = + getTokenFactory().create(new Pair(tok.getTokenSource(), tok.getTokenSource().getInputStream()), + expectedTokenType, tok.getText(), + Token.DEFAULT_CHANNEL, + -1, -1, // invalid start/stop + tok.getLine(), tok.getCharPositionInLine()); + _ctx.addErrorNode(errToken); + } + else { // NoViableAlt + Token tok = e.getOffendingToken(); + Token errToken = + getTokenFactory().create(new Pair(tok.getTokenSource(), tok.getTokenSource().getInputStream()), + Token.INVALID_TYPE, tok.getText(), + Token.DEFAULT_CHANNEL, + -1, -1, // invalid start/stop + tok.getLine(), tok.getCharPositionInLine()); + _ctx.addErrorNode(errToken); + } + } + } + + protected Token recoverInline() { + return _errHandler.recoverInline(this); + } }