2015-08-31 21 views
5

Ho un grammatica molto semplice test come segue:AnTLR4 strano comportamento in precedenza

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

Con questa versione della grammatica ho ottenuto il comportamento previsto se scrivo il seguente codice:

b.x + b.y 

ottengo un albero come (+ (. b x) (. b y))

Tuttavia, se sostituisco expression binary_op expression da expression '+' expression ho un albero molto diverso: (. (+ (. b x) b) y)

C'è qualche spiegazione per questo?

Grazie

risposta

0

letterali nel parser può confondere le cose. Controlla e correggi gli errori/gli avvisi riportati nella generazione del parser. Probabilmente è necessario spostare i letterali dalle regole del parser alle regole del lexer.

È possibile verificare che il lexer funzioni come previsto da dumping the token stream. Ciò fornirà una base chiara per comprendere il percorso che sta prendendo il parser.

Aggiornamento

Nessuna delle rappresentazioni albero sintattico vi elenco un'occhiata adeguata per un albero di analizzare Antlr4. Ciò nonostante, provato entrambe le varianti della tua grammatica e ho sempre ottengo:

discarica provvisoria: discarica

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] 

Albero:

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

utilizzando

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

Le null s in questo un particolare deposito di token è dovuto al fatto che i simboli vengono prima definiti nel parser.

+0

Non fa differenza spostare i valori letterali dalle regole del parser alle regole del lexer. Ho provato :) – pinker

0

è necessario impostare la precendenza utilizzando qualcosa di simile:

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

Ciò elimina ogni ambiguità sul dell'operatore precendenza.