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

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

 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)

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

 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* ,它们不会为您提供正确平衡的树。 您需要使用递归建模多个parens,如((a = 1)) ,就像我在上面的示例中所描述的那样。 这会给树一样

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

所以树就是这样的:

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

可能是我错了但我认为你的问题与这个事情有关LPAREN* something RPAREN*你可以写这样的东西((某事)和antlr认为这个写因为LParent和Rparent没有相互连接所以可能会使用某些东西像这样

 COMPLEX: LPARENT (COMPLEX|subcond) RPARENT; 

但我会再说一遍,也许我错了

UPDATE

改变这个:

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

对此:

 subcond : LPAREN (subcond|atom) RPAREN ; 

使用这个你现在可以写这样的东西((a=1))