And*_*dré 4 c++ boost boost-spirit boost-spirit-qi
我创建了一个测试应用程序来说明我的问题.它解析前面带有"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;
}
Run Code Online (Sandbox Code Playgroud)
实际上,还有更多需要解析的不同类型的字段.我对这种方法的反对意见在于以下表达式:[push_back(at_c <0>(_ val),_ 1)]这是赋值与MyStruct的第一个元素之间的"隐藏依赖".这使代码易于更改.如果结构被更改,它仍然可以编译,但不再执行预期的操作.
我希望有一个类似的结构:[push_back(at_c <0> bind(&MyStruct :: aList,arg1)(_ val),_ 1)]看到这个.所以它真的受到名字的约束.
这样的事情可能吗?或者我应该采取完全不同的方法?
Phoenix允许您绑定数据成员,因此您可以编写:
Parser =
*( aParser [push_back(bind(&MyStruct::m_aList, _val), _1)]
| bParser [push_back(bind(&MyStruct::m_bList, _val), _1)]
);
Run Code Online (Sandbox Code Playgroud)
而且,在这种情况下,你不再需要FUSION_ADAPT你的结构的魔力了.
| 归档时间: |
|
| 查看次数: |
2554 次 |
| 最近记录: |