如何解决要匹配的 ANTLR 解析器规则:x 和/或 y 和/或 z 以任何顺序
使用 ANTLR,有没有一种方法可以编写解析器规则,以便它可以在不编写 Java 的情况下以任何顺序表达:x 和/或 y 和/或 z。例如,它应该匹配:“x y”、“y z”和“x y z”,但不匹配“x x y”。我能想到的最好的规则是下面的规则,但是我需要在树行者中检查“x x y”。
context = {'latestPost': latest}
解决方法
虽然你可以做一些类似于:
rule: x
| y
| z
| x y
| y x
| x z
| z x
| y z
| z y
| x y z
| x z y
| y x z
| y z x
| z x y
| z y x;
或者(不那么荒谬):
rule: x? y? z?
| x? z? y?
| y? x? z?
| y? z? x?
| z? x? y?
| z? y? x?
;
我怀疑您的示例比您的实际应用程序简单得多,而且这种方法会变得太乏味(这已经变得很荒谬了)。
您也可以使用语义谓词来研究某些东西,但这会将您的语法锁定到特定的目标语言。 (它也会使你的语法复杂化。)
总的来说,我发现 ANTLR 用户(一般来说是解析器编写者)经常过于努力地将“所有规则”编码到语法中。
这看起来不错,但它会导致语法的很多复杂性,并导致“不太理想”的错误消息(因为它们来自解析器 (ANTLR) 本身)。>
我认为你会发现最好保持一个像你一样的规则,它会创建一个 ParseTree 来准确地表示解释(也就是“解析”)输入的正确方法。然后,您将这样的规则视为语义关注点(而不是句法关注点(解析器的领域))。
这意味着您将编写类似验证侦听器之类的内容,它会针对您的解析树运行,并且您可以多次检查相同子规则的使用情况。如果您遇到它,您可以编写一个对最终用户更有用的非常具体的错误消息。
,我能想到的最好的办法是......
grammar Sandbox;
@members {
boolean a,b,c;
}
start: ( 'test' test )+ EOF ;
test:
{a=b=c=true;} // Reset
( {a}? a {a=false;}
| {b}? b {b=false;}
| {c}? c {c=false;}
)* ;
a: 'a';
b: 'b';
c: 'c';
WS : [ \t\r\n]+ -> skip ;
和测试驱动程序...
package sandbox;
import org.antlr.v4.runtime.*;
public class Main {
public static void main(String[] args) {
new Main();
}
private Main() {
System.out.println("Should be OK...");
test("test a b c test c test c b a test c");
System.out.println("Should fail...");
test("test c a a");
}
private void test(String toTest) {
final CharStream cs = CharStreams.fromString(toTest);
final SandboxLexer lexer = new SandboxLexer(cs);
final CommonTokenStream tokens = new CommonTokenStream(lexer);
final SandboxParser parser = new SandboxParser(tokens);
parser.start();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。