Advertisement
Guest User

Untitled

a guest
Aug 31st, 2016
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.11 KB | None | 0 0
  1. package org.nohope.antlr4;
  2.  
  3. import org.antlr.v4.runtime.BailErrorStrategy;
  4. import org.antlr.v4.runtime.FailedPredicateException;
  5. import org.antlr.v4.runtime.InputMismatchException;
  6. import org.antlr.v4.runtime.NoViableAltException;
  7. import org.antlr.v4.runtime.Parser;
  8. import org.antlr.v4.runtime.ParserRuleContext;
  9. import org.antlr.v4.runtime.RecognitionException;
  10. import org.antlr.v4.runtime.Token;
  11. import org.antlr.v4.runtime.TokenStream;
  12. import org.antlr.v4.runtime.misc.ParseCancellationException;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15.  
  16. import javax.annotation.Nonnull;
  17.  
  18. /**
  19. */
  20. public final class VerboseErrorMessagePolicy extends DefaultErrorStrategy {
  21. private static final Logger LOG = LoggerFactory.getLogger(ProperErrorMessagePolicy.class);
  22. private static final String UNKNOWN_RECOGNITION_ERROR_TYPE = "Unknown recognition error type: %s with message: %s";
  23. private static final String ALREADY_REPORTED_ERROR_MESSAGE = "Got an already reported error: %s";
  24. private static final String MISMATCHED_INPUT_ERROR_MESSAGE = "Parse error: mismatched input on line %s:%s. Got a %s but expected %s. Text: \"%s\"";
  25. 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\"";
  26. private static final String TOKEN_DISPLAY_FORMAT = "<%s>";
  27. private static final int STRING_START = 0;
  28.  
  29. private final String originalExpression;
  30.  
  31. public VerboseErrorMessagePolicy(String expression) {
  32. this.originalExpression = expression;
  33. }
  34.  
  35. private static void setExceptionContext(Parser recognizer, RuntimeException e) {
  36. for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
  37. context.exception = (RecognitionException) e;
  38. }
  39. }
  40.  
  41. @Override
  42. public void recover(Parser recognizer, RecognitionException error) {
  43. setExceptionContext(recognizer, error);
  44. LOG.debug("Get a parse exception: ", error);
  45. throw new ParseCancellationException(error);
  46. }
  47.  
  48. @Override
  49. public void reportError(Parser recognizer, RecognitionException error) {
  50. if (inErrorRecoveryMode(recognizer)) {
  51. LOG.debug(String.format(ALREADY_REPORTED_ERROR_MESSAGE, error.getMessage()));
  52. return; // don't report spurious errors
  53. }
  54. beginErrorCondition(recognizer);
  55. if (error instanceof NoViableAltException) {
  56. reportNoViableAlternative(recognizer, (NoViableAltException) error);
  57. } else if (error instanceof InputMismatchException) {
  58. LOG.debug("Input mismatch: ", error);
  59. reportInputMismatch(recognizer, (InputMismatchException) error);
  60. } else if (error instanceof FailedPredicateException) {
  61. LOG.debug("Failed predicate exception: ", error);
  62. reportFailedPredicate(recognizer, (FailedPredicateException) error);
  63. } else {
  64. LOG.error(String.format(UNKNOWN_RECOGNITION_ERROR_TYPE, error.getClass().getName(), error.getMessage()));
  65. recognizer.notifyErrorListeners(error.getOffendingToken(), error.getMessage(), error);
  66. }
  67. }
  68.  
  69. @Override
  70. protected void reportNoViableAlternative(@Nonnull Parser recognizer,
  71. @Nonnull NoViableAltException e) {
  72. String msg = formViableExceptionMessage(e, recognizer);
  73. LOG.debug("Got a non-viable exception {}. Original exception: ", msg, e);
  74. recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e);
  75. throw new ParseCancellationException(msg, e);
  76. }
  77.  
  78. private boolean tokenIsEOF(Token token) {
  79. return getSymbolType(token) == Token.EOF;
  80. }
  81.  
  82. private static String getContext(Parser recognizer, TokenStream tokens) {
  83. String context = tokens.getText(recognizer.getContext());
  84. return context.isEmpty() ? "No context available" : context;
  85. }
  86.  
  87. private String getPieceOfTextWhichContainsError(RecognitionException e) {
  88. return originalExpression.substring(STRING_START, e.getOffendingToken().getStopIndex());
  89. }
  90.  
  91. private String formViableExceptionMessage(NoViableAltException e, Parser recognizer) {
  92. TokenStream tokens = recognizer.getInputStream();
  93. String text = getPieceOfTextWhichContainsError(e);
  94. String context = getContext(recognizer, tokens);
  95. return String.format(VIABLE_ALTERNATIVE_ERROR_MESSAGE,
  96. escapeWSAndQuote(getInputToken(e, tokens)),
  97. e.getOffendingToken().getLine(),
  98. e.getOffendingToken().getCharPositionInLine(),
  99. context, text);
  100. }
  101.  
  102. @Override
  103. public Token recoverInline(Parser recognizer)
  104. throws RecognitionException {
  105. LOG.debug("Got an input mismatch exception");
  106. InputMismatchException e = new InputMismatchException(recognizer);
  107. setExceptionContext(recognizer, e);
  108. reportError(recognizer, e);
  109. throw e;
  110. }
  111.  
  112. private static String getExpectedToken(Parser recognizer, InputMismatchException e) {
  113. return e.getExpectedTokens().toString(recognizer.getTokenNames());
  114. }
  115.  
  116. private static int getCharPositionInLine(InputMismatchException e) {
  117. return e.getOffendingToken().getCharPositionInLine();
  118. }
  119.  
  120. private static int getLine(InputMismatchException e) {
  121. return e.getOffendingToken().getLine();
  122. }
  123.  
  124. private String createErrorMessage(Parser recognizer, InputMismatchException e) {
  125. return String.format(MISMATCHED_INPUT_ERROR_MESSAGE,
  126. getLine(e),
  127. getCharPositionInLine(e),
  128. getTokenErrorDisplay(e.getOffendingToken()),
  129. getExpectedToken(recognizer, e),
  130. getPieceOfTextWhichContainsError(e));
  131. }
  132.  
  133. @Override
  134. protected void reportInputMismatch(@Nonnull Parser recognizer,
  135. @Nonnull InputMismatchException e) {
  136. String msg = createErrorMessage(recognizer, e);
  137. recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e);
  138. throw new ParseCancellationException(msg, e);
  139. }
  140.  
  141. @Override
  142. protected String getTokenErrorDisplay(Token token) {
  143. if (token == null) {
  144. return "<no token>";
  145. }
  146. return escapeWSAndQuote(String.format(TOKEN_DISPLAY_FORMAT, getErrorSymbol(token)));
  147. }
  148.  
  149. private static boolean noTextSymbol(String s) {
  150. return s == null;
  151. }
  152.  
  153. private String getErrorSymbol(Token token) {
  154. String symbol = getSymbolText(token);
  155.  
  156. if (noTextSymbol(symbol)) {
  157. if (tokenIsEOF(token)) {
  158. symbol = "EOF";
  159. } else {
  160. symbol = String.valueOf(getSymbolType(token));
  161. }
  162. }
  163. return symbol;
  164. }
  165.  
  166. private String getInputToken(NoViableAltException e, TokenStream tokens) {
  167. if (tokens != null) {
  168. String input;
  169. if (tokenIsEOF(e.getStartToken())) {
  170. input = "EOF";
  171. } else {
  172. input = tokens.getText(e.getStartToken(), e.getOffendingToken());
  173. }
  174. return input;
  175. }
  176. return "unknown input";
  177. }
  178. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement