【问题标题】:Parsing white-spaces in between lexemes using boost-spirit使用 boost-spirit 解析词位之间的空格
【发布时间】:2021-05-28 14:22:36
【问题描述】:

我想用 boost::spirit 解析一个 bnf 语法。这个parser 工作正常。但是,我也希望能够读取出现在词位之间的空格。例如,假设我有这样的语法:

<name> ::= <firtname> <surname>
<firtname> ::= <char><char> | <firstname><char>
<surname> ::= <char><char> | <surname><char>
<char>   ::= a | b | c ... | z

假设我有一个使用上述语法的重写系统,我应该在&lt;name&gt; 的末尾有类似David Harvey 的输出。但是,如果 &lt;name&gt; 规则是这样编写的 &lt;name&gt; ::= &lt;firtname&gt;&lt;surname&gt;。重写系统应该给出类似DavidHarvey 的输出。这是因为重写系统对空格敏感。

【问题讨论】:

  • 噢。这一切都是为了一个模板扩展引擎?你一直在追求“BNF 解析”......几个月了,结果你需要模板扩展。

标签: boost-spirit boost-spirit-qi


【解决方案1】:

生成与解析是完全不同的工作。

解析消除冗余并规范化数据。生成增加了冗余并根据一些目标(风格指南、效率目标等)选择(通常是许多中的一种)表示。

如果让自己偏离 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;

Live On Compiler Explorer

清洁解决方案

上面留下了一些“缺陷”:有些地方的空格仍然不重要(即在| 附近,特别是在列表属性数字之前):

<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”中剥离了整个引用字符串文字的概念已经。

一个干净的解决方案是忘记与 BNF 的误导性相似性,而只是从头开始设计自己的语法。

如果目标只是拥有一个(递归)宏/模板扩展引擎,那么它确实应该比您目前拥有的要简单得多。也许您可以描述您的实际任务(输入、期望的输出和所需的行为),以便我们帮助您实现这一目标?

【讨论】:

  • 我同意你的观点,管道符号周围的空格没有任何用处,唯一有用的空格是术语之间的空格。
  • 任何链接到一个简单的“(递归)宏模板扩展引擎”只是为了看看它是否最适合我的意图。
  • 嗯。我做了太多但搜索不是最好的。我会看看我能找到什么
  • 这是一个老歌 stackoverflow.com/questions/9404558/… 与此处以性能为导向的改编相比 stackoverflow.com/a/23517664/85371 - 那里的 cmets 链接了另一个相关示例,我在其中写了 Spirit 和非 Spirit 答案。
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多