确定字符串是否符合ANTLR4语法

3
如何测试字符串是否符合语法,以查看它是否有效(即未发现错误且不需要进行错误恢复)?
我尝试了这种方法自定义错误策略,但仍然会在控制台上收到像以下这样的消息:

line 1:2 token recognition error at: 'x'

所以我需要一种方式来确保所有错误都导致异常,或者一种不依赖异常的验证输入的方法。

有兴趣获得良好的错误消息的人也可以查看这里 - Brad Mace
2个回答

7
编辑:您看到的是词法分析错误,而不是语法分析错误。您需要更新词法分析器以确保词法分析器无法通过将以下内容作为词法分析器的最后一条规则添加而无法匹配输入字符。这将使错误字符传递给解析器进行处理(报告、恢复等)。
ERR_CHAR : . ;

此外,您需要执行以下一般步骤,这些步骤适用于配置解析器以进行简单字符串识别。

为了使其正常工作,您需要执行两个操作:

首先,禁用默认的错误报告机制。

parser.removeErrorListeners();

第二步,禁用默认的错误恢复机制。
parser.setErrorStrategy(new BailErrorStrategy());

如果您的字符串不匹配,您将会收到一个ParseCancellationException,并且没有其他报告。

如果您不使用解析操作的输出,您可能还希望通过禁用解析树构建来提高识别过程的效率。

parser.setBuildParseTree(false);

一些好的提示(谢谢!),但我对BailErrorStrategy并不完全认同,因为它完全缺乏任何有用的信息。令我惊讶的是,ANTLR在其异常中不包括消息 - 我错过了什么吗? - Brad Mace
@BradMace 我认为那是一个单独的问题,因为这里的问题说“不需要错误......”。按照问题的措辞,BailErrorStrategy 将会做到你所需的一切,并且还能高效地完成它。 - Sam Harwell

1
一个快速而简单的解决方案...
Parser p = new MyParser(myTokenStream);
p.rootRule();

if (p.getNumberOfSyntaxErrors() > 0) {
    throw new RuntimeException("Syntax error!");
}

这对于不会导致解析器混淆的词法错误(例如多余的输入)无法帮助您,因为语法错误的数量仍然为零。
如果您不想处理ErrorListeners并且不关心解析器可以避免某些词法分析错误,则这是一个很好的解决方案。

这并没有解决问题中的任何疑虑。 - Sam Harwell
@SamHarwell 这个问题是如何验证输入...这个解决方案肯定不是万能的解决方案,但检查Parser#getNumberOfSyntaxErrors()的值将有助于验证/否定输入。 - hendryau
1
@SamHarwell 我也在考虑这个问题,除了覆盖Lexer的recover方法重新抛出异常之外,还有其他无法通过这种方式检测到的错误吗? - Brad Mace
1
抱歉最初没有更详细地说明。这种解决方案的问题在于它不会禁用错误报告或错误恢复。即使您考虑了这些因素,对于手头的任务来说,它仍然比必要的慢得多,慢得多。 - Sam Harwell
1
问题不是“如何禁用错误报告”,也不是“如何禁用错误恢复”。问题是“如何验证输入”,我的解决方案提供了一种验证某些输入的方法。我承认这不是最快或最干净的解决方案,但对于一个没有经验的antlr用户来说,它需要更少的代码并且更少容易出错。 - hendryau
@SamHarwell 啊,性能受损是一个合理的缺点。看起来我在错误方面有些不清楚,现在我已经澄清了,但你可能是对的,这是一个单独的问题。 - Brad Mace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接