2011-03-01 95 views
1

我試圖爲個人項目創建一個布爾表達式語言/語法。用戶將能夠以類似Java的語法編寫一個字符串,併爲變量提供條件,這些變量將在稍後變量初始化時進行評估。 雨 例如,用戶可以輸入字符串ANTLR /語法問題:計算器語言

@FOO+7 > 4*([email protected]); 

以後,當變量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非常陌生):我是否正確地進行評估?或者我應該讓語法定義結構並使用另一種方法來確定該語句是否爲真/假?

回答

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(); 
    } 
} 

所以,一切似乎都很好。

一對夫婦的言論:

    你比較使用 ==!= double小號
  • 。小心:舍入錯誤會導致意外的行爲(從用戶的角度來看......);
  • 在語法操作中使用模運算符可以通過使用反斜槓進行轉義來完成:\%
+0

嗯。這將教會我相信自動化測試工具。不知道發生了什麼,但它在Java中工作,但不在ANTLRworks中。 – Trasvi 2011-03-01 15:09:37

+0

@Trasvi,ANTLRWorks是一個很好的工具,可以將您的語法形象化並對其進行編輯,但這是我唯一曾經使用過的語言:從不用於測試目的(不幸的是,太麻煩了,不支持謂詞)。 – 2011-03-01 15:15:47