3

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

严格不等式用 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;

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

4

1 回答 1

3

[...] 并以其他方式递归转换它,[...]

你可以部分做。

你不能告诉 ANTLR 重写a > b^('>=' a ^('+' b epsilon))然后定义a != b成为,^('||' ^('>' a b) ^('<' a b))然后让 ANTLR 分别自动重写^('>' a b)和。^('<' a b)^('>=' a ^('+' b epsilon))^('<=' a ^('-' b epsilon))

这里需要一些手工工作。诀窍是你不能只使用一个令牌,就像>=这个令牌实际上没有被解析一样。对此的解决方案是使用虚构的标记

快速演示:

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 > b

在此处输入图像描述


a < b

在此处输入图像描述


于 2012-08-27T18:51:38.883 回答