使用 boost-spirit 解析词位之间的空白
Parsing white-spaces in between lexemes using boost-spirit
我想使用 boost::spirit 解析 bnf 语法。这个 工作正常。但是,我也希望能够读取出现在词素之间的 white-spaces。例如,假设我有这样的语法:
<name> ::= <firtname> <surname>
<firtname> ::= <char><char> | <firstname><char>
<surname> ::= <char><char> | <surname><char>
<char> ::= a | b | c ... | z
假设我有一个使用上述语法的重写系统,我应该在最后为 <name>
输出类似 David Harvey
的内容。但是如果<name>
规则是这样写的<name> ::= <firtname><surname>
。重写系统应该给出这样的输出 DavidHarvey
。这是因为重写系统是white-space敏感的。
生成与解析完全不同。
解析删除冗余并规范化数据。 Generation 添加冗余并根据某些目标(风格指南、效率目标等)选择(通常是许多)表示。
由于 BNF 相似性而让自己偏离轨道,您已经忘记了自己的目标。因为,在 BNF 中,许多空格实例根本不重要。
直接观察表明 AST 不包含空格。
破解它
最简单的方法是在 AST 中将跳过的空格表示为“字符串文字”:
_term = _literal | _rule_name | _whitespace;
有
_whitespace = +blank;
然后使 _list
规则也成为一个词位(因此 to not skip blanks):
// lexemes
qi::rule<Iterator, Ast::List()> _list;
qi::rule<Iterator, std::string()> _literal, _whitespace;
清洁解决方案
上面留下了一些“缺陷”:有些地方的空格仍然不重要(即 |
左右,特别是在列表属性数字之前):
<code> ::= <letter><digit> 34 | <letter><digit><code> 23
<letter> ::= "a" 1 | "b" 2 | "c" 3 | "d" 4 | "e" 5 | "f" 6 | "g" 7 | "h" 8 | "i" 9
<digit> ::= "9" 10 | "1" 11 | "2" 12 | "3" 13 | "4" 14
我看不出它在那里有什么用处,当然除非你的输入看起来不像你一直在使用的输入。例如。如果它看起来像这样:
<code>::=<letter><digit>34|<letter><digit><code>23
<letter>::="a"1|"b"2|"c"3|"d"4|"e"5|"f"6|"g"7|"h"8|"i"9
<digit>::="9"10|"1"11|"2"12|"3"13|"4"14
你可以把所有的规则都变成词位。但是,这根本不会与引号字符串的存在相加。引用字符串的整个概念是标记暂停正常空白(和注释)跳过的区域。
我有一种挥之不去的感觉,你离你的实际问题(见 https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)比我们目前所能看到的要远得多,你甚至可能已经从中剥离了整个引用字符串文字的概念已经是“BNF”了。
A clean solution would be to forget about misleading similarities with BNF and just devise your own grammar from the ground up.
如果目标只是拥有一个(递归)macro/template 扩展引擎,那么它应该比您目前拥有的简单得多。也许您可以描述您的实际任务(输入、期望的输出和所需的行为),以便我们帮助您实现目标?
我想使用 boost::spirit 解析 bnf 语法。这个
<name> ::= <firtname> <surname>
<firtname> ::= <char><char> | <firstname><char>
<surname> ::= <char><char> | <surname><char>
<char> ::= a | b | c ... | z
假设我有一个使用上述语法的重写系统,我应该在最后为 <name>
输出类似 David Harvey
的内容。但是如果<name>
规则是这样写的<name> ::= <firtname><surname>
。重写系统应该给出这样的输出 DavidHarvey
。这是因为重写系统是white-space敏感的。
生成与解析完全不同。
解析删除冗余并规范化数据。 Generation 添加冗余并根据某些目标(风格指南、效率目标等)选择(通常是许多)表示。
由于 BNF 相似性而让自己偏离轨道,您已经忘记了自己的目标。因为,在 BNF 中,许多空格实例根本不重要。
直接观察表明 AST 不包含空格。
破解它
最简单的方法是在 AST 中将跳过的空格表示为“字符串文字”:
_term = _literal | _rule_name | _whitespace;
有
_whitespace = +blank;
然后使 _list
规则也成为一个词位(因此 to not skip blanks):
// lexemes
qi::rule<Iterator, Ast::List()> _list;
qi::rule<Iterator, std::string()> _literal, _whitespace;
清洁解决方案
上面留下了一些“缺陷”:有些地方的空格仍然不重要(即 |
左右,特别是在列表属性数字之前):
<code> ::= <letter><digit> 34 | <letter><digit><code> 23
<letter> ::= "a" 1 | "b" 2 | "c" 3 | "d" 4 | "e" 5 | "f" 6 | "g" 7 | "h" 8 | "i" 9
<digit> ::= "9" 10 | "1" 11 | "2" 12 | "3" 13 | "4" 14
我看不出它在那里有什么用处,当然除非你的输入看起来不像你一直在使用的输入。例如。如果它看起来像这样:
<code>::=<letter><digit>34|<letter><digit><code>23
<letter>::="a"1|"b"2|"c"3|"d"4|"e"5|"f"6|"g"7|"h"8|"i"9
<digit>::="9"10|"1"11|"2"12|"3"13|"4"14
你可以把所有的规则都变成词位。但是,这根本不会与引号字符串的存在相加。引用字符串的整个概念是标记暂停正常空白(和注释)跳过的区域。
我有一种挥之不去的感觉,你离你的实际问题(见 https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)比我们目前所能看到的要远得多,你甚至可能已经从中剥离了整个引用字符串文字的概念已经是“BNF”了。
A clean solution would be to forget about misleading similarities with BNF and just devise your own grammar from the ground up.
如果目标只是拥有一个(递归)macro/template 扩展引擎,那么它应该比您目前拥有的简单得多。也许您可以描述您的实际任务(输入、期望的输出和所需的行为),以便我们帮助您实现目标?