Ale*_*kov 5 compiler-construction grammar antlr antlr3
我正在尝试为算术和布尔表达式编写语法.我不明白我做错了什么.对于我的语法,ANTLR说:
[致命]规则logic_atom由于从alts 1,2可到达的递归规则调用而具有非LL(*)决策.通过左因子分解或使用语法谓词或使用backtrack = true选项来解析.
但我不能做左派因素.而且我不想触摸arith_expr,因为为此,我有一个代码.
错误 logic_atom : LBR logic_expr RBR | cmp_expr ;
我的代码:
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' | '_' ;
Run Code Online (Sandbox Code Playgroud)
// (LBR arith_expr)=>不行.
考虑将您的logic_expr和更改cmp_expr为:
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
;
Run Code Online (Sandbox Code Playgroud)
我删除了该规则logic_atom,因为它掩盖了您收到的错误并且不会增加价值。
通过使用 中的句法谓词cmp_expr,您可以告诉 ANTLR,任何arith_expr后跟逻辑符号的后面都只会跟着一个arith_expr,这意味着 ANTLR 遇到的任何括号都必须属于算术表达式而不是逻辑表达式。
这确保logic_expr只处理布尔值并且arith_expr只处理数值。
我使用修改后的语法测试了各种场景,并且在 ANTLRWorks 或自定义测试代码中没有收到错误。您能否发布有关您所看到内容的更多信息?
这是我正在使用的完整语法。请注意,我删除了language以便我可以在 Java 中测试它。这应该没问题,因为没有动作/语义谓词。我还做了一些小改动,但我不认为它们会成为严重的修复。它们用注释表示。
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' | '_' ;
Run Code Online (Sandbox Code Playgroud)
给定输入x=(2<3),将生成以下 AST 树:
(= x (< 2 3))
Run Code Online (Sandbox Code Playgroud)
其渲染如下:

修改后的语法现在还可以处理更复杂的情况,例如x = 2 + 3 < 4 || (5 ^ 5 > 30 && 3 == 10 + 2):
(= x (|| (< (+ 2 3) 4) (&& (> (^ 5 5) 30) (== 3 (+ 10 2)))))
Run Code Online (Sandbox Code Playgroud)

因此,请尝试复制上面的语法,看看是否可以修复您遇到的错误。如果没有,请让我更多地了解您所看到的错误。