ANTLR中的布尔和算术表达式语法 [英] boolean and arithmetic expression grammar in 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_expr
和cmp_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屋!