解析器不知道要做什么时的默认行为是将消息打印到终端,例如:
第1:23行在“}”处缺少DECIMAL
这是一个很好的信息,但是在错误的位置。我宁愿将此作为例外。
我尝试使用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中的动作现在被认为是“高级”的,所以也许我正在以一种奇怪的方式来处理事情,但是自从这种方式以来,我没有研究过什么是“非高级”的方式。一直很好地满足我们的需求。