2015-08-31 38 views
5

Mam bardzo prostą gramatykę testu w następujący sposób:AnTLR4 dziwne zachowanie w pierwszeństwa

grammar Test; 

statement: expression EOF; 

expression 
    : Identifier 
     | expression binary_op expression 
     | expression assignment_operator expression 
     | expression '.' Identifier 
    ; 

binary_op: '+'; 
assignment_operator : '=' ; 

Identifier : [a-zA-Z]+ ; 
WS : [ \n\r\t]+ -> channel(HIDDEN) ; 

Z tej wersji gramatyki dostałem oczekiwane zachowanie jeśli piszę następujący kod:

b.x + b.y 

dostaję drzewa jako (+ (. b x) (. b y))

Jednakże, jeśli mogę wymienić expression binary_op expression przez expression '+' expression uzyskać bardzo różne drzewa: (. (+ (. b x) b) y)

Czy są jakieś wyjaśnienia?

Dzięki

Odpowiedz

0

Literały w parserze mogą wprowadzać w błąd. Sprawdź i napraw błędy/ostrzeżenia zgłoszone podczas generowania analizatora składni. Prawdopodobnie musisz przenieść literały z reguł parsera do reguł leksykalnych.

Możesz sprawdzić, czy lexer działa zgodnie z zamierzeniami przez dumping the token stream. Zapewni to jasną podstawę do zrozumienia ścieżki, którą bierze parser.

Aktualizacja

Ani drzewa reprezentacji parse wyświetlić listę wyglądać właściwa dla analizowania drzewa Antlr4. Niemniej jednak, próbował oba warianty swojej gramatyki i konsekwentnie dostać:

Reklamowe przegubowe:

Identifier: [@0,0:0='b',<4>,1:0] 
Dot: [@1,1:1='.',<3>,1:1] 
Identifier: [@2,2:2='x',<4>,1:2] 
null: [@4,4:4='+',<1>,1:4] 
Identifier: [@6,6:6='b',<4>,1:6] 
Dot: [@7,7:7='.',<3>,1:7] 
Identifier: [@8,8:8='y',<4>,1:8] 

Drzewo przegubowe:

(statement (expression (expression (expression (expression b) . x) + (expression b)) . y) <EOF>) 

użyciu

ParseTree tree = parser.statement(); 
System.out.print(tree.toStringTree(parser)); 

The null S w ten konkretny zrzut tokenów, ponieważ symbole są najpierw zdefiniowane w analizatorze składni.

+0

Nie powoduje różnic w przesuwaniu literałów z reguł parsera do reguł leksykalnych. Testowałem. :) – pinker

0

Musisz ustawić precendence używając coś takiego:

expr : expr2 (assignment_operator expr3)? # Equals 
expr2 : expr1 (binary_op expr2)?   # Add 
expr1 : Identifier | 
     expr1 . Identifier 
     ; 

ta usuwa wszystkie niejasności na precendence operatora.