2

antlr3を使用して簡単な条件式パーサーを作成したい

更新:AND / ORの異なる階層をサポートするために、AND OR式のルールを分離しましたが、別の問題が発生しました: 式が次のようなものである場合:a=1およびb=2およびc=3ツリーは、現在の実装に従って次のようになります。

       =      =
 (a = 1)(b = 2)(c = 3)
But I want to generate it as follows:
          =       =
    (a = 1)(b = 2)
               (c = 3)
First "and" should be higher priority than another, because I want to parse all the expression as left exp and right exp.

「サブコンド」のルールを書き直す必要があると思います。a =1およびb=2およびc=3->(a=1およびb=2)およびc=3にする

しかし、運が悪かったので何度も試しました。誰かがそれを達成する方法を知っていますか?ありがとう。


私の目標は、ある種のSQL where句スタイルの文を解析し、ウォークスルーするASTを構築することです。

例えば:

    a = 1 and (b = 2 or c = 3)            //This one can parse correctly.
    a = 1 and ((b = 2 or c = 3) or d = 4) //This one cannot parse correctly, missing last d = 4 in the tree. 
                                          //Tree is not correct.

私の現在の文法ファイルは、上記の複雑な条件を解析できません。私はantlrの初心者なので、上記のアプローチをより正確に達成するために文法を変更する方法がわかりません。誰かがこれを手伝ってくれる?!提案やコメントは大歓迎です。

と私の文法は次のとおりです(コメントに従って更新されました。警告の問題は解決されました。):

grammar CriteriaExpression;

options {
  output       = AST;
  ASTLabelType = CommonTree;
  language     = Java;
}

tokens {
  AND    = 'and';
  OR     = 'or';
  LPAREN = '(';
  RPAREN = ')';
}

@lexer::header {
package com.antlr;
}

@parser::header {
package com.antlr;
}

eval
:
expression
;

式:andExp(OR ^ andExp)*;

andExp:subcond(AND ^ subcond)*;

subcond:LPAREN式RPAREN | atom;

atom
  :
  EXPR OPERATOR EXPR
  ;

OPERATOR
  :
  '='| '<>'| '!='| '<='| '!>'| '<'| '>='| '!<'| '>'| 'like'
  ;

EXPR
  :
  ('a'..'z'| 'A'..'Z'| '0'..'9')+
  ;

 WILDCARD
  :
  '%'
  ;

WS
  :
  ('\t'| ' '| '\r'| '\n'| '\u000C')*
   {$channel = HIDDEN;}
  ;

((a = 1)) ((a = 1))

a = 1および((b=2またはc=3)またはd = 4) a = 1および((b=2またはc=3)またはd = 4)

4

2 に答える 2

2

私は間違っているかもしれませんが、あなたはこのようなものを書くことLPAREN* something RPAREN* ができるという問題があると思います((何か)そしてantlrはLParentとRparentが互いに接続していないのでこの書き込みを考えるのでこのようなものを使用するかもしれません

COMPLEX:
    LPARENT (COMPLEX|subcond) RPARENT;

しかし、私はそれをもう一度言います、多分私は間違っています

アップデート

これを変える:

subcond
  : 
  //atom (( AND | OR )^ atom)*
  LPAREN* atom RPAREN*
  ;

これに:

subcond
  : 
  LPAREN (subcond|atom) RPAREN
  ;

これを使用して、次のようなものを書くことができます((a=1))

于 2013-02-20T08:24:00.277 に答える
2

文法の1つの欠陥はルールです

expression
  :
  LPAREN* subcond RPAREN* (( AND | OR )^ LPAREN* subcond RPAREN*)
  ;

LPARENまたはRPARENはいくつでも持つことができるため、それらが一致するという保証はありません。私は次のような何かを使用することをお勧めします

expression
  : subcond (( AND | OR ) subcond)?
  | subcond
  ;

とのためにsubcond

subcond
  : atom (( AND | OR )^ atom)*
  | LPAREN expression RPAREN
  ;

理想的には、解析ツリーで正しい優先順位を設定するために、式ANDと式を別々に設定する必要があります。OR

更新:更新された文法では、これも使用してLPAREN*おり、RPAREN*適切にバランスの取れたツリーが得られません。((a = 1))上記の例で説明したように、再帰のように複数の親をモデル化する必要があります。これは次のような木を与えるでしょう

((a = 1))
  ^---^--- ATOM
 ^-----^-- Subcond -> Expression
^-------^- Subcond -> Expression

したがって、ツリーは次のようになります。

Expression "((a = 1))"
^
Subcond "(a = 1)"
^
Expression "(a = 1)"
^
Subcond "a = 1"
^
ATOM "a = 1"
于 2013-02-20T08:29:46.213 に答える