]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/qi/mini_xml1.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2010 Joel de Guzman
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 ///////////////////////////////////////////////////////////////////////////////
9 // A mini XML-like parser
11 // [ JDG March 25, 2007 ] spirit2
13 ///////////////////////////////////////////////////////////////////////////////
15 #include <boost/config/warning_disable.hpp>
16 #include <boost/spirit/include/qi.hpp>
17 #include <boost/spirit/include/phoenix_core.hpp>
18 #include <boost/spirit/include/phoenix_operator.hpp>
19 #include <boost/spirit/include/phoenix_fusion.hpp>
20 #include <boost/spirit/include/phoenix_stl.hpp>
21 #include <boost/fusion/include/adapt_struct.hpp>
22 #include <boost/variant/recursive_variant.hpp>
23 #include <boost/foreach.hpp>
32 namespace fusion
= boost::fusion
;
33 namespace phoenix
= boost::phoenix
;
34 namespace qi
= boost::spirit::qi
;
35 namespace ascii
= boost::spirit::ascii
;
37 ///////////////////////////////////////////////////////////////////////////
38 // Our mini XML tree representation
39 ///////////////////////////////////////////////////////////////////////////
40 //[tutorial_xml1_structures
45 boost::recursive_wrapper
<mini_xml
>
52 std::string name
; // tag name
53 std::vector
<mini_xml_node
> children
; // children
58 // We need to tell fusion about our mini_xml struct
59 // to make it a first-class fusion citizen
60 //[tutorial_xml1_adapt_structures
61 BOOST_FUSION_ADAPT_STRUCT(
64 (std::vector
<client::mini_xml_node
>, children
)
70 ///////////////////////////////////////////////////////////////////////////
71 // Print out the mini xml tree
72 ///////////////////////////////////////////////////////////////////////////
73 int const tabsize
= 4;
77 for (int i
= 0; i
< indent
; ++i
)
81 struct mini_xml_printer
83 mini_xml_printer(int indent
= 0)
88 void operator()(mini_xml
const& xml
) const;
93 struct mini_xml_node_printer
: boost::static_visitor
<>
95 mini_xml_node_printer(int indent
= 0)
100 void operator()(mini_xml
const& xml
) const
102 mini_xml_printer(indent
+tabsize
)(xml
);
105 void operator()(std::string
const& text
) const
108 std::cout
<< "text: \"" << text
<< '"' << std::endl
;
114 void mini_xml_printer::operator()(mini_xml
const& xml
) const
117 std::cout
<< "tag: " << xml
.name
<< std::endl
;
119 std::cout
<< '{' << std::endl
;
121 BOOST_FOREACH(mini_xml_node
const& node
, xml
.children
)
123 boost::apply_visitor(mini_xml_node_printer(indent
), node
);
127 std::cout
<< '}' << std::endl
;
130 ///////////////////////////////////////////////////////////////////////////
131 // Our mini XML grammar definition
132 ///////////////////////////////////////////////////////////////////////////
133 //[tutorial_xml1_grammar
134 template <typename Iterator
>
135 struct mini_xml_grammar
: qi::grammar
<Iterator
, mini_xml(), ascii::space_type
>
137 mini_xml_grammar() : mini_xml_grammar::base_type(xml
)
143 using namespace qi::labels
;
146 using phoenix::push_back
;
148 text
= lexeme
[+(char_
- '<') [_val
+= _1
]];
149 node
= (xml
| text
) [_val
= _1
];
154 >> lexeme
[+(char_
- '>') [_val
+= _1
]]
165 start_tag
[at_c
<0>(_val
) = _1
]
166 >> *node
[push_back(at_c
<1>(_val
), _1
)]
167 >> end_tag(at_c
<0>(_val
))
171 qi::rule
<Iterator
, mini_xml(), ascii::space_type
> xml
;
172 qi::rule
<Iterator
, mini_xml_node(), ascii::space_type
> node
;
173 qi::rule
<Iterator
, std::string(), ascii::space_type
> text
;
174 qi::rule
<Iterator
, std::string(), ascii::space_type
> start_tag
;
175 qi::rule
<Iterator
, void(std::string
), ascii::space_type
> end_tag
;
180 ///////////////////////////////////////////////////////////////////////////////
182 ///////////////////////////////////////////////////////////////////////////////
183 int main(int argc
, char **argv
)
185 char const* filename
;
192 std::cerr
<< "Error: No input file provided." << std::endl
;
196 std::ifstream
in(filename
, std::ios_base::in
);
200 std::cerr
<< "Error: Could not open input file: "
201 << filename
<< std::endl
;
205 std::string storage
; // We will read the contents here.
206 in
.unsetf(std::ios::skipws
); // No white space skipping!
208 std::istream_iterator
<char>(in
),
209 std::istream_iterator
<char>(),
210 std::back_inserter(storage
));
212 typedef client::mini_xml_grammar
<std::string::const_iterator
> mini_xml_grammar
;
213 mini_xml_grammar xml
; // Our grammar
214 client::mini_xml ast
; // Our tree
216 using boost::spirit::ascii::space
;
217 std::string::const_iterator iter
= storage
.begin();
218 std::string::const_iterator end
= storage
.end();
219 bool r
= phrase_parse(iter
, end
, xml
, space
, ast
);
221 if (r
&& iter
== end
)
223 std::cout
<< "-------------------------\n";
224 std::cout
<< "Parsing succeeded\n";
225 std::cout
<< "-------------------------\n";
226 client::mini_xml_printer printer
;
232 std::string::const_iterator some
= iter
+30;
233 std::string
context(iter
, (some
>end
)?end
:some
);
234 std::cout
<< "-------------------------\n";
235 std::cout
<< "Parsing failed\n";
236 std::cout
<< "stopped at: \": " << context
<< "...\"\n";
237 std::cout
<< "-------------------------\n";