updated errors to be listener

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6881]
This commit is contained in:
parrt 2010-05-21 17:25:15 -08:00
parent 33c8efe7e5
commit bf92a4bc73
14 changed files with 103 additions and 68 deletions

View File

@ -0,0 +1,6 @@
package org.antlr.v4.runtime;
/** */
public interface ANTLRParserListener {
public void error(RecognitionException msg);
}

View File

@ -32,10 +32,7 @@ import org.antlr.runtime.Token;
import org.antlr.runtime.TokenStream;
import org.antlr.v4.runtime.misc.LABitSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/** A generic recognizer that can handle recognizers generated from
* parser and tree grammars. This is all the parsing
@ -171,8 +168,6 @@ public abstract class BaseRecognizer {
* 3. consume until token found in resynch set
* 4. try to resume parsing
* 5. next match() will reset errorRecovery mode
*
* If you override, make sure to update syntaxErrors if you care about that.
*/
public void reportError(RecognitionException e) {
// if we've already reported an error and have not matched a token
@ -184,15 +179,7 @@ public abstract class BaseRecognizer {
state.syntaxErrors++; // don't count spurious
state.errorRecovery = true;
displayRecognitionError(this.getTokenNames(), e);
}
public void displayRecognitionError(String[] tokenNames,
RecognitionException e)
{
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
emitErrorMessage(hdr+" "+msg);
notifyListeners(e);
}
/** What error message should be generated for the various
@ -217,7 +204,8 @@ public abstract class BaseRecognizer {
* Override this to change the message generated for one or more
* exception types.
*/
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
public String getErrorMessage(RecognitionException e) {
String[] tokenNames = getTokenNames();
String msg = e.getMessage();
if ( e instanceof UnwantedTokenException ) {
UnwantedTokenException ute = (UnwantedTokenException)e;
@ -337,11 +325,6 @@ public abstract class BaseRecognizer {
return "'"+s+"'";
}
/** Override this method to change where error messages go */
public void emitErrorMessage(String msg) {
System.err.println(msg);
}
/** Recover from an error found on the input stream. This is
* for NoViableAlt and mismatched symbol exceptions. If you enable
* single token insertion and deletion, this will usually not
@ -589,7 +572,7 @@ public abstract class BaseRecognizer {
RecognitionException e = null;
// if next token is what we are looking for then "delete" this token
if ( mismatchIsUnwantedToken(ttype) ) {
e = new UnwantedTokenException(ttype, state.input);
e = new UnwantedTokenException(this, ttype);
/*
System.err.println("recoverFromMismatchedToken deleting "+
((TokenStream)input).LT(1)+
@ -607,12 +590,12 @@ public abstract class BaseRecognizer {
// can't recover with single token deletion, try insertion
if ( mismatchIsMissingToken(follow) ) {
Object inserted = getMissingSymbol(e, ttype, follow);
e = new MissingTokenException(ttype, state.input, inserted);
e = new MissingTokenException(this, ttype, inserted);
reportError(e); // report after inserting so AW sees the token in the exception
return inserted;
}
// even that didn't work; must throw the exception
e = new MismatchedTokenException(ttype, state.input);
e = new MismatchedTokenException(this, ttype);
throw e;
}
@ -867,4 +850,52 @@ public abstract class BaseRecognizer {
System.out.println();
}
/* In v3, programmers altered error messages by overriding
displayRecognitionError() and possibly getTokenErrorDisplay().
They overrode emitErrorMessage(String) to change where the output goes.
Now, in v4, we're going to use a listener mechanism. This makes it
easier for language applications to have parsers notify them
upon error without having to override the parsers. If you don't specify
a listener, ANTLR calls the v3 legacy displayRecognitionError()
method. All that does is format a message and call emitErrorMessage().
Otherwise, your listener will receive RecognitionException
exceptions and you can do what ever you want with them including
reproducing the same behavior by calling the legacy methods.
(In v4, RecognitionException includes the recognizer object).
Grammar tools can have a listeners without having to worry about
messing up the programmers' error handling.
*/
public void displayRecognitionError(RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e);
emitErrorMessage(hdr+" "+msg);
}
/** Override this method to change where error messages go */
public void emitErrorMessage(String msg) {
System.err.println(msg);
}
public void addListener(ANTLRParserListener pl) {
if ( state.listeners==null ) {
state.listeners =
Collections.synchronizedList(new ArrayList<ANTLRParserListener>(2));
}
if ( pl!=null ) state.listeners.add(pl);
}
public void removeListener(ANTLRParserListener pl) { state.listeners.remove(pl); }
public void removeListeners() { state.listeners.clear(); }
public List<ANTLRParserListener> getListeners() { return state.listeners; }
public void notifyListeners(RecognitionException re) {
if ( state.listeners==null || state.listeners.size()==0 ) {
// call legacy v3 func; this calls emitErrorMessage(String msg)
displayRecognitionError(re);
return;
}
for (ANTLRParserListener pl : state.listeners) pl.error(re);
}
}

View File

@ -27,8 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
/** The recognizer did not match anything for a (..)+ loop. */
public class EarlyExitException extends RecognitionException {
public int decisionNumber;
@ -36,8 +34,8 @@ public class EarlyExitException extends RecognitionException {
/** Used for remote debugger deserialization */
public EarlyExitException() {;}
public EarlyExitException(int decisionNumber, IntStream input) {
super(input);
public EarlyExitException(BaseRecognizer recognizer, int decisionNumber) {
super(recognizer);
this.decisionNumber = decisionNumber;
}
}

View File

@ -27,8 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
/** A semantic predicate failed during validation. Validation of predicates
* occurs when normally parsing the alternative just like matching a token.
* Disambiguating predicate evaluation occurs when we hoist a predicate into
@ -41,11 +39,11 @@ public class FailedPredicateException extends RecognitionException {
/** Used for remote debugger deserialization */
public FailedPredicateException() {;}
public FailedPredicateException(IntStream input,
public FailedPredicateException(BaseRecognizer recognizer,
String ruleName,
String predicateText)
{
super(input);
super(recognizer);
this.ruleName = ruleName;
this.predicateText = predicateText;
}

View File

@ -27,15 +27,14 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
import org.antlr.v4.runtime.misc.LABitSet;
public class MismatchedNotSetException extends MismatchedSetException {
/** Used for remote debugger deserialization */
public MismatchedNotSetException() {;}
public MismatchedNotSetException(LABitSet expecting, IntStream input) {
super(expecting, input);
public MismatchedNotSetException(BaseRecognizer recognizer, LABitSet expecting) {
super(recognizer, expecting);
}
public String toString() {

View File

@ -27,16 +27,14 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
public class MismatchedRangeException extends RecognitionException {
public int a,b;
/** Used for remote debugger deserialization */
public MismatchedRangeException() {;}
public MismatchedRangeException(int a, int b, IntStream input) {
super(input);
public MismatchedRangeException(BaseRecognizer recognizer, int a, int b) {
super(recognizer);
this.a = a;
this.b = b;
}

View File

@ -27,7 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
import org.antlr.v4.runtime.misc.LABitSet;
public class MismatchedSetException extends RecognitionException {
@ -36,8 +35,8 @@ public class MismatchedSetException extends RecognitionException {
/** Used for remote debugger deserialization */
public MismatchedSetException() {;}
public MismatchedSetException(LABitSet expecting, IntStream input) {
super(input);
public MismatchedSetException(BaseRecognizer recognizer, LABitSet expecting) {
super(recognizer);
this.expecting = expecting;
}

View File

@ -27,7 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
import org.antlr.runtime.Token;
/** A mismatched char or Token or tree node */
@ -37,8 +36,8 @@ public class MismatchedTokenException extends RecognitionException {
/** Used for remote debugger deserialization */
public MismatchedTokenException() {;}
public MismatchedTokenException(int expecting, IntStream input) {
super(input);
public MismatchedTokenException(BaseRecognizer recognizer, int expecting) {
super(recognizer);
this.expecting = expecting;
}

View File

@ -27,8 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.tree.TreeNodeStream;
/**
*/
public class MismatchedTreeNodeException extends RecognitionException {
@ -37,8 +35,10 @@ public class MismatchedTreeNodeException extends RecognitionException {
public MismatchedTreeNodeException() {
}
public MismatchedTreeNodeException(int expecting, TreeNodeStream input) {
super(input);
public MismatchedTreeNodeException(BaseRecognizer recognizer,
int expecting)
{
super(recognizer);
this.expecting = expecting;
}

View File

@ -27,8 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
/** We were expecting a token but it's not found. The current token
* is actually what we wanted next. Used for tree node errors too.
*/
@ -37,8 +35,8 @@ public class MissingTokenException extends MismatchedTokenException {
/** Used for remote debugger deserialization */
public MissingTokenException() {;}
public MissingTokenException(int expecting, IntStream input, Object inserted) {
super(expecting, input);
public MissingTokenException(BaseRecognizer recognizer, int expecting, Object inserted) {
super(recognizer,expecting);
this.inserted = inserted;
}

View File

@ -28,7 +28,6 @@
package org.antlr.v4.runtime;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.IntStream;
public class NoViableAltException extends RecognitionException {
public String grammarDecisionDescription;
@ -38,19 +37,19 @@ public class NoViableAltException extends RecognitionException {
/** Used for remote debugger deserialization */
public NoViableAltException() {;}
public NoViableAltException(String grammarDecisionDescription,
public NoViableAltException(BaseRecognizer recognizer,
String grammarDecisionDescription,
int decisionNumber,
int stateNumber,
IntStream input)
int stateNumber)
{
super(input);
super(recognizer);
this.grammarDecisionDescription = grammarDecisionDescription;
this.decisionNumber = decisionNumber;
this.stateNumber = stateNumber;
}
public String toString() {
if ( input instanceof CharStream) {
if ( recognizer.state.input instanceof CharStream) {
return "NoViableAltException('"+(char)getUnexpectedType()+"'@["+grammarDecisionDescription+"])";
}
else {

View File

@ -67,8 +67,11 @@ import org.antlr.runtime.tree.TreeNodeStream;
* figure out a fancy report.
*/
public class RecognitionException extends RuntimeException {
/** Who threw the exception? */
public BaseRecognizer recognizer;
/** What input stream did the error occur in? */
public transient IntStream input;
//public transient IntStream input;
/** What is index of token/char were we looking at when the error occurred? */
public int index;
@ -106,8 +109,9 @@ public class RecognitionException extends RuntimeException {
public RecognitionException() {
}
public RecognitionException(IntStream input) {
this.input = input;
public RecognitionException(BaseRecognizer recognizer) {
this.recognizer = recognizer;
IntStream input = recognizer.state.input;
this.index = input.index();
if ( input instanceof TokenStream ) {
this.token = ((TokenStream)input).LT(1);
@ -127,6 +131,10 @@ public class RecognitionException extends RuntimeException {
}
}
// public RecognitionException(IntStream input) {
// this.input = input;
// }
protected void extractInformationFromTreeNodeStream(IntStream input) {
TreeNodeStream nodes = (TreeNodeStream)input;
this.node = nodes.LT(1);
@ -172,11 +180,11 @@ public class RecognitionException extends RuntimeException {
/** Return the token type or char of the unexpected input element */
public int getUnexpectedType() {
if ( input instanceof TokenStream) {
if ( recognizer.state.input instanceof TokenStream) {
return token.getType();
}
else if ( input instanceof TreeNodeStream ) {
TreeNodeStream nodes = (TreeNodeStream)input;
else if ( recognizer.state.input instanceof TreeNodeStream ) {
TreeNodeStream nodes = (TreeNodeStream)recognizer.state.input;
TreeAdaptor adaptor = nodes.getTreeAdaptor();
return adaptor.getType(node);
}

View File

@ -30,6 +30,7 @@ package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
import org.antlr.v4.runtime.misc.QStack;
import java.util.List;
import java.util.Map;
/** The set of fields needed by an abstract recognizer to recognize input
@ -77,6 +78,8 @@ public class RecognizerSharedState {
*/
public Map[] ruleMemo;
List<ANTLRParserListener> listeners;
public RecognizerSharedState() {
this.ctx = new QStack<RuleContext>();
}

View File

@ -27,7 +27,6 @@
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.IntStream;
import org.antlr.runtime.Token;
/** An extra token while parsing a TokenStream */
@ -35,8 +34,8 @@ public class UnwantedTokenException extends MismatchedTokenException {
/** Used for remote debugger deserialization */
public UnwantedTokenException() {;}
public UnwantedTokenException(int expecting, IntStream input) {
super(expecting, input);
public UnwantedTokenException(BaseRecognizer recognizer, int expecting) {
super(recognizer, expecting);
}
public Token getUnexpectedToken() {