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