我想在ANTLR3中实现一个“分支”。
我想用
branch[boolean is_a]
: ({ $is_a}? => a)
| ({!$is_a}? => b);
会做的伎俩,但我得到编译错误“无法找到符号”和“非法启动类型”,因为在生成的源中,即DFA45.specialStateTransition(...)
没有参数is_a
我尝试省略=>
¹,和/或省略$
的{{1}}。
第一组$is_a
和a
并不是不相交的。
实际上b
的类型为b
。
¹)因为我不理解((C) => c) | a
和{...}? => ...
答案 0 :(得分: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 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?