我有一个非常简单的语法,如下所示:
grammar Testing;
a : d | b;
b : {_input.LT(1).equals("b")}? C;
d : {!_input.LT(1).equals("b")}? C;
C : .;
它从输入中解析一个字符,并检查它是否等于字符b。如果是,则使用规则b,否则,使用规则d。
但是,解析树无法实现期望,并使用第一个规则(规则d)来解析所有内容。
$ antlr Testing.g4
$ javac *.java
$ grun Testing a -trace (base)
c
enter a, LT(1)=c
enter d, LT(1)=c
consume [@0,0:0='c',<1>,1:0] rule d
exit d, LT(1)=
exit a, LT(1)=
$ grun Testing a -trace (base)
b
enter a, LT(1)=b
enter d, LT(1)=b
consume [@0,0:0='b',<1>,1:0] rule d
exit d, LT(1)=
exit a, LT(1)=
在两种情况下,都使用规则d。但是,由于规则d有警惕,我希望规则d在第一个字符正好是'b'时会失败。
使用语义谓词时我做错什么了吗?
(我需要使用语义谓词,因为我需要解析一种可以将关键字用作标识符的语言。)
参考:https://github.com/antlr/antlr4/blob/master/doc/predicates.md
答案 0 :(得分:3)
_input.LT(int)
返回一个Token
,而Token.equals(String)
将始终返回false
。您要做的是在getText()
上致电Token
:
b : {_input.LT(1).getText().equals("b")}? C;
d : {!_input.LT(1).getText().equals("b")}? C;
但是,通常以这种方式处理关键字即标识符很容易:
rule
: KEYWORD_1 identifier
;
identifier
: IDENTIFIER
| KEYWORD_1
| KEYWORD_2
| KEYWORD_3
;
KEYWORD_1 : 'k1';
KEYWORD_2 : 'k2';
KEYWORD_3 : 'k3';
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]*;