我正在尝试为个人项目创建一个布尔表达式语言/语法。用户将能够以类似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很新):我正在进行正确的评估吗?或者我应该让语法定义结构并使用另一种方法来确定语句是否为true / false?
答案 0 :(得分: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
和==
对!=
进行比较。请注意:舍入错误将导致意外行为(从用户的角度来看......); \%
。