]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/test/tree_tests.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / classic / test / tree_tests.cpp
1 /*=============================================================================
2 Copyright (c) 2003 Giovanni Bajo
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 #include <boost/spirit/include/classic_core.hpp>
10 #include <boost/spirit/include/classic_ast.hpp>
11 #include <boost/spirit/include/classic_tree_to_xml.hpp>
12 #include <boost/preprocessor/arithmetic/inc.hpp>
13 #include <boost/preprocessor/punctuation/comma_if.hpp>
14 #include <boost/preprocessor/repetition.hpp>
15 #include <boost/preprocessor/arithmetic/sub.hpp>
16 #include <boost/mpl/list.hpp>
17 #include <boost/mpl/apply.hpp>
18 #include <boost/mpl/remove.hpp>
19 #include <boost/mpl/size.hpp>
20 #include <boost/mpl/for_each.hpp>
21
22 #include <map>
23 #include <string>
24
25 #include <fstream>
26 #include <boost/core/lightweight_test.hpp>
27 #include "impl/string_length.hpp"
28
29 #define DEBUG_DUMP_TREES (1)
30
31 //////////////////////////////////////////////////////////////////////////////
32 // rule_id helper
33 // http://sf.net/tracker/index.php?func=detail&aid=715483&group_id=28447&atid=393389)
34
35 namespace boost { namespace spirit {
36
37 template <
38 typename ScannerT,
39 unsigned long ID = 0,
40 typename ContextT = parser_context<> >
41 class rule_id
42 : public rule<ScannerT, ContextT, parser_tag<ID> >
43 {
44 typedef rule<ScannerT, ContextT, parser_tag<ID> > base_t;
45
46 public:
47 // Forward ctors and operator=.
48 rule_id()
49 {}
50
51 template <typename T>
52 rule_id(const T& a)
53 : base_t(a) {}
54
55 template <typename T>
56 rule_id& operator=(const T& a)
57 { base_t::operator=(a); return *this; }
58 };
59 }}
60
61
62 //////////////////////////////////////////////////////////////////////////////
63 // Framework setup
64
65 namespace mpl = boost::mpl;
66 using namespace BOOST_SPIRIT_CLASSIC_NS;
67 using namespace std;
68
69
70 enum RULE_ID
71 {
72 ID_A = 1,
73 ID_B,
74 ID_C,
75 ID_ROOT
76 };
77
78 map<parser_id, string> rule_names;
79
80
81 //////////////////////////////////////////////////////////////////////////////
82 // Generic tree manipulation tools
83
84 template <typename TreeT>
85 RULE_ID id(TreeT& t)
86 { return (RULE_ID)t.value.id().to_long(); }
87
88
89 template <typename TreeT>
90 TreeT& child(TreeT& t, unsigned n)
91 {
92 return t.children[n];
93 }
94
95 template <typename TreeT>
96 size_t num_children(const TreeT& t)
97 { return t.children.size(); }
98
99 template <typename TreeT>
100 typename TreeT::parse_node_t::iterator_t ValueBeginIterator(TreeT& t)
101 { return t.value.begin(); }
102
103 template <typename TreeT>
104 typename TreeT::parse_node_t::iterator_t ValueEndIterator(TreeT& t)
105 { return t.value.end(); }
106
107 template <typename TreeT>
108 bool equal(TreeT& a, TreeT& b)
109 {
110 if (id(a) != id(b))
111 return false;
112
113 if (num_children(a) != num_children(b))
114 return false;
115
116 unsigned n = num_children(a);
117 for (unsigned i=0;i<n;i++)
118 if (!equal(child(a, i), child(b, i)))
119 return false;
120
121 return true;
122 }
123
124 template <typename TreeT>
125 void dump(ostream& o, TreeT& t, int level = 0)
126 {
127 string name;
128 string value;
129 map<parser_id, string>::iterator iter =
130 rule_names.find(id(t));
131
132 if (iter == rule_names.end())
133 name = "noname";
134 else
135 name = iter->second;
136
137 value.assign(ValueBeginIterator(t), ValueEndIterator(t));
138
139 for (int i=0;i<level;i++)
140 o << " ";
141
142
143 o << name << ": " << value << endl;
144
145 unsigned n = num_children(t);
146 for (unsigned c=0;c<n;c++)
147 dump(o, child(t, c), level+1);
148 }
149
150
151 //////////////////////////////////////////////////////////////////////////////
152 // Tree folding
153
154 namespace test_impl {
155
156 template <typename ParmT>
157 struct fold_node
158 {
159 // assign a subtree
160 void operator()(ParmT& t, ParmT ch) const
161 { t = ch; }
162
163 // wrong specialization
164 template <typename TreeT>
165 void operator()(TreeT& t, ParmT p) const
166 { typedef typename TreeT::this_should_never_be_compiled type; }
167 };
168
169 template <>
170 struct fold_node<nil_t>
171 {
172 template <typename TreeT>
173 void operator()(TreeT& t, nil_t) const
174 { typedef typename TreeT::this_should_never_be_compiled type; }
175 };
176
177 template <>
178 struct fold_node<RULE_ID>
179 {
180 template <typename TreeT>
181 void operator()(TreeT& t, RULE_ID id) const
182 { t.value.id(id); }
183 };
184
185 template <typename ParmT>
186 struct fold_child
187 {
188 template <typename TreeT>
189 void operator()(TreeT& t, ParmT p, unsigned n) const
190 { fold_node<ParmT>()(t.children[n], p); }
191 };
192
193 template <>
194 struct fold_child<nil_t>
195 {
196 template <typename TreeT>
197 void operator()(TreeT& t, nil_t, unsigned n) const
198 {}
199 };
200 }
201
202 template <typename TreeT,
203 typename T, typename T1, typename T2, typename T3, typename T4,
204 typename T5, typename T6, typename T7, typename T8>
205 TreeT fold(T p, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
206 {
207 // Prepare a list with all the template types
208 typedef mpl::list<T1,T2,T3,T4,T5,T6,T7,T8> full_list_t;
209
210 // Remove the ones equal to nil_t: they are the default parameters
211 // unspecified from the user
212 typedef typename mpl::remove<full_list_t, nil_t>::type parm_list_t;
213
214 // Get the size of the list = number of parameters specified by the user
215 typedef typename mpl::size<parm_list_t>::type parm_list_size_t;
216 enum { NUM_CHILDREN = parm_list_size_t::value };
217
218 TreeT t;
219
220 // Generate the root of the tree (specialized for the first parameter)
221 test_impl::fold_node<T>()(t, p);
222
223 // Make room for the children
224 if (NUM_CHILDREN > 0)
225 t.children.resize(NUM_CHILDREN);
226
227 // For each children, call the GenerateChild function, which is specialized
228 // on the different types
229 test_impl::fold_child<T1>()(t, p1, 0);
230 test_impl::fold_child<T2>()(t, p2, 1);
231 test_impl::fold_child<T3>()(t, p3, 2);
232 test_impl::fold_child<T4>()(t, p4, 3);
233 test_impl::fold_child<T5>()(t, p5, 4);
234 test_impl::fold_child<T6>()(t, p6, 5);
235 test_impl::fold_child<T7>()(t, p7, 6);
236 test_impl::fold_child<T8>()(t, p8, 7);
237
238 return t;
239 }
240
241
242 // Define fold() wrapper for 1->7 parameters: they just call the 8 parameter
243 // version passing nil_t for the other arguments
244 #define PUT_EMPTY(Z, N, _) nil_t()
245
246 #define DEFINE_FOLD(Z, N, _) \
247 template <typename TreeT, typename T BOOST_PP_COMMA_IF(N) \
248 BOOST_PP_ENUM_PARAMS(N, typename T) > \
249 TreeT fold(T p BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS(N, T, p)) \
250 { \
251 return fold<TreeT>(p \
252 BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, p) \
253 BOOST_PP_COMMA_IF(BOOST_PP_SUB(8,N)) \
254 BOOST_PP_ENUM(BOOST_PP_SUB(8,N), PUT_EMPTY, _)); \
255 }
256
257 BOOST_PP_REPEAT(7, DEFINE_FOLD, _)
258
259 #undef PUT_EMPTY
260 #undef DEFINE_FOLD
261
262
263
264 //////////////////////////////////////////////////////////////////////////////
265 // test_banal: simple tree construction
266
267 struct test_banal : public grammar<test_banal>
268 {
269 template <class T>
270 struct definition
271 {
272 rule_id<T, ID_ROOT> root;
273 rule_id<T, ID_A> a;
274 rule_id<T, ID_B> b;
275 rule_id<T, ID_C> c;
276
277 definition(const test_banal&)
278 {
279 root = a >> c;
280 a = b;
281 b = chlit<>('b');
282 c = chlit<>('c');
283 }
284
285 const rule_id<T, ID_ROOT>& start()
286 { return root; }
287 };
288
289 const char* pattern(void)
290 {
291 return "bc";
292 }
293
294 template <typename TreeT>
295 TreeT expected_tree(void)
296 {
297 return fold<TreeT>(
298 ID_ROOT, fold<TreeT>(
299 ID_A,
300 ID_B),
301 ID_C);
302 }
303 };
304
305
306 //////////////////////////////////////////////////////////////////////////////
307 // All the tests
308
309 typedef mpl::list
310 <
311 test_banal
312
313 > tests_t;
314
315
316 //////////////////////////////////////////////////////////////////////////////
317 // run_test - code to run a test
318
319 struct run_test
320 {
321 template <typename TestT>
322 void operator()(TestT gram)
323 {
324 typedef const char* iterator_t;
325 typedef node_val_data_factory<nil_t> factory_t;
326 typedef typename
327 factory_t
328 ::BOOST_NESTED_TEMPLATE factory<iterator_t>
329 ::node_t node_t;
330 typedef tree_node<node_t> tree_t;
331
332 iterator_t text_begin = gram.pattern();
333 iterator_t text_end = text_begin + test_impl::string_length(text_begin);
334
335 tree_parse_info<iterator_t, factory_t> info =
336 ast_parse(text_begin, text_end, gram);
337
338 BOOST_TEST(info.full);
339
340 tree_t expected = gram.template expected_tree<tree_t>();
341
342 #if DEBUG_DUMP_TREES
343 dump(cout, info.trees[0]);
344 dump(cout, expected);
345 #endif
346
347 BOOST_TEST(equal(info.trees[0], expected));
348 }
349 };
350
351 //////////////////////////////////////////////////////////////////////////////
352 // main() stuff
353
354 #ifdef BOOST_NO_EXCEPTIONS
355 namespace boost
356 {
357 void throw_exception(std::exception const & )
358 {
359 std::cerr << "Exception caught" << std::endl;
360 BOOST_TEST(0);
361 }
362 }
363
364 #endif
365
366
367 void init(void)
368 {
369 rule_names[ID_ROOT] = "ID_ROOT";
370 rule_names[ID_A] = "ID_A";
371 rule_names[ID_B] = "ID_B";
372 rule_names[ID_C] = "ID_C";
373 }
374
375
376 int main()
377 {
378 init();
379
380 mpl::for_each<tests_t, mpl::_> (run_test());
381
382 return boost::report_errors();
383 }