5

我正在尝试为算术和布尔表达式编写语法。我不明白我做错了什么。对于我的语法,ANTLR 说:

[致命] 由于可从 alts 1,2 访问的递归规则调用,规则 logic_atom 具有非 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' | '_' ;

//(LBR arith_expr)=>不工作。

4

2 回答 2

4

考虑将您的logic_exprand更改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
           ;

我删除了该规则logic_atom,因为它掩盖了您遇到的错误并且没有增加价值。

通过使用 in 的语法谓词cmp_expr,您可以告诉 ANTLR anyarith_expr后面跟着一个逻辑符号只会跟着 an 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' | '_' ;

给定 input x=(2<3),生成以下 AST 树:

(= x (< 2 3))

呈现如下:

(= x (< 2 3))

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

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

更复杂的图

所以试着复制上面的语法,看看是否能解决你得到的错误。如果没有,请让我了解更多有关您看到的错误的信息。

于 2012-12-13T21:31:27.190 回答
1

我的快速建议是结合算术和逻辑表达式。查看任何示例语法,例如 Java.g 或其他。顺便说一句,ANTLR v4 可以解决这个问题。

于 2012-12-13T22:43:30.917 回答