【问题标题】:Plus operator in boost qi doesn't work as expectedboost qi 中的 Plus 运算符无法按预期工作
【发布时间】:2011-06-14 02:20:15
【问题描述】:

这是一个示例代码

#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::spirit::qi::rule& boost::spirit::qi::rule::operator=(const Expr&) [与 Expr = boost::proto::exprns_::expr&, 常量 boost::proto::exprns_::expr&>, 1l>&, 常量 boost::spirit::终端&>, 2l>&, 常量 boost::proto::exprns_::expr&>, 1l>&>, 2l>&, 常量 boost::spirit::终端&>, 2l>&>, 1l>&>, 2l>, 迭代器 = __gnu_cxx::__normal_iterator, 标准::分配器 > >, T1 = 无符号整数 ()(), T2 = boost::fusion::unused_type, T3 = boost::fusion::unused_type, T4 = boost::fusion::unused_type]’ mini.c++:34: 实例化自 â€〜输入::输入()[与 迭代器 = __gnu_cxx::__normal_iterator, std::allocator > >]’ mini.c++:49: 从这里实例化 /usr/local/include/boost/spirit/home/qi/operator/plus.hpp:62: 错误:没有名为“类型”的类型 ~结构 boost::spirit::traits::container_value——

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

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

...它编译得非常好!

在 gcc 4.3.4 上编译。

【问题讨论】:

    标签: boost boost-spirit-qi


    【解决方案1】:

    你的开始规则暴露的属性是unsigned,而plus-parser暴露了一个容器类型来保存被包装元素的属性。以下是来自docs的属性传播规则:

    a: A --> +a: vector<A>
    

    (即,如果解析器 a 公开了 A 类型的属性,则解析器 +a 将公开包含 A 实例的(标准)容器,例如 std::vector&lt;A&gt;)。

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

    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);  
    } 
    

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

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

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

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

    附注:您似乎想跳过输入中元素之间的空格。这可以通过使用跳过解析器更轻松地实现:

    template <typename Iterator>
    struct input : qi::grammar<Iterator, std::vector<double>(), qi::space_type>
    {
        input() : input::base_type(start)
        {
            using qi::lit;
            using qi::double_;
            start = lit("ADD") >> +double_;
        }
    
        qi::rule<Iterator, std::vector<double>(), qi::space_type> 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::phrase_parse(iter, end, input_parser, qi::space, result);  
    } 
    

    同时规避了上述问题。

    【讨论】:

    • 谢谢。您的解决方案运行良好,我现在知道我做错了什么。我的实际语法是空格分隔的,所以我不能跳过空格。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 2021-08-07
    • 2020-01-13
    • 2015-05-11
    • 2019-06-20
    • 2021-04-13
    • 1970-01-01
    相关资源
    最近更新 更多