Document ANTLRErrorListener and DiagnosticErrorListener (fixes #265)

This commit is contained in:
Sam Harwell 2013-06-01 21:54:24 -05:00
parent f1f134c962
commit 780b7ac4ce
3 changed files with 154 additions and 29 deletions

View File

@ -31,6 +31,8 @@
package org.antlr.v4.runtime; package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable; import org.antlr.v4.runtime.misc.Nullable;
@ -80,36 +82,102 @@ public interface ANTLRErrorListener {
String msg, String msg,
@Nullable RecognitionException e); @Nullable RecognitionException e);
/** Called when the parser detects a true ambiguity: an input /**
* sequence can be matched literally by two or more pass through * This method is called by the parser when a full-context prediction
* the grammar. ANTLR resolves the ambiguity in favor of the * results in an ambiguity.
* alternative appearing first in the grammar. The start and stop * <p/>
* index are zero-based absolute indices into the token * When {@code exact} is {@code true}, <em>all</em> of the alternatives in
* stream. ambigAlts is a set of alternative numbers that can * {@code ambigAlts} are viable, i.e. this is reporting an exact ambiguity.
* match the input sequence. This method is only called when we * When {@code exact} is {@code false}, <em>at least two</em> of the
* are parsing with full context. * alternatives in {@code ambigAlts} are viable for the current input, but
*/ * the prediction algorithm terminated as soon as it determined that at
void reportAmbiguity(@NotNull Parser recognizer, * least the <em>minimum</em> alternative in {@code ambigAlts} is viable.
DFA dfa, int startIndex, int stopIndex, * <p/>
* When the {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} prediction mode
* is used, the parser is required to identify exact ambiguities so
* {@code exact} will always be {@code true}.
* <p/>
* This method is not used by lexers.
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input input where the ambiguity is reported
* @param exact {@code true} if the ambiguity is exactly known, otherwise
* {@code false}. This is always {@code true} when
* {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} is used.
* @param ambigAlts the potentially ambiguous alternatives
* @param configs the ATN configuration set where the ambiguity was
* determined
*/
void reportAmbiguity(@NotNull Parser recognizer,
@NotNull DFA dfa,
int startIndex,
int stopIndex,
boolean exact, boolean exact,
@NotNull BitSet ambigAlts, @NotNull BitSet ambigAlts,
@NotNull ATNConfigSet configs); @NotNull ATNConfigSet configs);
/**
* This method is called when an SLL conflict occurs and the parser is about
* to use the full context information to make an LL decision.
* <p/>
* If one or more configurations in {@code configs} contains a semantic
* predicate, the predicates are evaluated before this method is called. The
* subset of alternatives which are still viable after predicates are
* evaluated is reported in {@code conflictingAlts}.
* <p/>
* This method is not used by lexers.
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the SLL conflict occurred
* @param conflictingAlts The specific conflicting alternatives. If this is
* {@code null}, the conflicting alternatives are all alternatives
* represented in {@code configs}.
* @param configs the ATN configuration set where the SLL conflict was
* detected
*/
void reportAttemptingFullContext(@NotNull Parser recognizer, void reportAttemptingFullContext(@NotNull Parser recognizer,
@NotNull DFA dfa, @NotNull DFA dfa,
int startIndex, int stopIndex, int startIndex,
int stopIndex,
@Nullable BitSet conflictingAlts, @Nullable BitSet conflictingAlts,
@NotNull ATNConfigSet configs); @NotNull ATNConfigSet configs);
/** Called by the parser when it find a conflict that is resolved /**
* by retrying the parse with full context. This is not a * This method is called by the parser when a full-context prediction has a
* warning; it simply notifies you that your grammar is more * unique result.
* complicated than Strong LL can handle. The parser moved up to * <p/>
* full context parsing for that input sequence. * For prediction implementations that only evaluate full-context
*/ * predictions when an SLL conflict is found (including the default
void reportContextSensitivity(@NotNull Parser recognizer, * {@link ParserATNSimulator} implementation), this method reports cases
@NotNull DFA dfa, * where SLL conflicts were resolved to unique full-context predictions,
int startIndex, int stopIndex, * i.e. the decision was context-sensitive. This report does not necessarily
* indicate a problem, and it may appear even in completely unambiguous
* grammars.
* <p/>
* {@code configs} may have more than one represented alternative if the
* full-context prediction algorithm does not evaluate predicates before
* beginning the full-context prediction. In all cases, the final prediction
* is passed as the {@code prediction} argument.
* <p/>
* This method is not used by lexers.
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the context sensitivity was
* finally determined
* @param prediction the unambiguous result of the full-context prediction
* @param configs the ATN configuration set where the unambiguous prediction
* was determined
*/
void reportContextSensitivity(@NotNull Parser recognizer,
@NotNull DFA dfa,
int startIndex,
int stopIndex,
int prediction, int prediction,
@NotNull ATNConfigSet configs); @NotNull ATNConfigSet configs);
} }

View File

@ -39,15 +39,62 @@ import org.antlr.v4.runtime.misc.Nullable;
import java.util.BitSet; import java.util.BitSet;
/**
* This implementation of {@link ANTLRErrorListener} can be used to identify
* certain potential correctness and performance problems in grammars. "Reports"
* are made by calling {@link Parser#notifyErrorListeners} with the appropriate
* message.
*
* <ul>
* <li><b>Ambiguities</b>: These are cases where more than one path through the
* grammar can match the input.</li>
* <li><b>Weak context sensitivity</b>: These are cases where full-context
* prediction resolved an SLL conflict to a unique alternative which equaled the
* minimum alternative of the SLL conflict.</li>
* <li><b>Strong (forced) context sensitivity</b>: These are cases where the
* full-context prediction resolved an SLL conflict to a unique alternative,
* <em>and</em> the minimum alternative of the SLL conflict was found to not be
* a truly viable alternative. Two-stage parsing cannot be used for inputs where
* this situation occurs.</li>
* </ul>
*
* @author Sam Harwell
*/
public class DiagnosticErrorListener extends BaseErrorListener { public class DiagnosticErrorListener extends BaseErrorListener {
@Override /**
public void reportAmbiguity(@NotNull Parser recognizer, * When {@code true}, only exactly known ambiguities are reported.
DFA dfa, int startIndex, int stopIndex, */
protected final boolean exactOnly;
/**
* Initializes a new instance of {@link DiagnosticErrorListener} which only
* reports exact ambiguities.
*/
public DiagnosticErrorListener() {
this(true);
}
/**
* Initializes a new instance of {@link DiagnosticErrorListener}, specifying
* whether all ambiguities or only exact ambiguities are reported.
*
* @param exactOnly {@code true} to report only exact ambiguities, otherwise
* {@code false} to report all ambiguities.
*/
public DiagnosticErrorListener(boolean exactOnly) {
this.exactOnly = exactOnly;
}
@Override
public void reportAmbiguity(@NotNull Parser recognizer,
DFA dfa,
int startIndex,
int stopIndex,
boolean exact, boolean exact,
@Nullable BitSet ambigAlts, @Nullable BitSet ambigAlts,
@NotNull ATNConfigSet configs) @NotNull ATNConfigSet configs)
{ {
if (!exact) { if (exactOnly && !exact) {
return; return;
} }
@ -62,7 +109,8 @@ public class DiagnosticErrorListener extends BaseErrorListener {
@Override @Override
public void reportAttemptingFullContext(@NotNull Parser recognizer, public void reportAttemptingFullContext(@NotNull Parser recognizer,
@NotNull DFA dfa, @NotNull DFA dfa,
int startIndex, int stopIndex, int startIndex,
int stopIndex,
@Nullable BitSet conflictingAlts, @Nullable BitSet conflictingAlts,
@NotNull ATNConfigSet configs) @NotNull ATNConfigSet configs)
{ {
@ -76,7 +124,8 @@ public class DiagnosticErrorListener extends BaseErrorListener {
@Override @Override
public void reportContextSensitivity(@NotNull Parser recognizer, public void reportContextSensitivity(@NotNull Parser recognizer,
@NotNull DFA dfa, @NotNull DFA dfa,
int startIndex, int stopIndex, int startIndex,
int stopIndex,
int prediction, int prediction,
@NotNull ATNConfigSet configs) @NotNull ATNConfigSet configs)
{ {

View File

@ -36,12 +36,20 @@ import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
/** /**
* This implementation of {@link ANTLRErrorListener} dispatches all calls to a
* collection of delegate listeners. This reduces the effort required to support multiple
* listeners.
*
* @author Sam Harwell * @author Sam Harwell
*/ */
public class ProxyErrorListener implements ANTLRErrorListener { public class ProxyErrorListener implements ANTLRErrorListener {
private final Collection<? extends ANTLRErrorListener> delegates; private final Collection<? extends ANTLRErrorListener> delegates;
public ProxyErrorListener(Collection<? extends ANTLRErrorListener> delegates) { public ProxyErrorListener(Collection<? extends ANTLRErrorListener> delegates) {
if (delegates == null) {
throw new NullPointerException("delegates");
}
this.delegates = delegates; this.delegates = delegates;
} }