attribute_of_qi_component
您可以从此处使用 Hartmut Kaiser 的元函数。这在内部使用了 ildjarn 为各个解析器建议的内容,除此之外,还适用于qi::int_ >> qi::lexeme[ qi::as_string[+qi::char_] ]
如下表达式。
#define BOOST_TEST_MODULE attr_of_qi_parsers
#include <boost/test/included/unit_test.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <utility>
#include <boost/fusion/include/adapted.hpp>
namespace qi = boost::spirit::qi;
typedef std::pair<int,int> pair_type;
typedef boost::fusion::vector2<int,std::string> vector_int_string;
struct data
{
data(){}
data(int m1, int m2): member1(m1), member2(m2) {}
int member1;
int member2;
};
std::ostream& operator<<(std::ostream& os, const data& d)
{
os << "{ 1st: " << d.member1 << ", 2nd: " << d.member2 << " }";
return os;
}
bool operator==(const data& lhs, const data& rhs)
{
return lhs.member1 == rhs.member1 && lhs.member2 == rhs.member2;
}
BOOST_FUSION_ADAPT_STRUCT(data,
(int, member1)
(int, member2)
)
//BOOST_CHECK_EQUAL requires that the arguments have defined operator<<
//You can either use in the global namespace
BOOST_TEST_DONT_PRINT_LOG_VALUE(pair_type);
//or define operator<< in the namespace std. This is technically illegal but it works
//namespace std
//{
// std::ostream& operator<<(std::ostream& os, const std::pair<int,int>& p)
// {
// os << "<" << p.first << "," << p.second << ">";
// return os;
// }
//}
namespace tests {
template <typename Expr, typename Iterator = boost::spirit::unused_type>
struct attribute_of_qi_component
{
typedef typename boost::spirit::result_of::compile<
qi::domain, Expr
>::type parser_expression_type;
typedef typename boost::spirit::traits::attribute_of<
parser_expression_type,
boost::spirit::unused_type, Iterator
>::type type;
};
template <typename P>
typename attribute_of_qi_component<P>::type parse(P const& p, const std::string& input)
{
std::string::const_iterator f = input.begin();
std::string::const_iterator l = input.end();
typename attribute_of_qi_component<P>::type parsed;
qi::phrase_parse(f, l, p, boost::spirit::ascii::space, parsed);
return parsed;
}
BOOST_AUTO_TEST_CASE(int_parser) {
BOOST_CHECK_EQUAL(parse(qi::int_, "23" ), 23);
}
BOOST_AUTO_TEST_CASE(int_and_string_parser) {
BOOST_CHECK_EQUAL(parse(qi::int_ >> qi::lexeme[ qi::as_string[+qi::char_] ], "23 is a number"), vector_int_string(23,"is a number"));
}
BOOST_AUTO_TEST_CASE(pair_rule_parser){
qi::rule<std::string::const_iterator,pair_type(),boost::spirit::ascii::space_type> pair_rule = qi::int_ >> ',' >> qi::int_;
BOOST_CHECK_EQUAL(parse(pair_rule,"1, 2"), std::make_pair(1,2));
}
BOOST_AUTO_TEST_CASE(data_rule_parser){
qi::rule<std::string::const_iterator,data(),boost::spirit::ascii::space_type> data_rule = qi::int_ >> ',' >> qi::int_;
BOOST_CHECK_EQUAL(parse(data_rule,"2, 4"), data(2,4));
}
}//end of tests namespace