/*============================================================================= Copyright (c) 2011 Thomas Bernard http://spirit.sourceforge.net/ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ //[reference_includes #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_container.hpp> #include <boost/spirit/include/phoenix_object.hpp> #include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/repository/include/qi_kwd.hpp> #include <boost/spirit/repository/include/qi_keywords.hpp> #include <iostream> #include <string> #include <cstdlib> #include <iterator> //] // Data structure definitions struct base_type { base_type(const std::string &name) : name(name) {} std::string name; virtual std::ostream &output(std::ostream &os) const { os<<"Base : "<<name; return os; } }; struct derived1 : public base_type { derived1(const std::string &name, unsigned int data1) : base_type(name), data1(data1) {} unsigned int data1; virtual std::ostream &output(std::ostream &os) const { base_type::output(os); os<<", "<<data1; return os; } }; struct derived2 : public base_type { derived2(const std::string &name, unsigned int data2) : base_type(name), data2(data2) {} unsigned int data2; virtual std::ostream &output(std::ostream &os) const { base_type::output(os); os<<", "<<data2; return os; } }; struct derived3 : public derived2 { derived3(const std::string &name, unsigned int data2, double data3) : derived2(name,data2), data3(data3) {} double data3; virtual std::ostream &output(std::ostream &os) const { derived2::output(os); os<<", "<<data3; return os; } }; std::ostream &operator<<(std::ostream &os, const base_type &obj) { return obj.output(os); } BOOST_FUSION_ADAPT_STRUCT( base_type, (std::string, name) ) BOOST_FUSION_ADAPT_STRUCT( derived1, (std::string , name) (unsigned int , data1) ) BOOST_FUSION_ADAPT_STRUCT( derived2, (std::string , name) (unsigned int, data2) ) BOOST_FUSION_ADAPT_STRUCT( derived3, (std::string , name) (unsigned int, data2) (double, data3) ) //] int main() { using boost::spirit::repository::qi::kwd; using boost::spirit::qi::inf; using boost::spirit::ascii::space_type; using boost::spirit::ascii::char_; using boost::spirit::qi::double_; using boost::spirit::qi::int_; using boost::spirit::qi::rule; using boost::spirit::_val; using boost::spirit::_1; using boost::spirit::_2; using boost::spirit::_3; //Rule declarations rule<const char *, std::string(), space_type> parse_string; rule<const char *, std::vector<base_type*>(), space_type> kwd_rule; // Our string parsing helper parse_string %= '"'> *(char_-'"') > '"'; namespace phx=boost::phoenix; //[ kwd rule kwd_rule = kwd("derived1")[ ('=' > parse_string > int_ ) [phx::push_back(_val,phx::new_<derived1>(_1,_2))] ] / kwd("derived2")[ ('=' > parse_string > int_ ) [phx::push_back(_val,phx::new_<derived2>(_1,_2))]] / kwd("derived3")[ ('=' > parse_string > int_ > double_) [phx::push_back(_val,phx::new_<derived3>(_1,_2,_3))] ] ; //] using boost::spirit::qi::phrase_parse; using boost::spirit::qi::ascii::space; // The result vector std::vector<base_type*> result; char const input[]="derived2 = \"object1\" 10 derived3= \"object2\" 40 20.0 "; char const* f(input); char const* l(f + strlen(f)); if (phrase_parse(f, l, kwd_rule, space,result) && (f == l)) std::cout << "ok" << std::endl; else std::cout << "fail" << std::endl; using namespace boost::phoenix::arg_names; std::for_each(result.begin(),result.end(),std::cout<<*arg1<<std::endl); // Clean up the vector of pointers std::for_each(result.begin(),result.end(),phx::delete_(arg1)); return 0; }