为什么我的简单SQL语法无法在Brag中解析?

时间:2019-09-22 00:38:55

标签: scheme racket brag

我正在尝试使用在Brag中用BNF编写的语法为SQL的简单子集创建解析器。我的Brag代码如下:

#lang brag
statement : "select" fields "from" source joins* filters*
fields    : field ("," field)*
field     : WORD
source    : WORD
joins     : join* 
join      : "join" source "on" "(" condition ")"
filters   : "where" condition ("and" | "or" condition)*
condition : field "=" field

但是当我尝试使用该语法来解析基本的SQL语句时,遇到了以下错误:

> (parse-to-datum "select * from table")
Encountered unexpected token of type "s" (value "s") while parsing 'unknown [line=#f, column=#f, offset=#f]

我是语法和吹牛的初学者。有什么想法我做错了吗?

1 个答案:

答案 0 :(得分:2)

您需要先对字符串进行lex / tokenize。 parse / parse-to-datum的输入应该是令牌列表。另外,吹嘘是区分大小写的,这意味着输入应为select而不是SELECT。完成之后,它应该可以工作:

> (parse-to-datum (list "select" 
                        (token 'WORD "foo") 
                        "from " 
                        (token 'WORD "bar") 
                        " " 
                        " "))
'(statement "select" (fields (field "foo")) "from " (source "bar") " " " ")

对于区分大小写的问题,这实际上不是问题,因为您可以在标记化阶段执行标准化。

但是,您的语法看起来很奇怪。您可能不应该处理空格。相反,应该在标记化阶段类似地处理空白。

有关令牌化的更多信息,请参见https://beautifulracket.com/bf/the-tokenizer-and-reader.html


另一种可能性是使用其他解析器。例如,https://docs.racket-lang.org/megaparsack/index.html可以立即将字符串解析为一个基准(或语法基准),尽管它在函数式编程中使用了一些高级概念,因此在某种程度上可能更难使用。