是否可以将boost :: phoenix :: at_c与boost :: spirit :: qi :: grammar结合使用 [英] Is there an alternative for boost::phoenix::at_c in combination with boost::spirit::qi::grammar

查看:109
本文介绍了是否可以将boost :: phoenix :: at_c与boost :: spirit :: qi :: grammar结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个测试应用程序来说明我的问题.它解析一个以"a ="或"b ="开头的整数列表,并以"\ r \ n"分隔.该列表以任意顺序包含这些字段的多次出现.

I have created a test application to illustrate my problem. It parses a list of integers preceded by "a=" or "b=" and is separated by "\r\n". The list contains multiple occurrences of those fields in any order.

#include <string>
#include <vector>
#include <iostream>

#include <boost/spirit/include/qi.hpp>

#include <boost/spirit/include/phoenix.hpp>

#include <boost/fusion/include/adapt_struct.hpp>


typedef std::vector<unsigned int> uint_vector_t;

std::ostream& operator<<(std::ostream& out, const uint_vector_t &data)
{
    for (unsigned int i(0); i < data.size(); i++)
    {
        out << data[i] << '\n';
    }
    return out;
}

struct MyStruct
{
    uint_vector_t m_aList;
    uint_vector_t m_bList;
};

BOOST_FUSION_ADAPT_STRUCT
(
    MyStruct,
    (uint_vector_t, m_aList)
    (uint_vector_t, m_bList)
)
;

template<typename Iterator>
struct MyParser : public boost::spirit::qi::grammar<Iterator,
        MyStruct()>
{
    MyParser() :
        MyParser::base_type(Parser, "Parser")
    {
        using boost::spirit::qi::uint_;
        using boost::spirit::qi::_val;
        using boost::spirit::qi::_1;

        using boost::phoenix::at_c;
        using boost::phoenix::push_back;

        Parser =
                *(
                        aParser [push_back(at_c<0>(_val), _1)]
                    |
                        bParser [push_back(at_c<1>(_val), _1)]
                );
        aParser = "a=" >> uint_ >> "\r\n";
        bParser = "b=" >> uint_ >> "\r\n";
    }
        boost::spirit::qi::rule<Iterator, MyStruct()> Parser;
        boost::spirit::qi::rule<Iterator, unsigned int()> aParser, bParser;
};

int main()
{
    using boost::spirit::qi::phrase_parse;

    std::string input("a=0\r\nb=7531\r\na=2\r\na=3\r\nb=246\r\n");
    std::string::const_iterator begin = input.begin();
    std::string::const_iterator end = input.end();
    MyParser<std::string::const_iterator> parser;

    MyStruct result;
    bool succes = phrase_parse(begin, end, parser, "", result);
    assert(succes);

    std::cout << "===A===\n" <<result.m_aList << "===B===\n" << result.m_bList << std::endl;
}

在实践中,需要解析更多具有不同类型的字段.我反对这种方法在于以下表达式: [push_back(at_c< 0>(_ val),_1)] 这是分配和MyStruct的第一个元素之间的隐藏依赖性".这使代码不易更改.如果更改了结构,它可能仍会编译,但不再执行预期的操作.

In practice there are more fields with different types which need to be parsed. My objection with this approach lies in the following expression: [push_back(at_c<0>(_val), _1)] Here is a 'hidden dependency' between the assignment and the first element of MyStruct. This makes the code fragile to changes. If the struct is changed it might still compile, but no longer do what is expected.

我希望有一个类似的构造: [push_back(at_c< 0> bind(& MyStruct :: aList,arg1)(_ val),_1)] 参见

I'm hoping for a construction like: [push_back(at_c<0>bind(&MyStruct::aList, arg1)(_val), _1)] See this. So that it is really bound by name.

像这样可能吗?还是应该采用完全不同的方法?

Is something like this possible? Or should I take a total different approach?

推荐答案

Phoenix还允许您绑定数据成员,因此您可以编写:

Phoenix allows you to bind data members as well, so you can write:

Parser = 
   *(  aParser [push_back(bind(&MyStruct::m_aList, _val), _1)] 
    |  bParser [push_back(bind(&MyStruct::m_bList, _val), _1)] 
    ); 

此外,在这种情况下,您的结构不再需要FUSION_ADAPT魔术了.

Moreover, in this case you don't need the FUSION_ADAPT magic for your structure anymore.

这篇关于是否可以将boost :: phoenix :: at_c与boost :: spirit :: qi :: grammar结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆