2015-08-31 9 views
5

Ich habe eine sehr einfache Test Grammatik, wie folgend:AnTLR4 seltsames Verhalten in Vorrang

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) ; 

Mit dieser Version der Grammatik ich das erwartete Verhalten bekam, wenn ich schreibe den folgenden Code:

b.x + b.y 

ich bekomme einen Baum als (+ (. b x) (. b y))

wenn ich jedoch expression binary_op expression ersetzen durch expression '+' expression ich einen ganz anderen Baum erhalten: (. (+ (. b x) b) y)

Gibt es eine Erklärung dafür?

Dank

Antwort

0

Literale in den Parser Angelegenheiten verwirren können. Überprüfen und beheben Sie die beim Generieren des Parsers gemeldeten Fehler/Warnungen. Wahrscheinlich müssen die Literale von Parser-Regeln in Lexer-Regeln verschoben werden.

Sie können überprüfen, ob der Lexer wie geplant von dumping the token stream funktioniert. Dies liefert eine klare Grundlage, um den Pfad zu verstehen, den der Parser einschlägt.

aktualisieren

Keines der Parsing-Baum-Darstellungen Sie Liste suchen richtige für einen Antlr4 Baum analysieren. Dennoch versucht, beide Varianten Ihrer Grammatik und ich konsequent erhalten:

Token dump:

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] 

Baum dump:

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

mit

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

Die null s in dieser bestimmte Token Dump sind, weil die Symbole zuerst im Parser definiert sind.

+0

Es macht keinen Unterschied, die Literale von Parser-Regeln zu Lexer-Regeln zu verschieben. Ich habe getestet. :) – pinker

0

Sie haben die precendence setzen so etwas wie dies mit:

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

Diese jede Zweideutigkeit auf Operator precendence entfernt.