【问题标题】:simple criteria expression parser with antlr3带有 antlr3 的简单标准表达式解析器
【发布时间】:2013-02-20 07:56:13
【问题描述】:

我想用 antlr3 创建一个简单的条件表达式解析器

更新:单独的 AND OR 表达式规则以支持 AND/OR 不同的层次结构,但遇到了另一个问题: 如果表达式类似于:a = 1 and b = 2 and 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 and b = 2 and c = 3 -> (a = 1 and b = 2) and 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 的新手,不知道如何修改我的语法以更正确地实现上述方法。有人可以帮忙吗? !任何建议或 cmets 表示赞赏。

和我的语法如下(根据cmets更新。警告问题已解决。):

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)* ;

和Exp : 子条件 (AND^ 子条件)* ;

子条件 : 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 和 ((b = 2 或 c = 3) 或 d = 4)

【问题讨论】:

  • 显示示例的传入文件
  • 嗨,@Aleksei Bulgak,您的传入文件是什么意思?这个例子只是我认为的可能价值。真正的输入字符串可能要复杂得多,并且可能是混合组合。谢谢。
  • 你给这个链接不完整的树。有树
  • @Aleksei Bulgak,不完整的树是由 antlrworks 1.4.3 生成的,例如 a = 1 和((b = 2 或 c = 3)或 d = 4),我认为树缺少最后一部分 d=4 并且不知道如何修复它。
  • 请创建一个新问题,而不是完全重写您已经回答的问题。还是没有回答您最初的问题?

标签: java antlr antlr3 abstract-syntax-tree


【解决方案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
  ;

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

更新: 在您更新的语法中,您再次使用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"

【讨论】:

  • 嗨,@tehlexx,是的,你是对的,我们不能保证输入字符串中 LPAREN 或 RPAREN 的数量。但我认为关键是这个语法不能描述括号优先级,不是吗?也许我错了,我更新了我的语法,它可以用复杂的例子生成完整的树:a = 1 and ((b = 2 or c = 3) or d = 4),但我不确定优先级是否在这棵树中是否正确。
  • 我理解你的问题的方式是必须有 *PARENs 必须匹配,所以如果有 2 个LPARENs,则必须正好有 2 个 RPARENs。上面的语法还应该涵盖根本没有PARENs 的场景,然后它会走直接路径expression -&gt; subcond -&gt; ATOM,所以这应该也可以。关键是用递归建模括号,而不是用PAREN*
  • 嗨,@tehlexx,我明白了你的意思,并且更新了语法,我认为现在的方法应该是正确的。非常感谢。 ((a=1)) 生成的树似乎比你描述的更深,我的方法现在符合你的描述吗?能帮忙确认一下吗?谢谢。
  • 据我所知,这些树看起来不错!您还应该检查a=1 OR b=2 AND c=3a=1 AND b=2 OR c=3 的树。在这两种情况下,AND 节点都应低于OR 节点。这很重要,因为AND 通常在OR 之前。
  • 嗨@tehlexx 非常感谢,我根据你的建议更新了我的语法。现在它是支持 AND 在 OR 之前。但是遇到了新问题,因为我想将所有表达式解析为左 exp 和右 exp 两部分,所以如果表达式类似于:a=1 和 b=2 和 c=3,那么树将有 3 次跳跃,即当我解析树时会出现问题,是否可以重写规则以使其支持 a=1 and b=2 and c=3 -> (a=1 and b=2) and c=3,甚至更多 ((a=1 and b=2) and c=3) and d=4 ?也许这是不可能的......无论如何,谢谢。
【解决方案2】:

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

COMPLEX:
    LPARENT (COMPLEX|subcond) RPARENT;

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

更新

改变这个:

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

到这里:

subcond
  : 
  LPAREN (subcond|atom) RPAREN
  ;

使用它,您现在可以编写类似 ((a=1))

的内容

【讨论】:

  • 太棒了!你的回答让我大开眼界。哪个可以解决警告。但我仍然认为括号的树优先级仍然不正确。
  • 更新后可以生成完整的树,但是仍然不能描述括号的优先级,应该是另一个问题。
  • 感谢@Aleksei Bulgak,您的更新可以满足((a = 1)),但语法似乎不够灵活。检查我更新的语法,我认为它是正确的,现在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多