【问题标题】:Alternatives in ANTLR rewrite ruleANTLR 重写规则中的替代方案
【发布时间】:2012-08-28 02:51:38
【问题描述】:

我正在编写一个支持任意布尔表达式的语法。文法用来表示一个程序,稍后通过静态分析工具传递。静态分析工具有一定的局限性,所以我想应用以下重写规则:

严格不等式用 epsilon 逼近:

expression_a > expression_b -> expression_a >= expression_b + EPSILON

不等式使用“或”语句近似:

expression_a != expression_b -> expression_a > expression_b || expression_a < expression_b

有没有使用 ANTLR 的简单方法?目前我的语法是这样的:

comparison          : expression ('=='^|'<='^|'>='^|'!='^|'>'^|'<'^) expression;

我不确定如何根据运算符应用不同的重写规则。如果运算符是 ("==", "="),我想保持原样,否则根据上面定义的规则递归转换它。

【问题讨论】:

    标签: parsing antlr


    【解决方案1】:

    [...] 否则递归转换它,[...]

    您可以部分完成。

    您不能告诉 ANTLR 将a &gt; b 重写为^('&gt;=' a ^('+' b epsilon)),然后将a != b 定义为^('||' ^('&gt;' a b) ^('&lt;' a b)),然后让ANTLR 自动将^('&gt;' a b)^('&lt;' a b) 重写为^('&gt;=' a ^('+' b epsilon)) 和@987654334 @ 分别。

    这里需要一些手工工作。诀窍是你不能只使用像&gt;= 这样的令牌,如果这个令牌实际上没有被解析。解决此问题的方法是使用imaginary tokens

    快速演示:

    grammar T;
    
    options {
      output=AST;
    }
    
    tokens {
      AND;
      OR;
      GTEQ;
      LTEQ;
      SUB;
      ADD;
      EPSILON;
    }
    
    parse
     : expr
     ;
    
    expr
     : logical_expr
     ;
    
    logical_expr
     : comp_expr ((And | Or)^ comp_expr)*
     ;
    
    comp_expr
     : (e1=mult_expr -> $e1) ( Eq   e2=mult_expr -> ^(AND ^(GTEQ $e1 $e2) ^(LTEQ $e1 $e2))
                             | LtEq e2=mult_expr -> ^(LTEQ $e1 $e2)
                             | GtEq e2=mult_expr -> ^(GTEQ $e1 $e2)
                             | NEq  e2=mult_expr -> ^(OR ^(GTEQ $e1 ^(ADD $e2 EPSILON)) ^(LTEQ $e1 ^(SUB $e2 EPSILON)))
                             | Gt   e2=mult_expr -> ^(GTEQ $e1 ^(ADD $e2 EPSILON))
                             | Lt   e2=mult_expr -> ^(LTEQ $e1 ^(SUB $e2 EPSILON))
                             )?
     ;
    
    add_expr
     : mult_expr ((Add | Sub)^ mult_expr)*
     ;
    
    mult_expr
     : atom ((Mult | Div)^ atom)*
     ;
    
    atom
     : Num
     | Id
     | '(' expr ')'
     ;
    
    Eq    : '==';
    LtEq  : '<=';
    GtEq  : '>=';
    NEq   : '!=';
    Gt    : '>';
    Lt    : '<';
    Or    : '||';
    And   : '&&';
    Mult  : '*';
    Div   : '/';
    Add   : '+';
    Sub   : '-';
    Num   : '0'..'9'+ ('.' '0'..'9'+)?;
    Id    : ('a'..'z' | 'A'..'Z')+;
    Space : ' ' {skip();};
    

    从上面的语法生成的解析器将产生以下内容:


    a == b


    a != b


    a &gt; b


    a &lt; b


    【讨论】:

    • 非常感谢!不知道您可以在一个语句中使用多个重写规则。 (顺便说一句,你如何生成这些图表?ANTLRWorks?)
    • @cheshire,不客气。是的,AST 图像来自 ANTLRWorks 的调试器(不是解释器!)。你也可以通过代码生成它们,看这个问答:stackoverflow.com/questions/2856612/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多