提升精神Qi重新建立跳过自定义跳过语法

时间:2011-02-18 04:35:54

标签: c++ boost-spirit boost-spirit-qi

到目前为止,我的语法一直使用标准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基类是有原因的,因为我的二进制文件几乎立即就被发现了。

我应该如何使用它?

由于

1 个答案:

答案 0 :(得分:7)

qi::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的常见问题here中有更详细的描述。