private void bail(Parser recognizer, Exception exc, String additionalHint)
throws ParseCancellationException
{
RecognitionException re = (RecognitionException)exc.getCause();
int offendingState = re.getOffendingState();
Token offendingToken = re.getOffendingToken();
int offendingTokenType = offendingToken.getType();
String msg = getErrorMessage(offendingState, offendingTokenType);
StringBuilder sb = new StringBuilder();
sb.append(introductionLine());
sb.append("\n");
// TODO add line, column
if (msg != null) {
sb.append("Possible issue: ");
sb.append(msg);
sb.append("\n");
}
sb.append(additionalHint);
underlineError(sb, recognizer, offendingToken);
throw new ParseCancellationException(
sb.toString(),
exc.getCause()
);
}
@Override public void recover(Parser recognizer, RecognitionException e)
throws ParseCancellationException
{
try {
super.recover(recognizer, e);
checkState(false);
} catch (Exception exc) {
bail(recognizer, exc, "");
}
}
@Override public Token recoverInline(Parser recognizer)
throws ParseCancellationException
{
String additionalHint = "";
// per {@link DefaultErrorStrategy#singleTokenDeletion}, {@link BailErrorStrategy#recoverInline}:
Token currentSymbol = recognizer.getCurrentToken();
int nextTokenType = recognizer.getInputStream().LA(2);
IntervalSet expecting = getExpectedTokens(recognizer);
if ( expecting.contains(nextTokenType) ) {
String s = currentSymbol.getType() == -1 ? "EOF" : ruleNames()[currentSymbol.getType()-1];
additionalHint += String.format("Maybe the token %s should be removed.\n", s);
}
// attempt to conjure a token, {@link DefaultErrorStrategy#getMissingSymbol}
int missingTokenType = expecting.getSingleElement();
if (missingTokenType != Token.INVALID_TYPE && missingTokenType != -1) {