异常报告和恢复
重定向错误信息
默认情况下,ANTLR输出异常采用的是标准输出,不过我们可以通过实现ANTLRErrorListener
来达到修改输出异常位置的目的
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.Nullable;
import java.util.*;
public class TestE_Listener {
public static class VerboseListener extends BaseErrorListener {
@Override
public void syntaxError(Recognizer, ?> recognizer,
Object offendingSymbol,
int line, int charPositionInLine,
String msg,
RecognitionException e)
{
List stack = ((Parser)recognizer).getRuleInvocationStack();
Collections.reverse(stack);
System.err.println("rule stack: "+stack);
System.err.println("line "+line+":"+charPositionInLine+" at "+
offendingSymbol+": "+msg);
}
}
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
SimpleLexer lexer = new SimpleLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SimpleParser parser = new SimpleParser(tokens);
parser.removeErrorListeners(); // remove ConsoleErrorListener
parser.addErrorListener(new VerboseListener()); // add ours
parser.prog(); // parse as usual
}
}
定制异常处理程序
import org.antlr.v4.runtime.*;
public class BailErrorStrategy extends DefaultErrorStrategy {
/** Instead of recovering from exception e, rethrow it wrapped
* in a generic RuntimeException so it is not caught by the
* rule function catches. Exception e is the "cause" of the
* RuntimeException.
*/
@Override
public void recover(Parser recognizer, RecognitionException e) {
throw new RuntimeException(e);
}
/** Make sure we don't attempt to recover inline; if the parser
* successfully recovers, it won't throw an exception.
*/
@Override
public Token recoverInline(Parser recognizer)
throws RecognitionException
{
throw new RuntimeException(new InputMismatchException(recognizer));
}
/** Make sure we don't attempt to recover from problems in subrules. */
@Override
public void sync(Parser recognizer) { }
}
import org.antlr.v4.runtime.*;
public class TestBail {
public static class BailSimpleLexer extends SimpleLexer {
public BailSimpleLexer(CharStream input) { super(input); }
public void recover(LexerNoViableAltException e) {
throw new RuntimeException(e); // Bail out
}
}
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
BailSimpleLexer lexer = new BailSimpleLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SimpleParser parser = new SimpleParser(tokens);
parser.setErrorHandler(new BailErrorStrategy());
parser.prog();
}
}
import org.antlr.v4.runtime.*;
public class MyErrorStrategy extends DefaultErrorStrategy {
@Override
public void reportNoViableAlternative(Parser parser,
NoViableAltException e)
throws RecognitionException
{
// ANTLR generates Parser subclasses from grammars and
// Parser extends Recognizer. Parameter parser is a
// pointer to the parser that detected the error
String msg = "can't choose between alternatives"; // nonstandard msg
parser.notifyErrorListeners(e.getOffendingToken(), msg, e);
}
}