ANTLR3:参数和语义谓词(“找不到符号”,“非法启动类型”)

时间:2011-02-11 02:57:28

标签: antlr antlr3

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

我想用

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

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

我尝试省略=>¹,和/或省略$的{​​{1}}。

第一组$is_aa并不是不相交的。

实际上b的类型为b

¹)因为我不理解((C) => c) | a{...}? => ...

之间的区别

1 个答案:

答案 0 :(得分:4)

我不是100%肯定你为什么会得到这个错误:我需要看到你的整个语法。无论如何,无需检查is_a !is_a$is_ais_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 T.g // A
javac -cp antlr-3.2.jar *.java            // B
java -cp .:antlr-3.2.jar Main             // C

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

运行它

产生以下输出:

branch B :: 11
branch B :: 22
branch B :: 33
branch A -> 44
branch B :: 55
branch B :: 66
branch B :: 77
branch A -> 88
branch B :: 99

所以,是的,在这种情况下你需要一个“门控语义谓词”{boolean}?=>),而不是“验证语义谓词”({{ 1}})。两个谓词之间的差异在之前的SO Q& A中解释:What is a 'semantic predicate' in ANTLR?