为什么语义谓词在ANTLR4中不起作用

时间:2020-07-30 02:28:15

标签: antlr antlr4

我有一个非常简单的语法,如下所示:

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

1 个答案:

答案 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]*;