假设我有一个std::string
属性,但为了便于解析,我想使用qi::int_
或qi::double_
。
是否有一种简单的方法可以将转换作为语义操作?
我试过这样的事情:
std::stringstream ss;
my_int_as_str = qi::int_ [ ref(ss)<<_1; _val=ss.str() ];
但这甚至不会编译。
编辑 - 尝试下面的回答
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;
int main(int argc, char* argv[])
{
std::string test="123";
std::string result;
// 1. qi::raw[ qi::int_ ] works
// 2. qi::lexeme[ qi::int_ ] doesn't
// 3. qi::as_string[ qi::int_ ] doesn't
qi::rule<std::string::const_iterator, std::string()> my_int_as_str =
qi::raw[ qi::int_ ];
parse( test.cbegin(), test.cend(), my_int_as_str, result );
std::cout << result << std::endl;
// -------------------------------------------------------------------------
std::string test_vector="456 789";
std::vector<std::string> result_vector;
// 4. qi::raw[ qi::int_ ] won't compile
// 5. qi::lexeme[ qi::int_ ] won't compile
// 6. qi::as_string[ qi::int_ ] doesn't
qi::rule<std::string::const_iterator,std::vector<std::string>(),qi::space_type>
my_int_as_str_vector = qi::lexeme[ qi::int_ ];
phrase_parse(test_vector.cbegin(),test_vector.cend(),
my_int_as_str_vector,qi::space,result_vector);
for(auto& string: result_vector)
std::cout << string << std::endl;
return 0;
}
答案 0 :(得分:6)
您可以使用attr_cast
为您的类型专门设置transform_attribute
。
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;
namespace boost { namespace spirit { namespace traits
{
template <>
struct transform_attribute<std::string, int, qi::domain>
{
typedef int type;
static int pre(std::string& d) { return 0; }//not useful in this case but required to avoid compiler errors
static void post(std::string& val, int const& attr) //`val` is the "returned" string, `attr` is what int_ parses
{
std::stringstream ss;
ss << attr;
val= ss.str();
}
static void fail(std::string&) {}
};
}}}
int main(int argc, char* argv[])
{
std::string test="123";
std::string test_vector="456 789";
qi::rule<std::string::const_iterator,std::string()> my_int_as_str = qi::attr_cast(qi::int_);
qi::rule<std::string::const_iterator,std::vector<std::string>(),qi::space_type> my_int_as_str_vector= *qi::attr_cast(qi::int_);
std::string result;
std::vector<std::string> result_vector;
parse(test.cbegin(),test.cend(),my_int_as_str,result);
phrase_parse(test_vector.cbegin(),test_vector.cend(),my_int_as_str_vector,qi::space,result_vector);
std::cout << result << std::endl;
for(auto& string: result_vector)
std::cout << string << std::endl;
return 0;
}
如果你真的需要/想要使用semantic actions,最简单的替代方法是定义一个以int作为参数并返回一个字符串的函数(这比attr_cast
替代方案简单,但它也是在我真正简单的基准测试中,速度慢了近两倍):
std::string semantic_transform(int i)
{
std::stringstream ss;
ss<<i;
return ss.str();
}
...
std::string string_semantic;
qi::parse(test.cbegin(),test.cend(),qi::int_[&semantic_transform],string_semantic);
std::cout << string_semantic << std::endl;
答案 1 :(得分:6)
内置方式:
qi::rule<Iterator, std::string()> my_int_as_str =
qi::as_string [ qi::int_ ];
对于这个特殊的简单情况,qi::raw
或qi::lexeme
同样可以正常工作,因为它们都公开了源 - 迭代器对,它们内置赋值给属性 std::string
<强>诠:强>
my_int_as_str = qi::lexeme [ qi::int_ ]; // equivalent
my_int_as_str = qi::raw [ qi::int_ ]; // idem