diff --git a/runtime/Java/src/org/antlr/v4/runtime/RecognitionException.java b/runtime/Java/src/org/antlr/v4/runtime/RecognitionException.java index ca62f73e4..14bff66dc 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/RecognitionException.java +++ b/runtime/Java/src/org/antlr/v4/runtime/RecognitionException.java @@ -29,6 +29,7 @@ */ package org.antlr.v4.runtime; +import org.antlr.v4.runtime.atn.DecisionState; import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.Nullable; @@ -39,26 +40,27 @@ import org.antlr.v4.runtime.misc.Nullable; * and what kind of problem occurred. */ public class RecognitionException extends RuntimeException { - /** Who threw the exception? */ - private Recognizer, ?> recognizer; + /** The {@link Recognizer} where this exception originated. */ + @Nullable + private final Recognizer, ?> recognizer; - // TODO: make a dummy recognizer for the interpreter to use? - // Next two (ctx,input) should be what is in recognizer, but - // won't work when interpreting + @Nullable + private final RuleContext ctx; - private RuleContext ctx; + @Nullable + private final IntStream input; - private IntStream input; - - /** The current Token when an error occurred. Since not all streams - * can retrieve the ith Token, we have to track the Token object. - * For parsers. Even when it's a tree parser, token might be set. + /** + * The current {@link Token} when an error occurred. Since not all streams + * support accessing symbols by index, we have to track the {@link Token} + * instance itself. */ private Token offendingToken; - private int offendingState; + private int offendingState = -1; - public RecognitionException(@Nullable Recognizer, ?> recognizer, IntStream input, + public RecognitionException(@Nullable Recognizer, ?> recognizer, + @Nullable IntStream input, @Nullable ParserRuleContext ctx) { this.recognizer = recognizer; @@ -67,7 +69,9 @@ public class RecognitionException extends RuntimeException { if ( recognizer!=null ) this.offendingState = recognizer.getState(); } - public RecognitionException(String message, @Nullable Recognizer, ?> recognizer, IntStream input, + public RecognitionException(String message, + @Nullable Recognizer, ?> recognizer, + @Nullable IntStream input, @Nullable ParserRuleContext ctx) { super(message); @@ -77,11 +81,14 @@ public class RecognitionException extends RuntimeException { if ( recognizer!=null ) this.offendingState = recognizer.getState(); } - /** Where was the parser in the ATN when the error occurred? - * For No viable alternative exceptions, this is the decision state number. - * For others, it is the state whose emanating edge we couldn't match. - * This will help us tie into the grammar and syntax diagrams in - * ANTLRWorks v2. + /** + * Get the ATN state number the parser was in at the time the error + * occurred. For {@link NoViableAltException} and + * {@link LexerNoViableAltException} exceptions, this is the + * {@link DecisionState} number. For others, it is the state whose outgoing + * edge we couldn't match. + *
+ * If the state number is not known, this method returns -1. */ public int getOffendingState() { return offendingState; @@ -91,6 +98,17 @@ public class RecognitionException extends RuntimeException { this.offendingState = offendingState; } + /** + * Gets the set of input symbols which could potentially follow the + * previously matched symbol at the time this exception was thrown. + * + * If the set of expected tokens is not known and could not be computed, + * this method returns {@code null}. + * + * @return The set of token types that could potentially follow the current + * state in the ATN, or {@code null} if the information is not available. + */ + @Nullable public IntervalSet getExpectedTokens() { if (recognizer != null) { return recognizer.getATN().getExpectedTokens(offendingState, ctx); @@ -99,22 +117,52 @@ public class RecognitionException extends RuntimeException { return null; } + /** + * Gets the {@link RuleContext} at the time this exception was thrown. + * + * If the context is not available, this method returns {@code null}. + * + * @return The {@link RuleContext} at the time this exception was thrown. + * If the context is not available, this method returns {@code null}. + */ + @Nullable public RuleContext getCtx() { return ctx; } + /** + * Gets the input stream which is the symbol source for the recognizer where + * this exception was thrown. + * + * If the input stream is not available, this method returns {@code null}. + * + * @return The input stream which is the symbol source for the recognizer + * where this exception was thrown, or {@code null} if the stream is not + * available. + */ + @Nullable public IntStream getInputStream() { return input; } + @Nullable public Token getOffendingToken() { return offendingToken; } - protected final void setOffendingToken(Token offendingToken) { + protected final void setOffendingToken(@Nullable Token offendingToken) { this.offendingToken = offendingToken; } + /** + * Gets the {@link Recognizer} where this exception occurred. + * + * If the recognizer is not available, this method returns {@code null}. + * + * @return The recognizer where this exception occurred, or {@code null} if + * the recognizer is not available. + */ + @Nullable public Recognizer, ?> getRecognizer() { return recognizer; }