Я отправил этот вопрос на anltr-интереса, и Андрей Харитонкин ответил. Барт K наполовину прав; вам нужно переопределить restoreFromMismatchedSet (), но также recoverFromMismatchedToken ().
Если вы также хотите, чтобы лексер завершил работу при первой ошибке, есть вики-страница, объясняющая, что делать:
http://www.antlr.org/wiki/pages/viewpage.action?pageId=5341217
Вкратце, говорится, что:
- Если вы хотите выбросить RecognitionException (или что-либо, наследуемое от Exception), то вам нужно выполнить хитрые Java-трюки, потому что соответствующие методы не объявляют никаких исключений
- Если можно сгенерировать RuntimeException или Error, вы можете либо переопределить nextToken (), чтобы сгенерировать исключение, вместо вызова recoveryError (), либо переопределить recoveryError (). бросить исключение.
Вот пример грамматики, которая возникает при первой ошибке лексера или синтаксического анализатора:
grammar Test;
@parser::members {
public static void main(String[] args) throws Exception {
String text = args[0];
ANTLRStringStream in = new ANTLRStringStream(text);
TestLexer lexer = new TestLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
System.out.println(new TestParser(tokens).mainRule());
}
@Override
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
throw new MismatchedTokenException(ttype, input);
}
@Override
public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
throw e;
}
}
@rulecatch {
catch (RecognitionException e) {
throw e;
}
}
@lexer::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException(e);
}
}
mainRule returns [List<String> words]
@init{$words = new ArrayList<String>();}
: w=Atom {$words.add($w.text);} (',' w=Atom {$words.add($w.text);} )* EOF
;
Atom: '0' | '1';
WS : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
Пример вывода:
C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,0"
[1, 0]
C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,,0"
Exception in thread "main" MismatchedTokenException(6!=4)
at TestParser.recoverFromMismatchedToken(TestParser.java:45)
at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:115)
at TestParser.mainRule(TestParser.java:86)
at TestParser.main(TestParser.java:40)
C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,+0"
Exception in thread "main" java.lang.RuntimeException: NoViableAltException('+@[])
at TestLexer.reportError(TestLexer.java:16)
at org.antlr.runtime.Lexer.nextToken(Lexer.java:94)
at org.antlr.runtime.CommonTokenStream.fillBuffer(CommonTokenStream.java:119) at org.antlr.runtime.CommonTokenStream.LT(CommonTokenStream.java:238)
at org.antlr.runtime.Parser.getCurrentInputSymbol(Parser.java:54)
at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:104)
at TestParser.mainRule(TestParser.java:68)
at TestParser.main(TestParser.java:40)
Caused by: NoViableAltException('+'@[])
at TestLexer.mTokens(TestLexer.java:165)
at org.antlr.runtime.Lexer.nextToken(Lexer.java:84)
... 6 more