]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/qi/mini_xml3.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / example / qi / mini_xml3.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2010 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 =============================================================================*/
7 ///////////////////////////////////////////////////////////////////////////////
8 //
9 // A mini XML-like parser
10 //
11 // [ JDG March 25, 2007 ] spirit2
12 //
13 ///////////////////////////////////////////////////////////////////////////////
14
15 #include <boost/spirit/include/qi.hpp>
16 #include <boost/phoenix/core.hpp>
17 #include <boost/phoenix/operator.hpp>
18 #include <boost/phoenix/fusion.hpp>
19 #include <boost/phoenix/stl.hpp>
20 #include <boost/phoenix/object.hpp>
21 #include <boost/fusion/include/adapt_struct.hpp>
22 #include <boost/variant/recursive_variant.hpp>
23 #include <boost/foreach.hpp>
24
25 #include <iostream>
26 #include <fstream>
27 #include <string>
28 #include <vector>
29
30 namespace client
31 {
32 namespace fusion = boost::fusion;
33 namespace phoenix = boost::phoenix;
34 namespace qi = boost::spirit::qi;
35 namespace ascii = boost::spirit::ascii;
36
37 ///////////////////////////////////////////////////////////////////////////
38 // Our mini XML tree representation
39 ///////////////////////////////////////////////////////////////////////////
40 struct mini_xml;
41
42 typedef
43 boost::variant<
44 boost::recursive_wrapper<mini_xml>
45 , std::string
46 >
47 mini_xml_node;
48
49 struct mini_xml
50 {
51 std::string name; // tag name
52 std::vector<mini_xml_node> children; // children
53 };
54 }
55
56 // We need to tell fusion about our mini_xml struct
57 // to make it a first-class fusion citizen
58 BOOST_FUSION_ADAPT_STRUCT(
59 client::mini_xml,
60 (std::string, name)
61 (std::vector<client::mini_xml_node>, children)
62 )
63
64 namespace client
65 {
66 ///////////////////////////////////////////////////////////////////////////
67 // Print out the mini xml tree
68 ///////////////////////////////////////////////////////////////////////////
69 int const tabsize = 4;
70
71 void tab(int indent)
72 {
73 for (int i = 0; i < indent; ++i)
74 std::cout << ' ';
75 }
76
77 struct mini_xml_printer
78 {
79 mini_xml_printer(int indent = 0)
80 : indent(indent)
81 {
82 }
83
84 void operator()(mini_xml const& xml) const;
85
86 int indent;
87 };
88
89 struct mini_xml_node_printer : boost::static_visitor<>
90 {
91 mini_xml_node_printer(int indent = 0)
92 : indent(indent)
93 {
94 }
95
96 void operator()(mini_xml const& xml) const
97 {
98 mini_xml_printer(indent+tabsize)(xml);
99 }
100
101 void operator()(std::string const& text) const
102 {
103 tab(indent+tabsize);
104 std::cout << "text: \"" << text << '"' << std::endl;
105 }
106
107 int indent;
108 };
109
110 void mini_xml_printer::operator()(mini_xml const& xml) const
111 {
112 tab(indent);
113 std::cout << "tag: " << xml.name << std::endl;
114 tab(indent);
115 std::cout << '{' << std::endl;
116
117 BOOST_FOREACH(mini_xml_node const& node, xml.children)
118 {
119 boost::apply_visitor(mini_xml_node_printer(indent), node);
120 }
121
122 tab(indent);
123 std::cout << '}' << std::endl;
124 }
125
126 ///////////////////////////////////////////////////////////////////////////
127 // Our mini XML grammar definition
128 ///////////////////////////////////////////////////////////////////////////
129 //[tutorial_xml3_grammar
130 template <typename Iterator>
131 struct mini_xml_grammar
132 : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
133 {
134 mini_xml_grammar()
135 : mini_xml_grammar::base_type(xml, "xml")
136 {
137 using qi::lit;
138 using qi::lexeme;
139 using qi::on_error;
140 using qi::fail;
141 using ascii::char_;
142 using ascii::string;
143 using namespace qi::labels;
144
145 using phoenix::construct;
146 using phoenix::val;
147
148 text %= lexeme[+(char_ - '<')];
149 node %= xml | text;
150
151 start_tag %=
152 '<'
153 >> !lit('/')
154 > lexeme[+(char_ - '>')]
155 > '>'
156 ;
157
158 end_tag =
159 "</"
160 > lit(_r1)
161 > '>'
162 ;
163
164 xml %=
165 start_tag[_a = _1]
166 > *node
167 > end_tag(_a)
168 ;
169
170 xml.name("xml");
171 node.name("node");
172 text.name("text");
173 start_tag.name("start_tag");
174 end_tag.name("end_tag");
175
176 on_error<fail>
177 (
178 xml
179 , std::cout
180 << val("Error! Expecting ")
181 << _4 // what failed?
182 << val(" here: \"")
183 << construct<std::string>(_3, _2) // iterators to error-pos, end
184 << val("\"")
185 << std::endl
186 );
187 }
188
189 qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
190 qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
191 qi::rule<Iterator, std::string(), ascii::space_type> text;
192 qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
193 qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
194 };
195 //]
196 }
197
198 ///////////////////////////////////////////////////////////////////////////////
199 // Main program
200 ///////////////////////////////////////////////////////////////////////////////
201 int main(int argc, char **argv)
202 {
203 char const* filename;
204 if (argc > 1)
205 {
206 filename = argv[1];
207 }
208 else
209 {
210 std::cerr << "Error: No input file provided." << std::endl;
211 return 1;
212 }
213
214 std::ifstream in(filename, std::ios_base::in);
215
216 if (!in)
217 {
218 std::cerr << "Error: Could not open input file: "
219 << filename << std::endl;
220 return 1;
221 }
222
223 std::string storage; // We will read the contents here.
224 in.unsetf(std::ios::skipws); // No white space skipping!
225 std::copy(
226 std::istream_iterator<char>(in),
227 std::istream_iterator<char>(),
228 std::back_inserter(storage));
229
230 typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
231 mini_xml_grammar xml; // Our grammar
232 client::mini_xml ast; // Our tree
233
234 using boost::spirit::ascii::space;
235 std::string::const_iterator iter = storage.begin();
236 std::string::const_iterator end = storage.end();
237 bool r = phrase_parse(iter, end, xml, space, ast);
238
239 if (r && iter == end)
240 {
241 std::cout << "-------------------------\n";
242 std::cout << "Parsing succeeded\n";
243 std::cout << "-------------------------\n";
244 client::mini_xml_printer printer;
245 printer(ast);
246 return 0;
247 }
248 else
249 {
250 std::cout << "-------------------------\n";
251 std::cout << "Parsing failed\n";
252 std::cout << "-------------------------\n";
253 return 1;
254 }
255 }
256
257