ANTLR 中的布尔和算术表达式语法 [英] boolean and arithmetic expression grammar in ANTLR

查看:33
本文介绍了ANTLR 中的布尔和算术表达式语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write a grammar for arithmetic and boolean expressions. I don't understand what I'm doing wrong. For my grammar, ANTLR says:

[fatal] 规则 logic_atom 具有非 LL(*) 决定,因为可以从 alts 1,2 访问递归规则调用.通过左因子分解或使用句法谓词或使用 backtrack=true 选项来解决.

[fatal] rule logic_atom has non-LL(*) decision due to recursive rule invocations reachable from alts 1,2. Resolve by left-factoring or using syntactic predicates or using backtrack=true option.

但我不能做左因子分解.而且我不想碰arith_expr,因为为此我有一个代码.

But I can't do a left-factoring. And I don't want to touch arith_expr, because for this I have a code.

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)=> 不起作用.

推荐答案

考虑将您的 logic_exprcmp_expr 更改为:

Consider changing your logic_expr and cmp_expr to this:

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,因为它掩盖了您得到的错误并且不会增加价值.

I removed the rule logic_atom because it obscures the error that you're getting and doesn't add value.

通过使用 cmp_expr 中的句法谓词,您可以告诉 ANTLR 任何后跟逻辑符号的 arith_expr 只会后跟 arith_expr,这意味着 ANTLR 遇到的任何括号都必须属于算术表达式而不是逻辑表达式.

By using the syntactic predicate in cmp_expr, you're able to tell ANTLR that any arith_expr followed by a logic sign will only be followed by an arith_expr, which means that any parentheses that ANTLR encounters must belong to an arithmetic expression and not a logical one.

这确保了 logic_expr 只处理布尔值,而 arith_expr 只处理数值.

This ensures that logic_expr only deals with boolean values and arith_expr only deals with numeric values.

我使用修改后的语法测试了各种场景,在 ANTLRWorks 或我的自定义测试代码中没有出现错误.你能发布更多关于你所看到的信息吗?

I tested various scenarios with the modified grammar and I'm not getting errors in ANTLRWorks or in my custom test code. Could you post more information about what you're seeing?

这是我使用的完整语法.请注意,我删除了 language 以便我可以在 Java 中测试它.这应该没问题,因为没有动作/语义谓词.我也做了一些小改动,但我不认为它们会是严重的修复.它们用注释表示.

Here is the full grammar I'm using. Note that I removed the language so that I could test this in Java. This should be fine since there are no actions/semantic predicates. I also made a few small changes, but I don't expect them to be serious fixes. They're denoted with comments.

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

<小时>

给定输入x=(2<3),生成如下AST树:

(= x (< 2 3))

呈现如下:

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

The modified grammar can also handle more complex cases now, like x = 2 + 3 < 4 || (5 ^ 5 > 30 && 3 == 10 + 2):

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

所以尝试复制上面的语法,看看是否能解决您遇到的错误.如果没有,请告诉我更多有关您所看到的错误的信息.

So try copying the grammar above and seeing if that fixes the error you get. If not, let me know more about the error you're seeing.

这篇关于ANTLR 中的布尔和算术表达式语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆