我有这样的规则:
declaration returns [RuntimeObject obj]:
DECLARE label value { $obj = new RuntimeObject($label.text, $value.text); };
不幸的是,它在RuntimeObject
构造函数中抛出异常,因为$label.text
为空。检查调试输出和其他一些事情表明,与“label”的匹配实际上失败了,但是Antlr运行时“有帮助”继续匹配,目的是提供更有用的错误消息(http://www.antlr.org/blog/antlr3/error.handling.tml)。
好的,我可以看到这对某些情况有用,但我怎么能告诉Antlr停止这样做呢?来自v2的defaultErrorHandler=false
选项似乎已经消失。
答案 0 :(得分:2)
我对Antlr了解不多,所以这可能偏离基础,但this migration page上标题为“错误处理”的部分看起来很有帮助。
它建议您可以使用@rulecatch { }
完全禁用错误处理,或使用您自己的不尝试恢复的实现覆盖mismatch()
的{{1}}方法。从您的问题描述中,该页面上的示例似乎完全符合您的要求。
答案 1 :(得分:0)
您还可以覆盖reportError(RecognitionException)方法,使其重新抛出异常而不是打印它,如下所示:
@parser::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException(e);
}
}
但是,我不确定你想要这个(或ire_and_curses的解决方案),因为每次解析尝试只会出现一个错误,然后你可以修复,只是为了找到下一个错误。如果你试图恢复(ANTLR没问题)你可以一次尝试多个错误,并修复所有错误。
答案 2 :(得分:0)
您需要覆盖mismatch
和recoverFromMismatchedSet
方法以确保立即抛出异常(示例适用于Java):
@members {
protected void mismatch(IntStream input, int ttype, BitSet follow) throws RecognitionException {
throw new MismatchedTokenException(ttype, input);
}
public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
throw e;
}
}
然后你需要改变解析器处理这些异常的方式,这样它们就不会被吞噬:
@rulecatch {
catch (RecognitionException e) {
throw e;
}
}
(解析器中所有规则匹配方法的主体都将包含在try
块中,并将其作为catch
块。)
为了进行比较,recoverFromMismatchedSet
的默认实现继承自BaseRecognizer
:
public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
if (mismatchIsMissingToken(input, follow)) {
reportError(e);
return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
}
throw e;
}
和默认的rulecatch:
catch (RecognitionException re) {
reportError(re);
recover(input,re);
}