首页 > 解决方案 > ANTLR4:在多个规则(AND,BETWEEN AND)中使用的关键字的解析器规则的排序问题

问题描述

我在使用 ANTLR4 解析一些 SQL 类型的字符串时遇到问题。解析后的字符串是:

WHERE a <> 17106
AND b BETWEEN c AND d
AND e BTW(f, g)

这是我的语法片段:

where_clause
    : WHERE element
    ;

element
    : element NOT_EQUAL_INFERIOR element
    | element BETWEEN element AND element
    | element BTW LEFT_PARENTHESIS element COMMA_CHAR element RIGHT_PARENTHESIS
    | element AND element
    | WORD
    ;

NOT_EQUAL_INFERIOR:     '<>';
LEFT_PARENTHESIS:       '(';
RIGHT_PARENTHESIS:      ')';
COMMA_CHAR:         ',';

BETWEEN:            B E T W E E N;
BTW:                B T W;

WORD ... //can be anything ... it doesn't matter for the problem.

该语法在该字符串上生成一棵树(图像)
(来源:hostpic.xyz

但正如您在同一张图片上看到的那样,这棵树不是“正确的”。

ANTLR4 是贪婪的,它将 BETWEEN 之后的所有内容都包含在一个“元素”中,但我们希望它只包含“c”和“d”。

自然地,由于它包含元素规则中的所有内容,它缺少 BETWEEN 的第二个 AND,因此它失败了。

我尝试过更改规则的顺序(在 BETWEEN 之前放置 AND),我尝试将关联更改为对这些规则的权利(< assoc=right >),但这些都不起作用。他们改变了树,但没有按照我想要的方式进行。

我觉得这个错误是贪婪、联想、递归的混合......这使得寻找相同类型的问题变得非常困难,但也许我只是错过了正确的词。

谢谢,祝你有美好的一天!

标签: sqlparsingantlrantlr4grammar

解决方案


我认为你滥用了规则element。我不认为 SQL 允许您将任何内容作为BETWEEN.

未经测试,但我会试试这个:

expression
    : expression NOT_EQUAL_INFERIOR expression
    | term BETWEEN term AND term
    | term BTW LEFT_PARENTHESIS term COMMA_CHAR term RIGHT_PARENTHESIS
    | expression AND expression
    | term
    ;

term
    : WORD
    ;

在这里,您在大多数地方element都变成expression了,但在其他地方,它变成了term. 后者现在是一个虚拟规则,但我很确定您还想在其中添加例如文字。


推荐阅读