0

激励例子
很好:

 SELECT   a, b,  c    d,e FROM t1

坏的:

SE L ECT a, b, c    d,e FR OM t1

SELECTa, b, c    d,eFROMt1

因此,正如您在这里看到的问题是,有些空格是可以的(例如,在 SELECT 和 a、b、c 之间),有些是不好的(SE L ECT),有些是必需的(关键字之后/之前)。

所以我的问题是在这里使用什么成语,因为如果我使用spaceskipperphrase_parse将允许错误的空间,如果我想允许没有船长的好空间,解析器会变得乱七八糟*char_(' ')

4

2 回答 2

3

您需要将关键字标记为qi::lexeme[].

此外,您可能想要boost::spirit::repository::qi::distinct避免解析后跟 2.\SELECT2SELECT

参见例如

于 2016-11-03T13:23:26.963 回答
1

您正在寻找的是解析。

这不是关于接受/拒绝“好”或“坏”的空间。这是关于尝试识别输入的内容,如果不能,则拒绝它。

在这种情况下,让我们从相关语句的(彻底简化的)语法开始:

select_statement ::= 'select' field_list 'from' table

所以,你读入了第一个令牌。如果它是SEor SELECTa,则您拒绝该声明为无效,因为它们都不符合您的语法。几乎任何体面的解析器生成器(包括但不限于 Spirit)都使这变得相当简单——您指定什么是可接受的,以及如果输入不可接受时该怎么做,它会处理为不可接受的输入调用它t 符合指定的语法。

至于如何开始标记化,它通常非常简单,并且通常可以基于正则表达式(例如,许多语言已经使用lex和衍生工具如 Flex 实现,它们使用正则表达式来指定标记化)。

对于这样的事情,您可以直接为您的语言指定关键字,因此当它匹配“选择”时,您会看到一些内容,它应该将其作为标记返回。然后,对于通常运行类似 `[_a-zA-Z][_a-zA-Z0-9]*' 的标识符(“标识符以下划线或字母开头,后跟任意数量的下划线、字母或数字”)。在上述情况下,这完全足以找到并返回“SE”和“SELECTa”作为“坏”示例中的第一个标记。

然后,您的解析器将检测到它收到的第一件事是标识符而不是关键字,此时它将(可能)被拒绝。

于 2016-11-03T11:21:04.240 回答