]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / example / karma / mini_xml_karma.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2010 Joel de Guzman
3 Copyright (c) 2001-2010 Hartmut Kaiser
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, Karma is used to print out the generated AST
11 //
12 // [ JDG March 25, 2007 ] spirit2
13 // [ HK April 02, 2007 ] spirit2
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include <boost/config/warning_disable.hpp>
18
19 #include <boost/spirit/include/qi.hpp>
20 #include <boost/spirit/include/karma.hpp>
21 #include <boost/spirit/include/phoenix_core.hpp>
22 #include <boost/spirit/include/phoenix_operator.hpp>
23 #include <boost/spirit/include/phoenix_fusion.hpp>
24 #include <boost/spirit/include/phoenix_function.hpp>
25 #include <boost/spirit/include/phoenix_stl.hpp>
26 #include <boost/fusion/include/adapt_struct.hpp>
27 #include <boost/variant/recursive_variant.hpp>
28
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32 #include <vector>
33
34 using namespace boost::spirit;
35 using namespace boost::spirit::ascii;
36
37 namespace fusion = boost::fusion;
38 namespace phoenix = boost::phoenix;
39
40 using phoenix::at_c;
41 using phoenix::push_back;
42
43 ///////////////////////////////////////////////////////////////////////////////
44 // Our mini XML tree representation
45 ///////////////////////////////////////////////////////////////////////////////
46 struct mini_xml;
47
48 typedef
49 boost::variant<
50 boost::recursive_wrapper<mini_xml>
51 , std::string
52 >
53 mini_xml_node;
54
55 struct mini_xml
56 {
57 std::string name; // tag name
58 std::vector<mini_xml_node> children; // children
59 };
60
61 // We need to tell fusion about our mini_xml struct
62 // to make it a first-class fusion citizen
63 BOOST_FUSION_ADAPT_STRUCT(
64 mini_xml,
65 (std::string, name)
66 (std::vector<mini_xml_node>, children)
67 )
68
69 ///////////////////////////////////////////////////////////////////////////////
70 // Our mini XML grammar definition
71 ///////////////////////////////////////////////////////////////////////////////
72 template <typename Iterator>
73 struct mini_xml_parser :
74 qi::grammar<Iterator, mini_xml(), space_type>
75 {
76 mini_xml_parser() : mini_xml_parser::base_type(xml)
77 {
78 text = lexeme[+(char_ - '<') [_val += _1]];
79 node = (xml | text) [_val = _1];
80
81 start_tag =
82 '<'
83 >> !lit('/')
84 >> lexeme[+(char_ - '>') [_val += _1]]
85 >> '>'
86 ;
87
88 end_tag =
89 "</"
90 >> lit(_r1)
91 >> '>'
92 ;
93
94 xml =
95 start_tag [at_c<0>(_val) = _1]
96 >> *node [push_back(at_c<1>(_val), _1)]
97 >> end_tag(at_c<0>(_val))
98 ;
99 }
100
101 qi::rule<Iterator, mini_xml(), space_type> xml;
102 qi::rule<Iterator, mini_xml_node(), space_type> node;
103 qi::rule<Iterator, std::string(), space_type> text;
104 qi::rule<Iterator, std::string(), space_type> start_tag;
105 qi::rule<Iterator, void(std::string), space_type> end_tag;
106 };
107
108 ///////////////////////////////////////////////////////////////////////////////
109 // A couple of phoenix functions helping to access the elements of the
110 // generated AST
111 ///////////////////////////////////////////////////////////////////////////////
112 template <typename T>
113 struct get_element
114 {
115 template <typename T1>
116 struct result { typedef T const& type; };
117
118 T const& operator()(mini_xml_node const& node) const
119 {
120 return boost::get<T>(node);
121 }
122 };
123
124 phoenix::function<get_element<std::string> > _string;
125 phoenix::function<get_element<mini_xml> > _xml;
126
127 ///////////////////////////////////////////////////////////////////////////////
128 // The output grammar defining the format of the generated data
129 ///////////////////////////////////////////////////////////////////////////////
130 template <typename OutputIterator>
131 struct mini_xml_generator
132 : karma::grammar<OutputIterator, mini_xml()>
133 {
134 mini_xml_generator() : mini_xml_generator::base_type(xml)
135 {
136 node %= string | xml;
137 xml =
138 '<' << string[_1 = at_c<0>(_val)] << '>'
139 << (*node)[_1 = at_c<1>(_val)]
140 << "</" << string[_1 = at_c<0>(_val)] << '>'
141 ;
142 }
143
144 karma::rule<OutputIterator, mini_xml()> xml;
145 karma::rule<OutputIterator, mini_xml_node()> node;
146 };
147
148 ///////////////////////////////////////////////////////////////////////////////
149 // Main program
150 ///////////////////////////////////////////////////////////////////////////////
151 int main(int argc, char **argv)
152 {
153 char const* filename;
154 if (argc > 1)
155 {
156 filename = argv[1];
157 }
158 else
159 {
160 std::cerr << "Error: No input file provided." << std::endl;
161 return 1;
162 }
163
164 std::ifstream in(filename, std::ios_base::in);
165
166 if (!in)
167 {
168 std::cerr << "Error: Could not open input file: "
169 << filename << std::endl;
170 return 1;
171 }
172
173 std::string storage; // We will read the contents here.
174 in.unsetf(std::ios::skipws); // No white space skipping!
175 std::copy(
176 std::istream_iterator<char>(in),
177 std::istream_iterator<char>(),
178 std::back_inserter(storage));
179
180 typedef mini_xml_parser<std::string::const_iterator> mini_xml_parser;
181 mini_xml_parser xmlin; // Our grammar definition
182 mini_xml ast; // our tree
183
184 std::string::const_iterator iter = storage.begin();
185 std::string::const_iterator end = storage.end();
186 bool r = qi::phrase_parse(iter, end, xmlin, space, ast);
187
188 if (r && iter == end)
189 {
190 std::cout << "-------------------------\n";
191 std::cout << "Parsing succeeded\n";
192 std::cout << "-------------------------\n";
193
194 typedef std::back_insert_iterator<std::string> outiter_type;
195 typedef mini_xml_generator<outiter_type> mini_xml_generator;
196
197 mini_xml_generator xmlout; // Our grammar definition
198
199 std::string generated;
200 outiter_type outit(generated);
201 bool r = karma::generate(outit, xmlout, ast);
202
203 if (r)
204 std::cout << generated << std::endl;
205 return 0;
206 }
207 else
208 {
209 std::string::const_iterator begin = storage.begin();
210 std::size_t dist = std::distance(begin, iter);
211 std::string::const_iterator some =
212 iter + (std::min)(storage.size()-dist, std::size_t(30));
213 std::string context(iter, some);
214 std::cout << "-------------------------\n";
215 std::cout << "Parsing failed\n";
216 std::cout << "stopped at: \": " << context << "...\"\n";
217 std::cout << "-------------------------\n";
218 return 1;
219 }
220 }
221
222