使用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和((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 ;
理想情况下,您还应该为AND
和OR
表达式设置单独的规则,以便在解析树中具有正确的优先级。
更新:在您更新的语法中,您再次使用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))