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

查看:293
本文介绍了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:

[致命]规则logic_atom具有非LL(*)决策,这是由于从alt 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树:


Given input x=(2<3), the following AST tree is produced:

(= 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天全站免登陆