Tengo una gramática muy simple que se ve así:

grammar Testing;

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

Analiza un carácter de la entrada y comprueba si es igual al carácter b. Si es así, se usa la regla b, y si no, se usa la regla d.

Sin embargo, el árbol de análisis no cumple la expectativa y analiza todo utilizando la primera regla (regla 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)=

En ambos casos se utiliza la regla d. Sin embargo, dado que hay una guardia en la regla d, espero que la regla d falle cuando el primer carácter sea exactamente 'b'.

¿Estoy haciendo algo mal al usar los predicados semánticos?

(Necesito usar predicados semánticos porque necesito analizar un lenguaje donde las palabras clave podrían usarse como identificadores).

Referencia: https://github.com/antlr/antlr4/blob/ master / doc / predicates.md

2
Ultimate Pea 30 jul. 2020 a las 05:28

1 respuesta

La mejor respuesta

_input.LT(int) devuelve Token, y Token.equals(String) siempre devolverá false. Lo que quieres hacer es llamar a getText() en el Token:

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

Sin embargo, a menudo es más fácil manejar las palabras clave como identificadores de esta manera:

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 jul. 2020 a las 06:51