在join子句处分析SQL Select语句时卡住(包括BNF语法)

在join子句处分析SQL Select语句时卡住(包括BNF语法),sql,parsing,bnf,Sql,Parsing,Bnf,我正在努力理解如何使用这种SQL语法从解析器解析下面给出的SQL语句。我被卡在“表引用”和“连接”结构中,在WHERE-WHERE令牌之后找到 BNF: 跳转到FROM子句。这里有一个表名,后跟两个联接 如果您查看“表引用”,那么您会看到它包含“表名”。这我能理解 <table reference> ::= **<table name> [ <correlation specification> ]** | <deriv

我正在努力理解如何使用这种SQL语法从解析器解析下面给出的SQL语句。我被卡在“表引用”和“连接”结构中,在WHERE-WHERE令牌之后找到

BNF:

跳转到FROM子句。这里有一个表名,后跟两个联接

如果您查看“表引用”,那么您会看到它包含“表名”。这我能理解

<table reference>    ::=
         **<table name> [ <correlation specification> ]**
     | <derived table> <correlation specification>
     | <joined table>
::=
** [  ]**
|  
| 
但是为了获得联接,解析器必须到达“联接表”,而它不能到达,因为它已经准备好读取“表名”

为了达到连接,解析器必须达到“限定连接”,但它不能,因为BNF中没有重复。如果它以某种方式到达“Join table”元素,那么If将非常失望,因为下一次读取将再次是“table reference”,然后它将再次到达“qualified Join”,并且。。。。然后会出现堆栈溢出

  <joined table>    ::=
         <cross join>
     | <**qualified join>**
     | <left paren> <joined table> <right paren>

**<qualified join>**    ::=
         <table reference> [ NATURAL ] [ <join type> ] JOIN <table reference> [ <join specification> ]
::=
| **
|   
****    ::=
[自然][]加入[]
我在这里没有得到什么?我相信这是有诀窍的,但我就是不明白

我希望你们中的一些人能向我解释一下这是怎么回事

我们如何构造一个递归下降解析器来解决这个语法呢

解析器需要遵循哪些步骤和/或规则

该语法不是LL(1),这是构建递归下降解析器所需要的。我怀疑SQL是否有LL(1)语法,尤其是是否有一种语法可以生成正确的解析树。幸运的是,这并不重要,因为有更强大的解析技术


很可能您可以使用该语法来构建一个LALR(1)解析器,使用类似bison/yacc的工具。或者参阅,它包括一个LALR(1)语法和一个名为“lemon”的LALR(1)解析器生成器

这个问题已经有一段时间没有提出了,但由于ANTLR的性能/内存问题,我正在考虑将我的Antl4 SQL解析器重写为RDP

所以,我(精神上)解决连接问题的方法是,我把它们当作操作符对待,因为它们就是这样的(至少这是我的印象)

基本表达式语法适用于常用表达式和联接:

ex
    : '(' ex ')'
    | ex OPERATOR ex
    | TERMINAL
    ;
在联接情况下,运算符变为联接,端子变为表引用


现在,这种左递归语法不是LL语法,但可以转换成ANTLR4自动执行的LL语法。

我不太熟悉您正在做的事情,但是。。。我读到的是,
表示一个只包含一个表的查询,而
表示一个包含连接表的查询。但我不确定你是如何运用逻辑来预先认识到这一点的。你如何告诉递归程序选择正确的路径?另一个问题是BNF如何支持嵌套联接?有了正确的解释,这可能很简单。为什么你认为语法必须可以用递归下降解析器解析?我不知道用递归下降解析器解析这个语法是可能的还是不可能的?我自己正试图用这样一个解析器来实现它。我不太明白:这是一个您正在尝试理解的经过验证的解析器,还是您自己在构建解析器?换句话说,解决这个问题的方法是更好地理解BNF,还是改变了BNF,还是其他什么@rici提出了一个很好的观点——我认为您不能用串行方法解析SQL,您可能需要从高层识别组件并深入研究这些片段。这正是我需要的信息。我认为我需要将我的知识扩展到RDP/LL(1)之外。我会阅读语法分析器,我会检查你的链接。你知道把LALR(1)BNF转换成ll(1)BNF的技巧吗?@brian一般来说,转换是不可能的,因为LR语法集是ll语法的严格超集。有一些机械转换是可以尝试的,但它们在玩具语法上比SQL等现实问题更有效。即使它们生成了LL语法(这是不能保证的),解析树也不会被保留,因此您最终会遇到另一个问题。最好的技巧,IMHO,是找到一个与您的编码语言一起工作的解析器生成器,并学习如何使用它。
  <joined table>    ::=
         <cross join>
     | <**qualified join>**
     | <left paren> <joined table> <right paren>

**<qualified join>**    ::=
         <table reference> [ NATURAL ] [ <join type> ] JOIN <table reference> [ <join specification> ]
ex
    : '(' ex ')'
    | ex OPERATOR ex
    | TERMINAL
    ;