我为一个非常小的语言子集编写了一个非常简单的SQL Parser来处理一次性特定问题。我不得不将极大量的旧SQL表达式转换为中间形式,然后可能将其带入业务规则系统。最初的尝试适用于大约80%的现有数据。
我查看了一些商业解决方案,但我认为根据过去的经验和一些阅读,我可以很容易地做到这一点。我遇到了一个问题并决定用商业解决方案完成任务,我知道何时承认失败。但是我仍然很好奇如何处理这个或者我可能做错了什么。
我的初始解决方案基于一个简单的递归下降解析器,可以在许多书籍和在线文章中找到,生成一个抽象语法树,然后在分析阶段,我将确定类型差异以及逻辑表达式是否与代数表达式混合等等。
我引用了Bark Kiers的ANTLR SQL Lite语法 https://github.com/bkiers/sqlite-parser
我还引用了一个在线SQL语法网站 http://savage.net.au/SQL/
主要问题是如何让解析器区分以下
expr AND expr
BETWEEN expr AND expr
我遇到的问题是当我点击以下单元测试用例时
PP_ID介于'009000'和'009999'之间然后'MA'时PP_ID介于'001000'和'001999'之后然后'TL'否则'LA'结束
'009000'和'009999'被匹配为二进制表达式,因此解析器会抛出一个错误,期待关键字AND,而是遇到那么。
在线ANSI语法实际上将表达式分解为更细粒度的制作,我怀疑这是正确的方法。我也想知道我的解析器是否应该在解析阶段检测表达式是否实际上是布尔对代数而不是语义阶段,并使用该信息来处理上述情况。
我确信我可以强制解决这个问题,但我想学习处理这个问题的正确方法。
感谢您提供的任何帮助。
答案 0 :(得分:1)
我在开发Jison(Bison)parser for SQLite时也遇到了这个问题,并用二进制操作的语法规则解决了这个问题:一个用于AND,另一个用于BETWEEN(这是一个Jison语法):
%left BETWEEN // Here I defined that AND has higher priority over BETWEEN
%left AND //
: expr AND expr // Rule for AND
{ $$ = {op: 'AND', left: $1, right: $3}; }
;
: expr BETWEEN expr // Rule for BETWEEN
{
if($3.op != 'AND') throw new Error('Wrong syntax of BETWEEN AND');
$$ = {op: 'BETWEEN', expr: $1, left:$3.left, right:$3.right};
}
;
然后解析器检查右表达式,并仅传递带AND运算的表达式。可能这种方法可以帮到你。
对于ANTLR语法,我发现了以下规则(参见Bart Kiers制作的this grammar)
expr
:
| expr K_AND expr
| expr K_NOT? K_BETWEEN expr K_AND expr
;
但我不确定,它是否以适当的方式运作。