3

任意のブール式をサポートする文法を書いています。文法は、後で静的分析ツールを通過するプログラムを表すために使用されます。静的解析ツールには一定の制限があるため、次の書き換えルールを適用したいと考えています。

厳密な不等式はイプシロンで近似されます。

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

[...]それ以外の場合は再帰的に変換します[...]

部分的にできます。

a > bANTLR に書き換えてからになるよう^('>=' a ^('+' b epsilon))に定義してから、ANTLRにと との両方を自動的に書き換えさせることはできません。a != b^('||' ^('>' a b) ^('<' a b))^('>' 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 に答える