1

個人的なプロジェクトのためにブール式の言語/文法を作成しようとしています。ユーザーは、後で変数が初期化されたときに評価される変数を提供して、Javaのような構文で文字列を書くことができます。雨たとえば、ユーザーが文字列を入力する場合があります

@FOO+7 > 4*(5+@BAR);

その後、変数FOOが初期化されて6に等しく、BARが1に等しい場合、式は13> 24と評価され、falseを返します。

私はANTLRworksを使用して文法を生成していますが、見た目は問題ありませんが、負の符号を正しく解釈していません。ANTLRworksの入力が(何らかの理由で)変更されました。「(8-3)> 6」は「(8> 6」として読み取られます(閉じ括弧がないため実行に失敗します)。実装していません。変数はまだ検索されていますが、これまでのところ整数のみの文法は次のとおりです。

grammar BooleanCalculator;

@header {
package test;
}

prog    : rule+
;

rule    : boolean_expr ';' NEWLINE {System.out.println($boolean_expr.b);}
| NEWLINE
;

boolean_expr returns [boolean b]
: v1=num_statement 
('<'  v2=num_statement {$b = $v1.d <  $v2.d;}
|'<=' v2=num_statement {$b = $v1.d <= $v2.d;}
|'='  v2=num_statement {$b = $v1.d == $v2.d;}
|'!=' v2=num_statement {$b = !($v1.d == $v2.d);}
|'>=' v2=num_statement {$b = $v1.d >= $v2.d;}
|'>'  v2=num_statement {$b = $v1.d >  $v2.d;})
;

num_statement returns [double d]
: v1=mult_statement {$d = $v1.d;}
('+' v2=mult_statement {$d += $v2.d;}
|'-' v2=mult_statement {$d -= $v2.d;})* //HERE IS THE OFFENDING LINE
;

mult_statement returns [double d]
: v1=var {$d = $v1.d;}
('*' v2=var {$d *= $v2.d;}
|'/' v2=var {$d /= $v2.d;}
|'%' v2=var {$d = $d/100*$v2.d;})*
;

var returns [double d]
: NUMBER {$d = Double.parseDouble($NUMBER.text);}
| '(' v1=num_statement ')' {$d = $v1.d;}
;

NUMBER  : '0'..'9'+
;

'-'記号以外はすべて正しく機能しています。誰かがこれを修正する方法を知っていますか?

また(私はANTLRに非常に慣れていません):私は正しく評価を行っていますか?または、文法で構造を定義し、別の方法を使用してステートメントが真か偽かを判断する必要がありますか?

4

1 に答える 1

3

あなたの文法:

grammar BooleanCalculator;

prog    
  :  rule+
  ;

rule
  :  boolean_expr {System.out.println($boolean_expr.b);}
  ;

boolean_expr returns [boolean b]
  : v1=num_statement ( '<'  v2=num_statement {$b = $v1.d < $v2.d;}
                     | '<=' v2=num_statement {$b = $v1.d <= $v2.d;}
                     | '='  v2=num_statement {$b = $v1.d == $v2.d;}
                     | '!=' v2=num_statement {$b = !($v1.d == $v2.d);}
                     | '>=' v2=num_statement {$b = $v1.d >= $v2.d;}
                     | '>'  v2=num_statement {$b = $v1.d > $v2.d;}  {System.out.println("v1=" + $v1.d + ", v2=" + $v2.d);}
                     )
  ;

num_statement returns [double d]
  :  v1=mult_statement {$d = $v1.d;} ( '+' v2=mult_statement {$d += $v2.d;}
                                     | '-' v2=mult_statement {$d -= $v2.d;}
                                     )* 
  ;

mult_statement returns [double d]
: v1=var {$d = $v1.d;} ( '*' v2=var {$d *= $v2.d;}
                       | '/' v2=var {$d /= $v2.d;}
                       | '%' v2=var {$d = $d/100*$v2.d;}
                       )*
;

var returns [double d]
  : NUMBER {$d = Double.parseDouble($NUMBER.text);}
  | '(' v1=num_statement ')' {$d = $v1.d;}
  ;

NUMBER  
  :  '0'..'9'+
  ;

(少し再フォーマットする以外は何も変更せずprintln、デバッグ用に追加したことに注意してください!)

次の出力を生成しました。

$ java -cp antlr-3.2.jar org.antlr.Tool BooleanCalculator.g 
$ javac -cp antlr-3.2.jar *.java
$ java -cp .:antlr-3.2.jar Main

v1=5.0, v2=6.0
false

テストクラスの使用:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("(8-3)>6");
        BooleanCalculatorLexer lexer = new BooleanCalculatorLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        BooleanCalculatorParser parser = new BooleanCalculatorParser(tokens);
        parser.prog();
    }
}

だから、すべてうまくいくようです。

いくつかの意見:

  • とを使用してdoublesを比較しています。注意してください。丸め誤差は、(ユーザーの観点からは...)予期しない動作を引き起こします。==!=
  • 文法アクションでモジュロ演算子を使用するには、バックスラッシュでエスケープします\%
于 2011-03-01T13:14:38.493 に答える