Antlr 帮助左分解语法以删除左递归

Antlr 帮助左分解语法以删除左递归,antlr,grammar,left-recursion,Antlr,Grammar,Left Recursion,我有一个小型的自定义脚本语言,我正在尝试更新它以允许布尔表达式,例如a>2和a>2和(b5)。这是我在这里遇到麻烦的插入式表达 这里有一个完整的语法(根据@Bart Kiers的答案从原始帖子开始编辑)展示了这个问题。这是我实际语法的精简版本,但问题也出现在这里 grammar test; options { language = 'JavaScript'; output = AST; } statement : value_assignment_sta

我有一个小型的自定义脚本语言,我正在尝试更新它以允许布尔表达式,例如
a>2
a>2和(b<3或c>5)
。这是我在这里遇到麻烦的插入式表达

这里有一个完整的语法(根据@Bart Kiers的答案从原始帖子开始编辑)展示了这个问题。这是我实际语法的精简版本,但问题也出现在这里

grammar test;


options {
    language = 'JavaScript'; 
    output = AST;
} 


statement 
    :   value_assignment_statement  
        EOF
    ;


value_assignment_statement 
    :   IDENT
        '='
        expression                      
    ;

value_expression 
    :   value_list_expression           
    |   IDENT                           
    ;


value_list_expression 
    :   value_enumerated_list       
    ;


value_enumerated_list : '{' unary+ '}'
    ;



term 
    :   LPAREN expression RPAREN        
    |   INTEGER                         
    |   value_expression                
    ;

unary : ( '+' | '-' )* term
    ;

mult :  unary ( ('*' | '/') unary)*
    ;

expression : mult ( ('+' | '-') mult )*
    ;


boolean 
    :   boolean_expression
        EOF
    ;

boolean_expression
    :   boolean_or_expression
    ;

boolean_or_expression 
    :   boolean_and_expression (OR boolean_and_expression)*
    ;

boolean_and_expression 
    :   boolean_rel_expression (AND boolean_rel_expression)*
    ;

boolean_rel_expression
    :   boolean_neg_expression relational_operator boolean_neg_expression
    ;

boolean_neg_expression 
    :   (NOT)? atom
    ;

atom
    :   LPAREN boolean_expression RPAREN
    //| expression
    ;


relational_operator : '=' | '>' | '<';


LPAREN      :   '(';
RPAREN      :   ')';
AND         :   'and';
OR          :   'or';
NOT         :   'not';
IDENT       :   LETTER LETTER+;
INTEGER     :   DIGIT+;
WS          :   (' ' | '\n' | '\r' | '\t')+     { $channel = HIDDEN; };

fragment DIGIT      : '0'..'9';
fragment LETTER     : ('a'..'z' | 'A'..'Z');
语法测试;
选择权{
语言='JavaScript';
输出=AST;
} 
陈述
:值\赋值\语句
EOF
;
赋值语句
:IDENT
'='
表情
;
值表达式
:值\列表\表达式
|识别
;
值\列表\表达式
:值\u枚举\u列表
;
值枚举列表:“{”一元+“}”
;
学期
:LPAREN表达式RPAREN
|整数
|值表达式
;
一元:(“+”|“-”)*项
;
mult:一元((“*”|“/”)一元)*
;
表达式:mult(“+”|“-”)mult)*
;
布尔值
:布尔表达式
EOF
;
布尔表达式
:布尔\u或\u表达式
;
布尔表达式
:布尔型_和_表达式(或布尔型_和_表达式)*
;
布尔_与_表达式
:布尔表达式(和布尔表达式)*
;
布尔表达式
:布尔表达式关系运算符布尔表达式
;
布尔负表达式
:(不是)?原子
;
原子
:LPAREN布尔表达式RPAREN
//|表情
;
关系_运算符:'='|'>'|'3和(xyz<5或xyz>10)
。当我尝试使用@Bart的答案作为模型时,它运行良好,直到我尝试将
语句使用的语法部分与
布尔值使用的语法部分合并。它们都应该能够使用
表达式
,但这就是我遇到这个左递归错误的地方


那么,如何既处理括号又避免左递归问题呢?

布尔表达式与加法和乘法表达式完全相同,因此不应与它们分开。下面介绍如何解释所有类型的表达式:

grammar test;

parse
  :  expression EOF
  ;

expression 
  :  or
  ;

or
  :  and (OR and)*
  ;

and
  :  rel (AND rel)*
  ;

rel
  :  add (('=' | '>' | '<') add)*
  ;

add
  :  mult (('+' | '-') mult)*
  ;

mult
  :  unary (('*' | '/') unary)*
  ;

unary 
  :  '-' term
  |  '+' term
  |  NOT term
  |  term
  ;

term 
  :  INTEGER  
  |  IDENT       
  |  list
  |  '(' expression ')'
  ;

list 
  :  '{' (expression (',' expression)*)? '}'
  ;

AND     :  'and';
OR      :  'or';
NOT     :  'not';
IDENT   :  LETTER LETTER*;
INTEGER :  DIGIT+;
WS      :  (' ' | '\n' | '\r' | '\t')+  { $channel = HIDDEN; };

fragment DIGIT   : '0'..'9';
fragment LETTER  : ('a'..'z' | 'A'..'Z');
语法测试;
作语法分析
:表达式EOF
;
表情
:或
;
或
:及(或及)*
;
和
:rel(和rel)*
;
雷尔

:add(“=”|“>”|“您的
表达式
符号是否有括号表达式的规则?@larsmans:它可以表示计算为数字的括号表达式,例如
(3+x)*2
但不适合我现在所做的布尔运算。谢谢你的回复。这对我来说是有意义的,当单独使用时。我现在发现问题在于这个布尔运算相关的东西如何与我语法中其他基于表达式的东西交互。我用我的真实语法的子集编辑了我的原始帖子,其中这就是问题所在。@Chris,看看我修改过的答案。非常感谢更新。我想把它们分开的主要原因是,在某些上下文中,我希望输入只能支持某种关系比较。在语法中,只有一个根,
a+3
始终是有效的输入,但有些是我不想这样。所以,在我的使用案例中,我想说布尔和你在答案开头所说的加法/乘法表达式不一样。有什么原因让我认为它们是愚蠢的吗?@Chris,我不完全确定你想做什么。但你不能照我的建议去做吗(或非常类似)并在评估(浏览AST)时,执行某些检查,以查看AST中的特定位置是否允许使用某些表达式。如果您不能选择此选项,请编辑您的原始问题(或发布新问题),并给出几个显示问题的示例输入源。祝您好运。
abc > 3 and (xyz < 5 or xyz > {1, 2, 3})