我正在尝试使用在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]
我是语法和吹牛的初学者。有什么想法我做错了吗?
答案 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可以立即将字符串解析为一个基准(或语法基准),尽管它在函数式编程中使用了一些高级概念,因此在某种程度上可能更难使用。