2012-12-13 17 views
5

Ich versuche, eine Grammatik für arithmetische und boolesche Ausdrücke zu schreiben. Ich verstehe nicht, was ich falsch mache. Für meine Grammatik sagt ANTLR:Boolean und arithmetischer Ausdruck Grammatik in ANTLR

[Fatal] Regel Logic_atom hat nicht-LL (*) Entscheidung wegen rekursive Regelaufrufe von alts 1,2 erreichbar. Auflösen durch Links-Factoring oder Verwenden von syntaktischen Prädikaten oder Verwenden der Option backtrack = true.

Aber ich kann nicht eine Links-Factoring machen. Und ich möchte nicht arith_expr berühren, weil ich dafür einen Code habe.

Fehler bei logic_atom : LBR logic_expr RBR | cmp_expr ;

Mein Code:

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)=> wird nicht funktionieren.

Antwort

3

Betrachten Sie Ihre logic_expr und cmp_expr zu diesem Wechsel:

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 
      ; 

ich die Regel entfernt logic_atom, weil sie den Fehler verschleiert, die Sie bekommen, und fügen Sie nicht Wert.

durch die syntaktische Prädikat in cmp_expr verwenden, sind Sie in der Lage ANTLR zu sagen, dass jede arith_expr durch ein logisches Zeichen gefolgt wird nur von einem arith_expr gefolgt werden, was bedeutet, dass alle Klammern, die Begegnungen antlr zu einem arithmetischen Ausdruck gehören muss und nicht logisch.

Dies stellt sicher, dass logic_expr nur mit booleschen Werten und arith_expr nur mit numerischen Werten handelt.


ich verschiedene Szenarien mit der modifizierten Grammatik getestet und ich bin nicht Fehler in ANTLRWorks oder in meinem benutzerdefinierten Testcode zu bekommen. Könnten Sie weitere Informationen über das, was Sie sehen, posten?

Hier ist die volle Grammatik, die ich verwende. Beachten Sie, dass ich die language entfernt habe, so dass ich das in Java testen konnte. Dies sollte in Ordnung sein, da es keine Aktionen/semantischen Prädikate gibt. Ich habe auch ein paar kleine Änderungen vorgenommen, aber ich erwarte nicht, dass sie ernsthafte Korrekturen sind. Sie sind mit Kommentaren gekennzeichnet.

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' | '_' ; 

Bei Eingang x=(2<3), wird die folgende AST Baum produziert:

(= x (< 2 3)) 

Welche macht etwa so:

(= x (< 2 3))

Die modifizierte Grammatik auch komplexere handhaben kann Fälle jetzt, wie x = 2 + 3 < 4 || (5^5 > 30 && 3 == 10 + 2):

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

a more complex graph

versuchen also das Kopieren der Grammatik oben und sehen, ob das den Fehler behebt man bekommt. Wenn nicht, lassen Sie mich mehr über den Fehler wissen, den Sie sehen.

+0

Ich habe das auch probiert. Für diese antlrworks zeichnete einen Fehlerbaum. Zum Beispiel: 'x = (1 <2)' zeichnete ein '(... -> cmp_expr -> NoViableAltExpression)' –

+1

@AlexanderLavrukov Ich aktualisierte die Antwort mit der Grammatik, die ich für das Testen und einige Beispielausgaben verwendete. Wenn Sie Zeit haben, versuchen Sie, diese Grammatik selbst auszuführen, um zu sehen, ob Sie Fehler bekommen. – user1201210

+2

@AlexanderLavrukov, stellen Sie sicher, dass Sie ** nicht ** den Interpreter beim Testen verwenden. Verwenden Sie stattdessen den Debugger. –

1

Mein schneller Vorschlag ist, arith und logische Ausdrücke zu kombinieren. Sehen Sie eine Beispielgrammatik wie Java.g oder was auch immer. ANTLR v4 würde damit kein Problem umgehen, übrigens.

Verwandte Themen