ANTLR/语法问题:计算器语言 [英] ANTLR/Grammar issue: calculator language

查看:100
本文介绍了ANTLR/语法问题:计算器语言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为个人项目创建布尔表达式语言/语法.用户将能够使用类似Java的语法编写字符串,并提供变量,这些变量将在变量初始化后的稍后时间进行评估. 雨 例如,用户可能输入字符串

I'm attempting to create a boolean expression language/grammar for a personal project. The user will be able to write a string in a Java-like syntax, with provision for variables, which will be evaluated at a later time when the variables have been initialised. Rain For example, a user might enter the string

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

稍后,当变量FOO初始化为6且BAR等于1时,表达式的计算结果为13> 24,因此返回false.

Later, when the variable FOO is initialised and equal to 6, and BAR is equal to 1, the expression evaluates to 13>24 and thus returns false.

我正在使用ANTLRworks生成语法,尽管看起来不错,但它不能正确解释负号. ANTLRworks中的输入已更改(由于某种原因):(8-3)> 6"读为(8> 6"(由于缺少右括号而无法运行).我尚未实现变量查找,但是这里是到目前为止仅整数的语法:

I'm using ANTLRworks to generate the grammar and whilst it LOOKS fine, it doesn't correctly interpret negative signs. The input in the ANTLRworks is (for some reason) changed: "(8-3)>6" is read as "(8>6" (which fails to run as it is missing the closing bracket). I haven't implemented the variable lookups yet, but here is the grammar so far for just integers:

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'+
;

对于除-"号以外的所有内容,它均正常工作.有人知道解决此问题的方法吗?

It is working correctly for everything except the '-' sign. Does anyone know a way to fix this?

也(我是ANTLR的新手):我是否正确进行了评估?还是我应该让语法定义结构并使用另一种方法来确定该语句是对是假?

Also (I'm very new to ANTLR): am I doing the evaluation correctly? Or should I just let the grammar define the structure and use another method to determine if the statement is true/false?

推荐答案

您的语法:

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进行调试!)

(note that I did not change anything else than reformat it a bit, and added an extra println for debugging!)

产生了以下输出:

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

所以,一切似乎都很好.

So, all seems to go fine.

几句话:

  • 您正在使用==!=比较double.请注意以下几点:舍入错误将导致意外的行为(从用户的角度来看...);
  • 在语法操作中使用模运算符可以通过使用反斜杠转义来实现:\%.
  • you're comparing doubles using == and !=. Be careful with that: rounding errors will result in unexpected behavior (from a user's perspective...);
  • using the modulo operator in your grammar actions can be done by escaping it with a backslash: \%.

这篇关于ANTLR/语法问题:计算器语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆