1

さて、2 日間で 3 回目の 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 に切り替えたくありません。

ジェイソン

4

2 に答える 2

1

私は次のようにします:

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;}
                                                ;
于 2012-11-15T14:58:42.680 に答える
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
于 2012-11-15T19:09:08.130 に答える