我是编译器的新手,但我得到了一个项目SQL引擎 - 仅用于select语句。为此,我必须只使用手写的解析器和引擎。我研究了LL(k)语法和递归下降技术的样本(由stackoverflow建议用于手动编写解析器)。但是在任何一个样本中,都没有找到从函数构造解析树的方法。
你们中的任何人都可以告诉我,如何一步一步地完成整个编译过程,只需要 “从表中选择columnname1,columnname2”示例。还有一件事 - 升级库也是不允许的。数据在内存中。我使用结构存储数据。提前谢谢。
答案 0 :(得分:0)
我想说更简单的方法是将其作为编译器处理:
标记化是关于识别“单词”,对于你的例子,这给出了:
"Select", "columnname1", ",", "columnanme2", "from", "table"
解析是将这个令牌列表解释为抽象语法树。鉴于您的要求:
我将在Python中概述这个
class Select:
def __init__(self):
self.columnList = None
self.tableName = None
def Tokenize(statement):
result = []
for word in statement.split(" "):
sub = word.split(",") # the comma may not be separated by space
for i in range(len(sub)-1):
result.append(sub[i].lower()) # case insensitive
result.append(",")
result.append(sub[-1])
return result
def CreateSelect(tokens):
if len(tokens) == 0: raise NoToken()
if tokens[0] != "select": raise NotASelectStatement()
select = Select()
i = 1
while tokens[i] != "from":
if tokens[i] == "*":
select.columnList == ALL
break
else:
select.columnList.append(tokens[i])
i = i + 1
if tokens[i] != ",": raise ExpectedComma(i)
i = i + 1
select.tableName = tokens[i+1]
当然,正如您所知,这是一个有限的例子:
然而它运作良好且效率很高。如果我们将标记化和解析阶段结合起来,它通常会更有效率,但我发现它通常只会使代码更难以阅读。
另请注意,正确的错误报告会更好:
.lower()
),只是使用不区分大小写的比较修改强>:
使用一个不那么人为的例子,AST会是什么样子?
"select foo, bar from FooBar where category = 'example' and id < 500;"
我们走吧:
Select
|_ Columns (foo, bar)
|_ Table (FooBar)
\_ Where
\_ And
|_ Equal (category, 'example')
\_ LessThan (id, 500)
这里有一个树状结构,这就是你想要产生的结构。
答案 1 :(得分:0)
您可能还会在网上找到BNF grammars for SQL 92, 99 and 2003,这可能很方便。
这些是完整的语法,但不应该仅仅难以隔离SELECT分支。
另外,您可以在http://www.antlr.org/grammar/list探索已有的语法;那里有一些SQL风格。