【发布时间】:2015-01-25 01:23:49
【问题描述】:
我对 boost::spirit 还是很陌生。我想将一串逗号分隔的对象解析为 std::vector (类似于教程中的)。字符串可以是不同的类型(在编译时已知):整数,如"1,2,3"、字符串"Apple, Orange, Banana" 等。
我希望所有类型都有一个统一的接口。
如果我解析单个元素,我可以使用auto_ 表达式。
是否有可能与向量有类似的接口?
我可以定义一个规则,给定一个模板参数,实际上可以解析这个向量吗?
这是一个简单的示例代码(由于最后一次调用phrase_parse而无法编译):
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <iostream>
#include <vector>
#include <boost/spirit/include/qi_auto.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
using qi::auto_;
using qi::phrase_parse;
using ascii::space;
using phoenix::push_back;
int main()
{
std::string line1 = "3";
std::string line2 = "1, 2, 3";
int v;
std::vector<int> vector;
typedef std::string::iterator stringIterator;
stringIterator first = line1.begin();
stringIterator last = line1.end();
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
bool r1 = qi::phrase_parse( first,
last,
qi::auto_,
ascii::space,
v );
first = line2.begin();
last = line2.end();
//The following call is wrong!
bool r2 = qi::phrase_parse( first,
last,
// Begin grammar
(
qi::auto_[push_back(phoenix::ref(vector), qi::_1)]
>> *(',' >> qi::auto_[push_back(phoenix::ref(vector),qi::_1)])
),
// End grammar
ascii::space,
vector);
return 0;
}
更新
我找到了一个解决方案,在解析之前知道向量大小的情况下。另一方面,我不能使用语法*( ',' >> qi::auto_ )。
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main()
{
std::string s = "1, 2, 3";
std::vector<int> vector;
//This works
qi::phrase_parse(s.begin(), s.end(), qi::auto_ >> ',' >> qi::auto_ >> ',' >> qi::auto_ , qi::blank, vector);
//This does not compile
qi::phrase_parse(s.begin(), s.end(), qi::auto_ >> *( ',' >> qi::auto_ ) , qi::blank, vector);
for(int i = 0; i < vector.size() ; i++)
std::cout << i << ": " << vector[i] << std::endl;
return 0;
}
此外,使用auto_,我无法解析字符串。是否可以定义模板函数,通过模板参数推导出语法?
template< typename T >
void MyParse(std::string& line, std::vector<T> vec)
{
qi::phrase_parse( line.begin(),
line.end(),
/*
How do I define a grammar based on T
such as:
double_ >> *( ',' >> double_ ) for T = double
+qi::alnum >> *( ',' >> +qi::alnum ) for T = std::string
*/,
qi::blank,
vec);
}
【问题讨论】:
-
忽略std::string的问题,你要使用的是list parser(
auto_%',')。 -
@cv_and_he 它就像一个魅力! list parser 的精神文档声称对于`a % b`:“这相当于a >> *(b >> a)”。但是使用 `auto_` 就不同了,因为它甚至不能编译。
-
auto_不适合 std::string,因为它可以匹配任何东西,真的 -
@cv_and_he 我想出了一种稍微不那么侵入性的方法来处理
std::string与auto_我认为在我更新的答案中。您可能也应该发布基于create_parser<>的版本作为答案...值得点赞。
标签: c++ boost boost-spirit boost-spirit-qi boost-phoenix