【问题标题】:Is there an alternative for boost::phoenix::at_c in combination with boost::spirit::qi::grammarboost::phoenix::at_c 与 boost::spirit::qi::grammar 结合是否有替代方案
【发布时间】:2010-07-20 13:26:13
【问题描述】:

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

#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(_val), _1)] 这是赋值和 MyStruct 的第一个元素之间的“隐藏依赖关系”。这使得代码对更改很脆弱。如果结构被更改,它可能仍然可以编译,但不再执行预期的操作。

我希望有这样的结构: [push_back(at_cbind(&MyStruct::aList, arg1)(_val), _1)] 见this.这样真的是被名字绑定了。

这样的事情可能吗?还是我应该采取完全不同的方法?

【问题讨论】:

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


    【解决方案1】:

    Phoenix 也允许你绑定数据成员,所以你可以这样写:

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

    此外,在这种情况下,您的结构不再需要 FUSION_ADAPT 魔法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多