Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.nohope.antlr4;
- import org.antlr.v4.runtime.BailErrorStrategy;
- import org.antlr.v4.runtime.FailedPredicateException;
- import org.antlr.v4.runtime.InputMismatchException;
- import org.antlr.v4.runtime.NoViableAltException;
- import org.antlr.v4.runtime.Parser;
- import org.antlr.v4.runtime.ParserRuleContext;
- import org.antlr.v4.runtime.RecognitionException;
- import org.antlr.v4.runtime.Token;
- import org.antlr.v4.runtime.TokenStream;
- import org.antlr.v4.runtime.misc.ParseCancellationException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.annotation.Nonnull;
- /**
- */
- public final class VerboseErrorMessagePolicy extends DefaultErrorStrategy {
- private static final Logger LOG = LoggerFactory.getLogger(ProperErrorMessagePolicy.class);
- private static final String UNKNOWN_RECOGNITION_ERROR_TYPE = "Unknown recognition error type: %s with message: %s";
- private static final String ALREADY_REPORTED_ERROR_MESSAGE = "Got an already reported error: %s";
- private static final String MISMATCHED_INPUT_ERROR_MESSAGE = "Parse error: mismatched input on line %s:%s. Got a %s but expected %s. Text: \"%s\"";
- private static final String VIABLE_ALTERNATIVE_ERROR_MESSAGE = "Parse error: can't find viable alternative at %s(line %s:%s). Rule context: %s. Text: \"%s\"";
- private static final String TOKEN_DISPLAY_FORMAT = "<%s>";
- private static final int STRING_START = 0;
- private final String originalExpression;
- public VerboseErrorMessagePolicy(String expression) {
- this.originalExpression = expression;
- }
- private static void setExceptionContext(Parser recognizer, RuntimeException e) {
- for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
- context.exception = (RecognitionException) e;
- }
- }
- @Override
- public void recover(Parser recognizer, RecognitionException error) {
- setExceptionContext(recognizer, error);
- LOG.debug("Get a parse exception: ", error);
- throw new ParseCancellationException(error);
- }
- @Override
- public void reportError(Parser recognizer, RecognitionException error) {
- if (inErrorRecoveryMode(recognizer)) {
- LOG.debug(String.format(ALREADY_REPORTED_ERROR_MESSAGE, error.getMessage()));
- return; // don't report spurious errors
- }
- beginErrorCondition(recognizer);
- if (error instanceof NoViableAltException) {
- reportNoViableAlternative(recognizer, (NoViableAltException) error);
- } else if (error instanceof InputMismatchException) {
- LOG.debug("Input mismatch: ", error);
- reportInputMismatch(recognizer, (InputMismatchException) error);
- } else if (error instanceof FailedPredicateException) {
- LOG.debug("Failed predicate exception: ", error);
- reportFailedPredicate(recognizer, (FailedPredicateException) error);
- } else {
- LOG.error(String.format(UNKNOWN_RECOGNITION_ERROR_TYPE, error.getClass().getName(), error.getMessage()));
- recognizer.notifyErrorListeners(error.getOffendingToken(), error.getMessage(), error);
- }
- }
- @Override
- protected void reportNoViableAlternative(@Nonnull Parser recognizer,
- @Nonnull NoViableAltException e) {
- String msg = formViableExceptionMessage(e, recognizer);
- LOG.debug("Got a non-viable exception {}. Original exception: ", msg, e);
- recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e);
- throw new ParseCancellationException(msg, e);
- }
- private boolean tokenIsEOF(Token token) {
- return getSymbolType(token) == Token.EOF;
- }
- private static String getContext(Parser recognizer, TokenStream tokens) {
- String context = tokens.getText(recognizer.getContext());
- return context.isEmpty() ? "No context available" : context;
- }
- private String getPieceOfTextWhichContainsError(RecognitionException e) {
- return originalExpression.substring(STRING_START, e.getOffendingToken().getStopIndex());
- }
- private String formViableExceptionMessage(NoViableAltException e, Parser recognizer) {
- TokenStream tokens = recognizer.getInputStream();
- String text = getPieceOfTextWhichContainsError(e);
- String context = getContext(recognizer, tokens);
- return String.format(VIABLE_ALTERNATIVE_ERROR_MESSAGE,
- escapeWSAndQuote(getInputToken(e, tokens)),
- e.getOffendingToken().getLine(),
- e.getOffendingToken().getCharPositionInLine(),
- context, text);
- }
- @Override
- public Token recoverInline(Parser recognizer)
- throws RecognitionException {
- LOG.debug("Got an input mismatch exception");
- InputMismatchException e = new InputMismatchException(recognizer);
- setExceptionContext(recognizer, e);
- reportError(recognizer, e);
- throw e;
- }
- private static String getExpectedToken(Parser recognizer, InputMismatchException e) {
- return e.getExpectedTokens().toString(recognizer.getTokenNames());
- }
- private static int getCharPositionInLine(InputMismatchException e) {
- return e.getOffendingToken().getCharPositionInLine();
- }
- private static int getLine(InputMismatchException e) {
- return e.getOffendingToken().getLine();
- }
- private String createErrorMessage(Parser recognizer, InputMismatchException e) {
- return String.format(MISMATCHED_INPUT_ERROR_MESSAGE,
- getLine(e),
- getCharPositionInLine(e),
- getTokenErrorDisplay(e.getOffendingToken()),
- getExpectedToken(recognizer, e),
- getPieceOfTextWhichContainsError(e));
- }
- @Override
- protected void reportInputMismatch(@Nonnull Parser recognizer,
- @Nonnull InputMismatchException e) {
- String msg = createErrorMessage(recognizer, e);
- recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e);
- throw new ParseCancellationException(msg, e);
- }
- @Override
- protected String getTokenErrorDisplay(Token token) {
- if (token == null) {
- return "<no token>";
- }
- return escapeWSAndQuote(String.format(TOKEN_DISPLAY_FORMAT, getErrorSymbol(token)));
- }
- private static boolean noTextSymbol(String s) {
- return s == null;
- }
- private String getErrorSymbol(Token token) {
- String symbol = getSymbolText(token);
- if (noTextSymbol(symbol)) {
- if (tokenIsEOF(token)) {
- symbol = "EOF";
- } else {
- symbol = String.valueOf(getSymbolType(token));
- }
- }
- return symbol;
- }
- private String getInputToken(NoViableAltException e, TokenStream tokens) {
- if (tokens != null) {
- String input;
- if (tokenIsEOF(e.getStartToken())) {
- input = "EOF";
- } else {
- input = tokens.getText(e.getStartToken(), e.getOffendingToken());
- }
- return input;
- }
- return "unknown input";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement