3

我想在 ANTLR3 中实现一个“分支”。

我想用

branch[boolean is_a]
    : ({ $is_a}? => a)
    | ({!$is_a}? => b);

会做的伎俩,但我得到编译错误“找不到符号”和“类型的非法开始”,因为在生成的源中,即DFA45.specialStateTransition(...)没有参数is_a

我尝试省略=>¹,和/或省略$of $is_a

第一组ab不是不相交的。

实际上b是类型((C) => c) | a

¹)因为我不明白和之间的{...}? => ...区别{...}? ...

4

1 回答 1

4

我不是 100% 确定您为什么会收到该错误:我需要查看您的整个语法。无论如何,没有必要同时检查is_a !is_a。并且两者$is_a都是is_a有效的。

假设您正在解析一个数字列表,并且每第 4 个数字,您想通过不同的“分支”进行处理。一个语法看起来像:

grammar T;

parse
@init{int n = 1;}
  :  (number[n\%4 == 0] {n++;})+ EOF
  ;


number [boolean multipleOf4]
  :  {multipleOf4}?=> Int {System.out.println("branch A -> " + $Int.text);}
  |                   Int {System.out.println("branch B :: " + $Int.text);}
  ;

Int
  :  '0'..'9'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

(请注意,这%是 ANTLR 语法中的保留字符(但不在字符串文字和注释中),因此需要使用反斜杠转义)

并且可以用类进行测试:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("11 22 33 44 55 66 77 88 99");
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);
        parser.parse();
    }
}

现在生成解析器/词法分析器(A),编译所有源文件(B)并运行主类(C):

java -cp antlr-3.2.jar org.antlr.Tool Tg // A
javac -cp antlr-3.2.jar *.java // B
java -cp .:antlr-3.2.jar Main // C

(在 Windows 上,通过 do 运行它java -cp .;antlr-3.2.jar Main

产生以下输出:

B分公司::11
B分公司::22
B分公司::33
分支 A -> 44
B分公司::55
B分公司::66
B分公司::77
分支 A -> 88
B分店::99

所以,是的,在这种情况下,您需要一个“门控语义谓词”{boolean}?=>),而不是“验证语义谓词”{boolean}?)。这两个谓词之间的区别在之前的 SO Q&A 中进行了解释:什么是 ANTLR 中的“语义谓词”?

于 2011-02-11T07:48:34.230 回答