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