有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在ANTLR中递归处理规则

好的,两天后我的第三个ANTLR问题:

我的语法是用来解析布尔语句的,比如:

AGE > 21 AND AGE < 35

因为这是一个相对简单的语法,所以我嵌入了代码,而不是使用AST。规则如下:

: a=singleEvaluation { $evalResult = $a.evalResult;} 
(('AND') b=singleEvaluation {$evalResult = $evalResult && $b.evalResult;})+
{
// code
}
;

现在我需要使用括号实现操作顺序,来解析如下内容:

AGE >= 21 AND (DEPARTMENT=1000 OR DEPARTMENT=1001)

甚至更糟:

AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001))

有人能提出一种实现所需递归的方法吗?我不想在这么晚的时候换成AST,在这一点上我还是一个相对的noob

杰森


共 (2) 个答案

  1. # 1 楼答案

    由于一些规则的计算结果是布尔值,而另一些规则的计算结果是整数(或仅比较整数),因此最好让规则返回一个泛型对象,并进行相应的强制转换

    下面是一个快速演示(包括在括号表达式的情况下进行递归调用):

    grammar T;
    
    @parser::members {
      private java.util.Map<String, Integer> memory = new java.util.HashMap<String, Integer>();
    }
    
    parse
    @init{
      // initialize some test values
      memory.put("AGE", 42);
      memory.put("DEPARTMENT", 999);
      memory.put("EMPID", 1001);
    }
     : expression EOF {System.out.println($text + " -> " + $expression.value);}
     ;
    
    expression returns [Object value]
     : logical {$value = $logical.value;}
     ;
    
    logical returns [Object value]
     : e1=equality {$value = $e1.value;} ( 'AND' e2=equality {$value = (Boolean)$value && (Boolean)$e2.value;}
                                         | 'OR' e2=equality  {$value = (Boolean)$value || (Boolean)$e2.value;}
                                         )*
     ;
    
    equality  returns [Object value]
     : r1=relational {$value = $r1.value;} ( '=' r2=relational  {$value = $value.equals($r2.value);}
                                           | '!=' r2=relational {$value = !$value.equals($r2.value);}
                                           )*
     ;
    
    relational returns [Object value]
     : a1=atom {$value = $a1.value;} ( '>=' a2=atom {$value = (Integer)$a1.value >= (Integer)$a2.value;}
                                     | '>'  a2=atom {$value = (Integer)$a1.value >  (Integer)$a2.value;}
                                     | '<=' a2=atom {$value = (Integer)$a1.value <= (Integer)$a2.value;}
                                     | '<'  a2=atom {$value = (Integer)$a1.value <  (Integer)$a2.value;}
                                     )?
     ;
    
    atom returns [Object value]
     : INTEGER            {$value = Integer.valueOf($INTEGER.text);}
     | ID                 {$value = memory.get($ID.text);}
     | '(' expression ')' {$value = $expression.value;}
     ;
    
    INTEGER : '0'..'9'+;
    ID      : ('a'..'z' | 'A'..'Z')+;
    SPACE   : ' ' {$channel=HIDDEN;};
    

    解析输入"AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001))"将产生以下输出:

    AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001)) -> true
    
  2. # 2 楼答案

    我会这样做:

    program : a=logicalExpression {System.out.println($a.evalResult);}
            ;
    
    logicalExpression returns [boolean evalResult]  :   a=andExpression { $evalResult = $a.evalResult;} (('OR') b=andExpression {$evalResult = $evalResult || $b.evalResult;})*
                                                    ;
    
    andExpression returns [boolean evalResult]      :   a=atomicExpression { $evalResult = $a.evalResult;} (('AND') b=atomicExpression {$evalResult = $evalResult && $b.evalResult;})*
                                                    ;
    
    atomicExpression returns [boolean evalResult]   :   a=singleEvaluation {$evalResult = $a.evalResult;}
                                                    |   '(' b=logicalExpression ')' {$evalResult = $b.evalResult;}
                                                    ;
    
    singleEvaluation returns [boolean evalResult ]  :   'TRUE'  {$evalResult = true;}
                                                    |   'FALSE' {$evalResult = false;}
                                                    ;