2012-12-13 15 views
5

Sto provando a scrivere una grammatica per le espressioni aritmetiche e booleane. Non capisco cosa sto sbagliando. Per la mia grammatica, ANTLR dice:grammatica di espressioni booleane e aritmetiche in ANTLR

La regola [fatale] logic_atom ha una decisione non LL (*) dovuta a invocazioni di regole ricorsive raggiungibili da alts 1,2. Risolvi con il factoring sinistro o usando predicati sintattici o usando l'opzione backtrack = true.

Ma non posso fare a sinistra-factoring. E non voglio toccare arith_expr, perché per questo ho un codice.

Errore in logic_atom : LBR logic_expr RBR | cmp_expr ;

Il mio codice:

grammar ArithmeticInterpreter; 

options { 
    output = AST; 
    language = C; 
} 
//options{greedy=true;}: 

axiom : lines EOF! ; 
lines : line (SEP! line)* ; 
line : (def_var | print_expr | scan_expr)? ; 

def_var : VARIABLE ASSIGMENT^ logic_expr ; 
print_expr : PRINT_KEYW^ arith_expr ; 
scan_expr : SCAN_KEYW^ VARIABLE ; 

arith_expr : ((PLS | MNS)^)? term ((PLS | MNS)^ term)*; 
term  : power ((MLP | DIV)^ power)*; 
power  : atom (options{greedy=true;}: PWR^ power)*; 
atom  : INT | FLOAT | VARIABLE | LBR arith_expr RBR -> ^(arith_expr); 

logic_expr : logic_atom ((OR | AND)^ logic_atom)*; 
logic_atom : LBR logic_expr RBR | cmp_expr ; 
cmp_expr: arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ) arith_expr; 

WS : (' '| '\t'| '\r') {$channel=HIDDEN;}; 

LBR : '(' ; 
RBR : ')' ; 
PLS : '+' ; 
MNS : '-' ; 
MLP : '*' ; 
DIV : '/' ; 
PWR : '^' ; 

LSS : '<' ; 
LSQ : '<=' ; 
GRT : '>' ; 
GRQ : '>=' ; 
EQL : '==' ; 
NEQ : '!=' ; 
AND : '&&' ; 
OR : '||' ; 
NOT : '!' ; 

ASSIGMENT : '=' ; 
PRINT_KEYW : 'print' ; 
SCAN_KEYW : 'scan' ; 

SEP : '\n' | ';' ; 

INT : ('0'..'9')+; 

FLOAT : INT '.' INT* EXP? | '.' INT EXP? | INT EXP; 
fragment EXP : ('e'|'E') (PLS | MNS)? INT; 

VARIABLE : SS (SS | '0'..'9')* ; 
fragment SS : 'a'..'z' | 'A'..'Z' | '_' ; 

// (LBR arith_expr)=> non è un lavoro.

risposta

3

pensare di cambiare il vostro logic_expr e cmp_expr a questo:

logic_expr : cmp_expr ((OR | AND)^ cmp_expr)*; 
cmp_expr : (arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ))=> arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ)^ arith_expr 
      | LBR logic_expr RBR -> logic_expr 
      ; 

ho rimosso la regola logic_atom perché oscura l'errore che state ottenendo e non aggiunge valore.

Utilizzando il predicato sintattico in cmp_expr, siete in grado di dire che qualsiasi ANTLR arith_expr seguito da un segno logica sarà seguita solo da un arith_expr, il che significa che qualsiasi parentesi che ANTLR incontri devono appartenere a un'espressione aritmetica e non logico.

Questo assicura che logic_expr si occupi solo di valori booleani e arith_expr si occupa solo di valori numerici.


ho provato vari scenari con la grammatica modificato e non sto ottenendo gli errori in ANTLRWorks o nel mio codice di prova personalizzato. Potresti pubblicare maggiori informazioni su ciò che stai vedendo?

Ecco la grammatica completa che sto utilizzando. Si noti che ho rimosso il language in modo da poterlo verificare in Java. Questo dovrebbe andare bene poiché non ci sono azioni/predicati semantici. Ho anche apportato alcune piccole modifiche, ma non mi aspetto che siano delle serie correzioni. Sono denotati con commenti.

grammar ArithmeticInterpreter; 

options { 
    output = AST; 
} 
//options{greedy=true;}: 

axiom : lines EOF! ; 
lines : line (SEP! line)* ; 
line : (def_var | print_expr | scan_expr)? ; 

def_var : VARIABLE ASSIGMENT^ logic_expr ; 
print_expr : PRINT_KEYW^ arith_expr ; 
scan_expr : SCAN_KEYW^ VARIABLE ; 

arith_expr : ((PLS | MNS)^)? term ((PLS | MNS)^ term)*; 
term  : power ((MLP | DIV)^ power)*; 
power  : atom (PWR^ atom)*; //<-- changed 
atom  : INT | FLOAT | VARIABLE 
      | LBR arith_expr RBR -> arith_expr //<-- changed 
      ; 

logic_expr : cmp_expr ((OR | AND)^ cmp_expr)*; 
cmp_expr : (arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ))=> arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ)^ arith_expr 
      | LBR logic_expr RBR -> logic_expr 
      ; 

WS : (' '| '\t'| '\r') {$channel=HIDDEN;}; 

LBR : '(' ; 
RBR : ')' ; 
PLS : '+' ; 
MNS : '-' ; 
MLP : '*' ; 
DIV : '/' ; 
PWR : '^' ; 

LSS : '<' ; 
LSQ : '<=' ; 
GRT : '>' ; 
GRQ : '>=' ; 
EQL : '==' ; 
NEQ : '!=' ; 
AND : '&&' ; 
OR : '||' ; 
NOT : '!' ; 

ASSIGMENT : '=' ; 
PRINT_KEYW : 'print' ; 
SCAN_KEYW : 'scan' ; 

SEP : '\n' | ';' ; 

INT : ('0'..'9')+; 

FLOAT : INT '.' INT* EXP? | '.' INT EXP? | INT EXP; 
fragment EXP : ('e'|'E') (PLS | MNS)? INT; 

VARIABLE : SS (SS | '0'..'9')* ; 
fragment SS : 'a'..'z' | 'A'..'Z' | '_' ; 

Dato ingresso x=(2<3), la seguente struttura AST viene prodotto:

(= x (< 2 3)) 

che rende questo modo:

(= x (< 2 3))

La grammatica modificato può anche gestire più complesso casi ora, come x = 2 + 3 < 4 || (5^5 > 30 && 3 == 10 + 2):

(= x (|| (< (+ 2 3) 4) (&& (> (^ 5 5) 30) (== 3 (+ 10 2))))) 

a more complex graph

Quindi provare a copiare la grammatica di cui sopra e vedere se questo risolve l'errore che si ottiene. In caso contrario, fammi sapere di più sull'errore che stai vedendo.

+0

Anche io ci provo. Per questo antlrworks disegnato un albero di errori. Ad esempio: 'x = (1 <2)' disegnato a '(... -> cmp_expr -> NoViableAltExpression)' –

+1

@AlexanderLavrukov Ho aggiornato la risposta con la grammatica che ho usato per i test e alcuni esempi di output. Quando hai tempo, prova a eseguire questa grammatica tu stesso per vedere se ti dà errori. – user1201210

+2

@AlexanderLavrukov, assicurati di non ** usare l'interprete durante i test. Usa invece il debugger. –

1

Il mio suggerimento rapido è quello di combinare arith ed espressioni logiche. Vedi qualsiasi esempio di grammatica come Java.g o qualsiasi altra cosa. ANTLR v4 non avrebbe gestito questo problema, btw.