当解析器不知道该做什么时,默认行为是将消息打印到终端,如:
行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中行为被认为是“先进的”,所以也许我正以一种奇怪的方式去做事情,但是我还没有研究什么是“非先进的”方式来做这件事,因为这种方式已经很好地满足了我们的需要。