Mam bardzo prostą gramatykę, która wygląda tak:

grammar Testing;

a :  d | b;
b : {_input.LT(1).equals("b")}? C;
d : {!_input.LT(1).equals("b")}? C;
C : .;

Parasuje jeden znak z wejścia i sprawdza, czy jest równa postaci b. Jeśli tak, stosuje się regułę B, a jeśli nie stosuje się rządzenia D.

Jednak drzewo analizy nie spełnia oczekiwań i analizuje wszystko za pomocą pierwszej reguły (zasada 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)=

W obu przypadkach stosowana jest reguła D. Jednakże, ponieważ istnieje strażnik w zasadzie D, spodziewam się, że zasada d nie powiedzie się, gdy pierwsza postać jest dokładnie "b".

Czy robię coś złego, gdy używasz predykatów semantycznych?

(Muszę użyć predykatów semantycznych, ponieważ muszę przeanalizować język, w którym słowa kluczowe mogłyby być używane jako identyfikatory).

Odniesienie: https://github.com/antlr/antlr4/blob/ Master / Doc / Predicate.md

2
Ultimate Pea 30 lipiec 2020, 05:28

1 odpowiedź

Najlepsza odpowiedź

_input.LT(int) zwraca Token i Token.equals(String) zawsze powróci false. Co chcesz zrobić, to zadzwoń getText() na Token:

b : {_input.LT(1).getText().equals("b")}? C;
d : {!_input.LT(1).getText().equals("b")}? C;

Jednak często łatwiej jest obsługiwać identyfikatorów słów kluczowych w taki sposób:

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]*;
3
Bart Kiers 30 lipiec 2020, 06:51