使用antlr3的简单标准表达式解析器

时间:2013-02-20 07:56:13

标签: java antlr antlr3 abstract-syntax-tree

我想用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.

我想我需要在“subcond”中重写规则        使 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
  :
  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 and ((b = 2 or c = 3) or d = 4)

2 个答案:

答案 0 :(得分: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))

的内容

答案 1 :(得分:2)

你语法中的一个缺陷是规则

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
  ;

理想情况下,您还应该为ANDOR表达式设置单独的规则,以便在您的解析树中具有正确的优先级。

更新: 在您更新的语法中,您再次使用LPAREN*RPAREN*,这将无法为您提供正确平衡的树。您需要使用递归对((a = 1))之类的多个pare建模,就像我在上面的示例中所描述的那样。这会给出像

这样的树
((a = 1))
  ^---^--- ATOM
 ^-----^-- Subcond -> Expression
^-------^- Subcond -> Expression

所以这棵树就是这样的:

Expression "((a = 1))"
^
Subcond "(a = 1)"
^
Expression "(a = 1)"
^
Subcond "a = 1"
^
ATOM "a = 1"