boost qi中的Plus运算符无法正常工作

时间:2011-01-23 17:27:43

标签: boost boost-spirit-qi

以下是示例代码

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

    template <typename Iterator>
    struct input : qi::grammar<Iterator, unsigned()>
    {
        input() : input::base_type(start)
        {
            using qi::lit;
            using qi::double_;

            start = lit("ADD") 
                            >> +(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                ); 
        }

        qi::rule<Iterator, unsigned()> start;
    };

int main()
{

    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";
    unsigned result;

    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();

    bool r = qi::parse(iter, end, input_parser, result);

}

我收到以下错误。

  

/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:201:   实例化   â€~boost ::精神::齐::规则和放大器;   boost :: spirit :: qi :: rule :: operator =(const Expr&amp;)   [与Expr =   提高::原:: exprns _ :: EXPR&安培;,   常量   升压::原:: exprns _ :: EXPR&安培;&gt;中   1l&gt;&amp;,const   升压::精神::终端&安培;&gt;中   2l&gt;&amp;,const   升压::原:: exprns _ :: EXPR&安培;&gt;中   1l&gt;&amp;&gt;,2&gt;&amp;,const   升压::精神::终端&安培;&gt;中   2l&gt;&amp;&gt;,1l&gt;&amp;&gt;,2l&gt;,Iterator =   __gnu_cxx :: __ normal_iterator,   std :: allocator&gt; &gt;,T1 =   unsigned int()(),T2 =   boost :: fusion :: unused_type,T3 =   boost :: fusion :: unused_type,T4 =   提高::融合:: unused_type]答€™   mini.c ++:34:实例化   â€〜input :: input()[with   迭代器=   __gnu_cxx :: __ normal_iterator,   std :: allocator&gt; &GT;]’   mini.c ++:49:从这里实例化   /usr/local/include/boost/spirit/home/qi/operator/plus.hpp:62:   错误:没有名为“type”的类型   â€~struct   升压::精神::性状::container_valueâ€

奇怪的部分是,如果我使用减号( - )操作,即

start = lit("ADD") 
                            >> -(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                );

......编译得非常好!

在gcc 4.3.4上编译。

1 个答案:

答案 0 :(得分:2)

启动规则公开的属性为unsigned,而加解析器公开包含包装元素属性的容器类型。以下是docs

中的属性传播规则
a: A --> +a: vector<A>

(即,如果解析器a公开类型为A的属性,则解析器+a将公开一个(标准)容器,其中包含A个实例,例如{ {1}})。

在您的情况下,嵌入式解析器会公开std::vector<A>。因此,您需要更改代码才能按预期工作:

double

但不幸的是,事情并不像看起来那么容易。当前版本的Spirit有一个错误阻止代码工作(即使很快发布的Boost V1.46仍然会有这个错误,但它已在SVN中继中修复)。问题是,plus不会将嵌入的元素“展平”到提供的容器中,从而导致上面代码解析的每两秒都丢失。

解决方法是避免序列在plus中暴露多个属性:

template <typename Iterator>
struct input : qi::grammar<Iterator, std::vector<double>()>
{
    input() : input::base_type(start)
    {
        using qi::lit;
        using qi::double_;
        start = lit("ADD") >> +(+lit(" ") >> double_ >> +lit(" ") >> double_);
    }

    qi::rule<Iterator, std::vector<double>()> start;
};

int main() 
{
    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";

    std::vector<double> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = qi::parse(iter, end, input_parser, result);  
} 

之后验证解析的元素数是偶数。

旁注:您似乎想跳过输入中元素之间的空格。使用跳过解析器可以更容易地实现这一点:

start = lit("ADD") >> +(+lit(" ") >> double_);

同时规避了上述问题。