Compiler construction ANTLR中的布尔和算术表达式语法

Compiler construction ANTLR中的布尔和算术表达式语法,compiler-construction,antlr,grammar,antlr3,Compiler Construction,Antlr,Grammar,Antlr3,我正在写算术和布尔表达式的语法。我不明白我做错了什么。对于我的语法,ANTLR说: [致命]由于可从alts 1,2访问递归规则调用,规则逻辑_atom具有非LL(*)决策。通过左因子分解或使用语法谓词或使用backtrack=true选项进行解析 但我不能做左因子分解。我不想碰算术表达式,因为我有一个代码 logic_atom中的错误:LBR logic_expr RBR | cmp_expr 我的代码: grammar ArithmeticInterpreter; options {

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

[致命]由于可从alts 1,2访问递归规则调用,规则逻辑_atom具有非LL(*)决策。通过左因子分解或使用语法谓词或使用backtrack=true选项进行解析

但我不能做左因子分解。我不想碰算术表达式,因为我有一个代码

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' | '_' ;
语法算术解释器;
选项{
输出=AST;
语言=C;
}
//选项{greedy=true;}:
公理:线EOF;
行:行(九月行)*;
行:(def_var | print|expr | scan|expr);
定义变量:变量分配逻辑表达式;
打印表达式:打印表达式;
scan_expr:scan_KEYW^变量;
第四种解释:((请说明)^)?期限((请填写)^期限)*;
任期:权力((MLP分区)^权力)*;
power:atom(选项{greedy=true;}:PWR^power)*;
atom:INT | FLOAT | VARIABLE | LBR arith_expr RBR->^(arith_expr);
逻辑表达式:逻辑原子((或和)^逻辑原子)*;
逻辑原子:LBR逻辑运算RBR | cmp运算;
cmp|u expr:arith|u expr(LSS | LSQ | GRT | GRQ | EQL | NEQ)arith|u expr;
WS:(“”|’\t’|’\r’{$channel=HIDDEN;};
LBR:'(';
RBR:')';
请:“+”;
MNS:“-”;
MLP:“*”;
分区:“/”;
压水堆:“^”;
LSS:'=';
EQL:'=';
NEQ:“!=”;
及:"&";
或:“| |”;
不是:“!”;
分配:'=';
打印键:“打印”;
扫描键:“扫描”;
SEP:“\n”|“;”;
INT:('0'..'9')+;
浮点:INT'.'INT*EXP?|'.'国际经验国际贸易;
片段扩展:('e'|'e')(PLS | MNS)?INT;
变量:SS(SS |‘0’…‘9’)*;
片段SS:'a'..'z'|'a'..'z'|'|';

//
(LBR arith\u expr)=>
不起作用。

考虑将
逻辑表达式和
cmp\u 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\u atom
,因为它掩盖了您得到的错误,并且没有增加价值

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

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


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

这是我使用的完整语法。请注意,我删除了
语言
,以便可以在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' | '_' ;
语法算术解释器;
选项{
输出=AST;
}
//选项{greedy=true;}:
公理:线EOF;
行:行(九月行)*;
行:(def_var | print|expr | scan|expr);
定义变量:变量分配逻辑表达式;
打印表达式:打印表达式;
scan_expr:scan_KEYW^变量;
第四种解释:((请说明)^)?期限((请填写)^期限)*;
任期:权力((MLP分区)^权力)*;
功率:原子(压水堆^原子)*;//算术表达式//算术表达式(LSS | LSQ | GRT | GRQ | EQL | NEQ)^算术表达式
|LBR逻辑\u expr RBR->逻辑\u expr
;
WS:(“”|’\t’|’\r’{$channel=HIDDEN;};
LBR:'(';
RBR:')';
请:“+”;
MNS:“-”;
MLP:“*”;
分区:“/”;
压水堆:“^”;
LSS:'=';
EQL:'=';
NEQ:“!=”;
及:"&";
或:“| |”;
不是:“!”;
分配:'=';
打印键:“打印”;
扫描键:“扫描”;
SEP:“\n”|“;”;
INT:('0'..'9')+;
浮点:INT'.'INT*EXP?|'.'国际经验国际贸易;
片段扩展:('e'|'e')(PLS | MNS)?INT;
变量:SS(SS |‘0’…‘9’)*;
片段SS:'a'..'z'|'a'..'z'|'|';

给定输入
x=(230&&3==10+2)

(=x(| |)(<(+23)4)(&&(>(^55)30)(==3(+102)()))


因此,试着复制上面的语法,看看这是否能修复您所遇到的错误。如果没有,请让我了解更多有关您看到的错误的信息

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

我也尝试过这个。为此,AntlWorks绘制了一个bug树。例如:
x=(1 cmp\u expr->noviableexpression)
@AlexanderLavrukov我用测试用的语法和一些示例输出更新了答案。当你有时间时,试着自己运行这个语法,看看它是否会给你带来错误。@AlexanderLavrukov,确保你在测试时没有使用解释器。改用调试器。
(= x (< 2 3))
(= x (|| (< (+ 2 3) 4) (&& (> (^ 5 5) 30) (== 3 (+ 10 2)))))