使用 ANTLR 4 解析 SQL 'between' 和 'and' 表达式
Parsing SQL 'between' and 'and' expressions with ANTLR 4
我在使用 SQL 表达式解析器时遇到困难。具体来说,使用 a AND b
和 a BETWEEN c AND d
规则。备选方案指定如下:
| lhs=exprRule K_AND rhs=exprRule # AndExpression
| value=exprRule K_NOT? K_BETWEEN lower=exprRule K_AND upper=exprRule # BetweenExpression
不幸的是,这个语法解析的是一个字符串,比如
...
l_discount BETWEEN 0.02 - 0.01 AND 0.02 + 0.01
AND l_quantity < 25
...
作为 BetweenExpression
与 lower={0.02 - 0.01 AND 0.02 + 0.01}
和 upper={l_quantity < 25}
。显然,我希望将其解析为 lower={0.02 - 0.01}
和 upper={0.02 + 0.01}
,并以 AndExpression
作为父节点。
基本上,我希望 BetweenExpression
的 lower=exprRule
取最少的令牌,而不是最多的令牌。在我看来,应该有一个直接的解决方案,但我缺乏术语来表达正确的 google 搜索,也无法在 ANTLR 文档中找到答案。
我也试过,按照 mnesarco 的建议,给 BETWEEN
表达式 alt 更高的优先级,但在这两种情况下,解析树:
已创建。想想也是有道理的。
我唯一能想到的是引入一个额外的 "numeric expression" 规则,它不匹配 and
和 between
表达式:
exprRule
: value=exprRule ( '+' | '-' ) lower=exprRule #AddExpression
| value=exprRule ( '<' | '>' | '<=' | '=>' ) lower=exprRule #ComparisonExpression
| value=exprRule K_NOT? K_BETWEEN lower=exprNumeric K_AND upper=exprNumeric #BetweenExpression
| lhs=exprRule K_AND rhs=exprRule #AndExpression
| NUMBER #NumberExpression
| ID #IdExpression
;
exprNumeric
: value=exprNumeric ( '+' | '-' ) lower=exprNumeric #AddNumericExpression
| NUMBER #NumNumericberExpression
| ID #IdNumericExpression
;
这导致解析树:
看起来像是一个优先级问题。基本上你需要 [Between] 运算符的优先级高于 [And] 并且可能也高于 [Or]。
在 Antlr4 中,优先级只是定义的顺序。因此,只需尝试交换替代顺序。即:
| value=exprRule K_NOT? K_BETWEEN lower=exprRule K_AND upper=exprRule # BetweenExpression
| lhs=exprRule K_AND rhs=exprRule # AndExpression
我在使用 SQL 表达式解析器时遇到困难。具体来说,使用 a AND b
和 a BETWEEN c AND d
规则。备选方案指定如下:
| lhs=exprRule K_AND rhs=exprRule # AndExpression
| value=exprRule K_NOT? K_BETWEEN lower=exprRule K_AND upper=exprRule # BetweenExpression
不幸的是,这个语法解析的是一个字符串,比如
...
l_discount BETWEEN 0.02 - 0.01 AND 0.02 + 0.01
AND l_quantity < 25
...
作为 BetweenExpression
与 lower={0.02 - 0.01 AND 0.02 + 0.01}
和 upper={l_quantity < 25}
。显然,我希望将其解析为 lower={0.02 - 0.01}
和 upper={0.02 + 0.01}
,并以 AndExpression
作为父节点。
基本上,我希望 BetweenExpression
的 lower=exprRule
取最少的令牌,而不是最多的令牌。在我看来,应该有一个直接的解决方案,但我缺乏术语来表达正确的 google 搜索,也无法在 ANTLR 文档中找到答案。
我也试过,按照 mnesarco 的建议,给 BETWEEN
表达式 alt 更高的优先级,但在这两种情况下,解析树:
已创建。想想也是有道理的。
我唯一能想到的是引入一个额外的 "numeric expression" 规则,它不匹配 and
和 between
表达式:
exprRule
: value=exprRule ( '+' | '-' ) lower=exprRule #AddExpression
| value=exprRule ( '<' | '>' | '<=' | '=>' ) lower=exprRule #ComparisonExpression
| value=exprRule K_NOT? K_BETWEEN lower=exprNumeric K_AND upper=exprNumeric #BetweenExpression
| lhs=exprRule K_AND rhs=exprRule #AndExpression
| NUMBER #NumberExpression
| ID #IdExpression
;
exprNumeric
: value=exprNumeric ( '+' | '-' ) lower=exprNumeric #AddNumericExpression
| NUMBER #NumNumericberExpression
| ID #IdNumericExpression
;
这导致解析树:
看起来像是一个优先级问题。基本上你需要 [Between] 运算符的优先级高于 [And] 并且可能也高于 [Or]。
在 Antlr4 中,优先级只是定义的顺序。因此,只需尝试交换替代顺序。即:
| value=exprRule K_NOT? K_BETWEEN lower=exprRule K_AND upper=exprRule # BetweenExpression
| lhs=exprRule K_AND rhs=exprRule # AndExpression