gpt4 book ai didi

java - 处理 ANTLR4 中的错误

转载 作者:IT老高 更新时间:2023-10-28 13:53:59 26 4
gpt4 key购买 nike

解析器不知道该做什么时的默认行为是将消息打印到终端,例如:

line 1:23 missing DECIMAL at '}'

这是一条好消息,但发错了地方。我宁愿将其视为异常(exception)。

我尝试使用 BailErrorStrategy,但这会引发 ParseCancellationException 没有消息(由 InputMismatchException 引起,也没有消息)。

有没有办法让它通过异常报告错误,同时保留消息中的有用信息?


这就是我真正追求的——我通常在规则中使用 Action 来构建一个对象:

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() 调用以在无法解析输入时抛出异常(理想情况下是已检查异常)
  • 为该异常提供有用的消息并提供对发现问题的行号和位置的访问权限

然后我会让这个异常在调用堆栈中冒泡到最适合向用户呈现有用消息的地方——就像我处理断开的网络连接、读取损坏的文件等一样。

我确实看到 Action 现在在 ANTLR4 中被认为是“高级”的,所以也许我正在以一种奇怪的方式处理事情,但我还没有研究过这样做的“非高级”方式是什么因为这种方式一直很好地满足我们的需求。

最佳答案

由于我对现有的两个答案有点挣扎,我想分享一下我最终得到的解决方案。

首先,我创建了自己的 ErrorListener 版本,例如 Sam Harwell建议:

public class ThrowingErrorListener extends BaseErrorListener {

public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();

@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
throws ParseCancellationException {
throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg);
}
}

注意使用 ParseCancellationException 而不是 RecognitionException 因为 DefaultErrorStrategy 会捕获后者,并且永远不会到达您自己的代码。

创建一个全新的 ErrorStrategy 像 Brad Mace建议不是必需的,因为默认情况下 DefaultErrorStrategy 会产生非常好的错误消息。

然后我在解析函数中使用自定义的 ErrorListener:

public static String parse(String text) throws ParseCancellationException {
MyLexer lexer = new MyLexer(new ANTLRInputStream(text));
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);

CommonTokenStream tokens = new CommonTokenStream(lexer);

MyParser parser = new MyParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE);

ParserRuleContext tree = parser.expr();
MyParseRules extractor = new MyParseRules();

return extractor.visit(tree);
}

(有关 MyParseRules 作用的更多信息,请参阅 here。)

这将为您提供与默认情况下打印到控制台相同的错误消息,只是以适当的异常形式。

关于java - 处理 ANTLR4 中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18132078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com