7

到目前为止,我的语法一直在使用标准boost::spirit::ascii::space/boost::spirit::ascii::space_type船长。

我有一些使用船长的规则和一些不使用的规则,比如

qi::rule<Iterator, PTR<Expression>(), ascii::space_type> expression;
qi::rule<Iterator, PTR<Term>()> term;

term当我在跳过的非终结符(如)内使用非跳过的非终结符(如expression)时,一切都像我预期的那样工作 - 空格只在term非终结符内部很重要。

此外,到目前为止,我一直很好,包括在不用于qi::skip重新建立跳过的非终端内使用船长的非终端,例如

index = (qi::lit('[') >> qi::skip(ascii::space)[explist >> qi::lit(']')]);

这样,空格在[]大括号内部并不重要,但在外部。

但是,现在我想添加我自己的自定义跳过程序(我想让换行符变得重要,然后添加评论跳过)。我的船长语法看起来像:

struct skip_grammar : qi::grammar<Iterator> {
  qi::rule<Iterator> start;
  skip_grammar() : skip_grammar::base_type(start) {
    start = qi::char_("\t\r ");
  }
};

我已经能够将它添加到我的规则定义中,就像

qi::rule<Iterator, PTR<Expression>(), skip_grammar> expression;

但我似乎无法弄清楚如何使用我的跳过语法作为qi::skip(和替换ascii::space)的参数。我尝试过使用类型、局部实例变量和全局实例变量。我得到的最远的是让clang抱怨我的skip_grammar需要一个复制构造函数。所以我尝试在我的跳过语法中添加一个复制构造函数,但显然boost::noncopyable基类的存在是有原因的,因为我的二进制文件几乎立即发生了段错误。

我应该如何使用这个?

谢谢

4

1 回答 1

7

Aqi::grammar只是qi::rules. 它没有复制构造函数,因为这可能会无意中在这些规则右侧的解析器表达式中创建悬空引用。

按照您的意愿使用语法作为跳过器有点棘手,相当于将语法的开始规则传递给跳过解析器。为它创建一个规则实例可能更容易(特别是如果您有一个规则跳过器)。

在任何情况下,都需要将规则作为参考传递给船长(通过调用规则的成员函数alias()):

skip_grammar skippper;
index = '[' >> qi::skip(skipper.start.alias())[explist >> ']'];

或者简单地说:

rule<iterator> skipper = qi::char_("\t\r ");
index = '[' >> qi::skip(skipper.alias())[explist >> ']'];

由于复制规则的具体含义,别名是必要的。在 Spirit 的 FAQ 中有更详细的描述

于 2011-02-18T12:32:19.237 回答