]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/test/tree_to_xml.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / spirit / classic / test / tree_to_xml.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2007 Hartmut Kaiser
3 http://spirit.sourceforge.net/
4
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9
10 #include <boost/detail/lightweight_test.hpp>
11 #include <boost/preprocessor/cat.hpp>
12 #include <boost/spirit/include/classic_core.hpp>
13 #include <boost/spirit/include/classic_ast.hpp>
14 #include <boost/spirit/include/classic_tree_to_xml.hpp>
15
16 #ifdef _MSC_VER
17 # pragma warning(push)
18 # pragma warning(disable: 4702) // unreachable code
19 #endif
20 #include <boost/iostreams/stream.hpp>
21 #ifdef _MSC_VER
22 # pragma warning(pop)
23 #endif
24
25 #include <iostream>
26 #include <fstream>
27 #include <string>
28
29 using namespace BOOST_SPIRIT_CLASSIC_NS;
30
31 ///////////////////////////////////////////////////////////////////////////////
32 struct calculator : public grammar<calculator>
33 {
34 static const int integerID = 1;
35 static const int factorID = 2;
36 static const int termID = 3;
37 static const int expressionID = 4;
38
39 template <typename ScannerT>
40 struct definition
41 {
42 definition(calculator const& /*self*/)
43 {
44 // Start grammar definition
45 integer = leaf_node_d[ lexeme_d[
46 (!ch_p('-') >> +digit_p)
47 ] ];
48
49 factor = integer
50 | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
51 | (root_node_d[ch_p('-')] >> factor);
52
53 term = factor >>
54 *( (root_node_d[ch_p('*')] >> factor)
55 | (root_node_d[ch_p('/')] >> factor)
56 );
57
58 expression = term >>
59 *( (root_node_d[ch_p('+')] >> term)
60 | (root_node_d[ch_p('-')] >> term)
61 );
62 // End grammar definition
63
64 // turn on the debugging info.
65 BOOST_SPIRIT_DEBUG_RULE(integer);
66 BOOST_SPIRIT_DEBUG_RULE(factor);
67 BOOST_SPIRIT_DEBUG_RULE(term);
68 BOOST_SPIRIT_DEBUG_RULE(expression);
69 }
70
71 rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
72 rule<ScannerT, parser_context<>, parser_tag<termID> > term;
73 rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
74 rule<ScannerT, parser_context<>, parser_tag<integerID> > integer;
75
76 rule<ScannerT, parser_context<>, parser_tag<expressionID> > const&
77 start() const { return expression; }
78 };
79 };
80
81 ///////////////////////////////////////////////////////////////////////////////
82 /// this is a Boost.IoStreams source device usable to create a istream on
83 /// top of a random access container (i.e. vector<>)
84 template<typename Container>
85 class container_device
86 {
87 public:
88 typedef typename Container::value_type char_type;
89 typedef boost::iostreams::sink_tag category;
90
91 container_device(Container& container)
92 : container_(container), pos_(0)
93 {}
94
95 /// Write up to n characters to the underlying data sink into the
96 /// buffer s, returning the number of characters written
97 std::streamsize write(const char_type* s, std::streamsize n)
98 {
99 std::streamsize result = 0;
100 if (pos_ != container_.size()) {
101 std::streamsize amt =
102 static_cast<std::streamsize>(container_.size() - pos_);
103 result = (std::min)(n, amt);
104 std::copy(s, s + result, container_.begin() + pos_);
105 pos_ += static_cast<size_type>(result);
106 }
107 if (result < n) {
108 container_.insert(container_.end(), s, s + n);
109 pos_ = container_.size();
110 }
111 return n;
112 }
113
114 Container& container() { return container_; }
115
116 private:
117 typedef typename Container::size_type size_type;
118 Container& container_;
119 size_type pos_;
120 };
121
122 ///////////////////////////////////////////////////////////////////////////////
123 #define EXPECTED_XML_OUTPUT "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\
124 <!DOCTYPE parsetree SYSTEM \"parsetree.dtd\">\n\
125 <!-- 1+2 -->\n\
126 <parsetree version=\"1.0\">\n\
127 <parsenode>\n\
128 <value>+</value>\n\
129 <parsenode>\n\
130 <value>1</value>\n\
131 </parsenode>\n\
132 <parsenode>\n\
133 <value>2</value>\n\
134 </parsenode>\n\
135 </parsenode>\n\
136 </parsetree>\n"
137
138 #define EXPECTED_XML_OUTPUT_WIDE BOOST_PP_CAT(L, EXPECTED_XML_OUTPUT)
139
140 bool test(wchar_t const *text)
141 {
142 typedef std::basic_string<wchar_t>::iterator iterator_t;
143
144 std::basic_string<wchar_t> input(text);
145 calculator calc;
146 tree_parse_info<iterator_t> ast_info =
147 ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
148 calc >> end_p, space_p);
149
150 std::basic_string<wchar_t> out;
151 {
152 typedef container_device<std::basic_string<wchar_t> > device_type;
153 boost::iostreams::stream<device_type> outsink(out);
154 basic_tree_to_xml<wchar_t>(outsink, ast_info.trees, input);
155 }
156 return out == EXPECTED_XML_OUTPUT_WIDE;
157 }
158
159 bool test(char const *text)
160 {
161 typedef std::string::iterator iterator_t;
162
163 std::string input(text);
164 calculator calc;
165 tree_parse_info<iterator_t> ast_info =
166 ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
167 calc >> end_p, space_p);
168
169 std::string out;
170 {
171 typedef container_device<std::string> device_type;
172 boost::iostreams::stream<device_type> outsink(out);
173 basic_tree_to_xml<char>(outsink, ast_info.trees, input);
174 }
175 return out == EXPECTED_XML_OUTPUT;
176 }
177
178 int main()
179 {
180 BOOST_TEST(test("1+2"));
181 if (std::has_facet<std::ctype<wchar_t> >(std::locale()))
182 {
183 BOOST_TEST(test(L"1+2"));
184 }
185 return boost::report_errors();
186 }