处理 ANTLR4 中的错误
当解析器不知道该怎么做时,默认行为是将消息打印到终端,如下所示:
第 1 行:23 在“}”处缺少小数
这是一个好信息,但在错误的地方。我宁愿把这个作为例外。
我尝试过使用 ,但这会抛出一个没有消息(由 一个 引起,也没有消息)。BailErrorStrategy
ParseCancellationException
InputMismatchException
有没有办法让它通过异常报告错误,同时保留消息中的有用信息?
以下是我真正想要的 - 我通常使用规则中的操作来构建对象:
dataspec returns [DataExtractor extractor]
@init {
DataExtractorBuilder builder = new DataExtractorBuilder(layout);
}
@after {
$extractor = builder.create();
}
: first=expr { builder.addAll($first.values); } (COMMA next=expr { builder.addAll($next.values); })* EOF
;
expr returns [List<ValueExtractor> values]
: a=atom { $values = Arrays.asList($a.val); }
| fields=fieldrange { $values = values($fields.fields); }
| '%' { $values = null; }
| ASTERISK { $values = values(layout); }
;
然后,当我调用解析器时,我会执行如下操作:
public static DataExtractor create(String dataspec) {
CharStream stream = new ANTLRInputStream(dataspec);
DataSpecificationLexer lexer = new DataSpecificationLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DataSpecificationParser parser = new DataSpecificationParser(tokens);
return parser.dataspec().extractor;
}
我真正想要的只是
- 用于在无法解析输入时引发异常(理想情况下为选中的异常)的调用
dataspec()
- 使该异常具有有用的消息,并提供对发现问题的行号和位置的访问
然后,我会让该异常将调用堆栈冒泡到最适合向用户呈现有用消息的位置 - 就像我处理断开的网络连接,读取损坏的文件等一样。
我确实看到操作现在在ANTLR4中被认为是“高级的”,所以也许我正在以一种奇怪的方式做事,但我还没有研究过“非高级”的方式会是什么,因为这种方式已经很好地满足了我们的需求。