1 /*=============================================================================
2     Copyright (c) 2011 Thomas Bernard
3     http://spirit.sourceforge.net/
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 //[reference_includes
9 #include <boost/spirit/include/qi.hpp>
10 #include <boost/spirit/include/phoenix_core.hpp>
11 #include <boost/spirit/include/phoenix_operator.hpp>
12 #include <boost/spirit/include/phoenix_container.hpp>
13 #include <boost/spirit/include/phoenix_object.hpp>
14 #include <boost/spirit/include/phoenix_fusion.hpp>
15 #include <boost/fusion/include/adapt_struct.hpp>
16 #include <boost/spirit/repository/include/qi_kwd.hpp>
17 #include <boost/spirit/repository/include/qi_keywords.hpp>
18 #include <iostream>
19 #include <string>
20 #include <cstdlib>
21 #include <iterator>
22 //]
23 
24 
25 // Data structure definitions
26 
27 struct base_type {
base_typebase_type28     base_type(const std::string &name) : name(name)  {}
29     std::string name;
30 
outputbase_type31     virtual std::ostream &output(std::ostream &os) const
32     {
33         os<<"Base : "<<name;
34         return os;
35     }
36 
37 };
38 
39 struct derived1 : public base_type {
derived1derived140     derived1(const std::string &name, unsigned int data1) : base_type(name), data1(data1)  {}
41     unsigned int data1;
42 
outputderived143     virtual std::ostream &output(std::ostream &os) const
44     {
45         base_type::output(os);
46         os<<", "<<data1;
47         return os;
48     }
49 
50 };
51 
52 struct derived2 : public base_type {
derived2derived253     derived2(const std::string &name, unsigned int data2) : base_type(name), data2(data2)  {}
54     unsigned int data2;
outputderived255     virtual std::ostream &output(std::ostream &os) const
56     {
57         base_type::output(os);
58         os<<", "<<data2;
59         return os;
60     }
61 
62 };
63 
64 struct derived3 : public derived2 {
derived3derived365     derived3(const std::string &name, unsigned int data2, double data3) :
66         derived2(name,data2),
67         data3(data3)  {}
68     double data3;
69 
outputderived370     virtual std::ostream &output(std::ostream &os) const
71     {
72         derived2::output(os);
73         os<<", "<<data3;
74         return os;
75     }
76 
77 
78 };
79 
operator <<(std::ostream & os,const base_type & obj)80 std::ostream &operator<<(std::ostream &os, const base_type &obj)
81 {
82     return obj.output(os);
83 }
84 
85 BOOST_FUSION_ADAPT_STRUCT( base_type,
86     (std::string, name)
87 )
88 
89 BOOST_FUSION_ADAPT_STRUCT( derived1,
90     (std::string , name)
91     (unsigned int , data1)
92 )
93 BOOST_FUSION_ADAPT_STRUCT( derived2,
94     (std::string , name)
95     (unsigned int, data2)
96 )
97 BOOST_FUSION_ADAPT_STRUCT( derived3,
98     (std::string , name)
99     (unsigned int, data2)
100     (double, data3)
101 )
102 //]
103 
104 int
main()105 main()
106 {
107 
108 
109         using boost::spirit::repository::qi::kwd;
110         using boost::spirit::qi::inf;
111         using boost::spirit::ascii::space_type;
112         using boost::spirit::ascii::char_;
113         using boost::spirit::qi::double_;
114         using boost::spirit::qi::int_;
115         using boost::spirit::qi::rule;
116         using boost::spirit::_val;
117         using boost::spirit::_1;
118         using boost::spirit::_2;
119         using boost::spirit::_3;
120 
121 
122         //Rule declarations
123         rule<const char *, std::string(), space_type> parse_string;
124         rule<const char *, std::vector<base_type*>(), space_type> kwd_rule;
125 
126         // Our string parsing helper
127         parse_string   %= '"'> *(char_-'"') > '"';
128 
129         namespace phx=boost::phoenix;
130         //[ kwd rule
131         kwd_rule =
132             kwd("derived1")[ ('=' > parse_string > int_ ) [phx::push_back(_val,phx::new_<derived1>(_1,_2))] ]
133           / kwd("derived2")[ ('=' > parse_string > int_ )  [phx::push_back(_val,phx::new_<derived2>(_1,_2))]]
134           / kwd("derived3")[ ('=' > parse_string > int_ > double_)  [phx::push_back(_val,phx::new_<derived3>(_1,_2,_3))] ]
135           ;
136         //]
137 
138     using boost::spirit::qi::phrase_parse;
139     using boost::spirit::qi::ascii::space;
140 
141     // The result vector
142     std::vector<base_type*> result;
143 
144     char const input[]="derived2 = \"object1\" 10 derived3= \"object2\" 40 20.0 ";
145     char const* f(input);
146     char const* l(f + strlen(f));
147 
148     if (phrase_parse(f, l, kwd_rule, space,result) && (f == l))
149         std::cout << "ok" << std::endl;
150     else
151         std::cout << "fail" << std::endl;
152 
153     using namespace boost::phoenix::arg_names;
154     std::for_each(result.begin(),result.end(),std::cout<<*arg1<<std::endl);
155     // Clean up the vector of pointers
156     std::for_each(result.begin(),result.end(),phx::delete_(arg1));
157     return 0;
158 }
159