]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/classic/test/traverse_tests.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / classic / test / traverse_tests.cpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2002-2003 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//
11// Traversal tests
12//
13///////////////////////////////////////////////////////////////////////////////
14
1e59de90 15#include <boost/core/lightweight_test.hpp>
7c673cae
FG
16#include <iostream>
17#include <string>
18#include <vector>
19
20#include <boost/config.hpp>
21#include <boost/static_assert.hpp>
22
23#ifdef BOOST_NO_STRINGSTREAM
24#include <strstream>
25#define OSSTREAM std::ostrstream
26std::string GETSTRING(std::ostrstream& ss)
27{
28 ss << ends;
29 std::string rval = ss.str();
30 ss.freeze(false);
31 return rval;
32}
33#else
34#include <sstream>
35#define GETSTRING(ss) ss.str()
36#define OSSTREAM std::ostringstream
37#endif
38
39#ifndef BOOST_SPIRIT_DEBUG
40#define BOOST_SPIRIT_DEBUG // needed for parser_name functions
41#endif
42
43#include <boost/spirit/include/classic_core.hpp>
44#include <boost/spirit/include/classic_assign_actor.hpp>
45#include <boost/spirit/include/classic_meta.hpp>
46
7c673cae
FG
47using namespace BOOST_SPIRIT_CLASSIC_NS;
48
49typedef ref_value_actor<char, assign_action> assign_actor;
50
51///////////////////////////////////////////////////////////////////////////////
52//
53// Test identity transformation
54//
55///////////////////////////////////////////////////////////////////////////////
56void
57traverse_identity_tests()
58{
59 // test type equality
60 typedef sequence<chlit<char>, chlit<char> > test_sequence1_t;
61 BOOST_STATIC_ASSERT((
62 ::boost::is_same<
63 test_sequence1_t,
64 post_order::result<identity_transform, test_sequence1_t>::type
65 >::value
66 ));
67
68 // test (rough) runtime equality
69 BOOST_TEST(
70 parse(
71 "ab",
72 post_order::traverse(identity_transform(), ch_p('a') >> 'b')
73 ).full
74 );
75 BOOST_TEST(
76 !parse(
77 "ba",
78 post_order::traverse(identity_transform(), ch_p('a') >> 'b')
79 ).hit
80 );
81
82 ///////////////////////////////////////////////////////////////////////////
83 BOOST_TEST(
84 !parse(
85 "cba",
86 post_order::traverse(
87 identity_transform(),
88 ch_p('a') >> 'b' >> 'c'
89 )
90 ).hit
91 );
92
93///////////////////////////////////////////////////////////////////////////////
94// Test more complex sequences
95char c;
96
97///////////////////////////////////////////////////////////////////////////////
98// test: ((a >> b) >> c) >> d
99 typedef
100 sequence<
101 sequence<
102 sequence<
103 kleene_star<chlit<> >,
104 action<chlit<>, assign_actor>
105 >,
106 chlit<>
107 >,
108 optional<chlit<> >
109 > test_sequence2_t;
110
111 BOOST_STATIC_ASSERT((
112 ::boost::is_same<
113 test_sequence2_t,
114 post_order::result<identity_transform, test_sequence2_t>::type
115 >::value
116 ));
117
118 c = 0;
119 BOOST_TEST(
120 parse(
121 "aabcd",
122 post_order::traverse(
123 identity_transform(),
124 ((*ch_p('a') >> ch_p('b')[assign_a(c)]) >> 'c') >> !ch_p('d')
125 )
126 ).full
127 );
128 BOOST_TEST(c == 'b');
129
130///////////////////////////////////////////////////////////////////////////////
131// test: (a >> (b >> c)) >> d
132 typedef
133 sequence<
134 sequence<
135 kleene_star<chlit<> >,
136 sequence<
137 action<chlit<>, assign_actor>,
138 chlit<>
139 >
140 >,
141 optional<chlit<char> >
142 > test_sequence3_t;
143
144 BOOST_STATIC_ASSERT((
145 ::boost::is_same<
146 test_sequence3_t,
147 post_order::result<identity_transform, test_sequence3_t>::type
148 >::value
149 ));
150
151 c = 0;
152 BOOST_TEST(
153 parse(
154 "aabcd",
155 post_order::traverse(
156 identity_transform(),
157 (*ch_p('a') >> (ch_p('b')[assign_a(c)] >> 'c')) >> !ch_p('d')
158 )
159 ).full
160 );
161 BOOST_TEST(c == 'b');
162
163///////////////////////////////////////////////////////////////////////////////
164// test: a >> (b >> (c >> d))
165 typedef
166 sequence<
167 kleene_star<chlit<> >,
168 sequence<
169 action<chlit<>, assign_actor>,
170 sequence<
171 chlit<>,
172 optional<chlit<> >
173 >
174 >
175 > test_sequence4_t;
176
177 BOOST_STATIC_ASSERT((
178 ::boost::is_same<
179 test_sequence4_t,
180 post_order::result<identity_transform, test_sequence4_t>::type
181 >::value
182 ));
183
184 c = 0;
185 BOOST_TEST(
186 parse(
187 "aabcd",
188 post_order::traverse(
189 identity_transform(),
190 *ch_p('a') >> (ch_p('b')[assign_a(c)] >> ('c' >> !ch_p('d')))
191 )
192 ).full
193 );
194 BOOST_TEST(c == 'b');
195
196///////////////////////////////////////////////////////////////////////////////
197// test: a >> ((b >> c) >> d)
198 typedef
199 sequence<
200 kleene_star<chlit<> >,
201 sequence<
202 sequence<
203 action<chlit<>, assign_actor>,
204 chlit<>
205 >,
206 optional<chlit<> >
207 >
208 > test_sequence5_t;
209
210 BOOST_STATIC_ASSERT((
211 ::boost::is_same<
212 test_sequence5_t,
213 post_order::result<identity_transform, test_sequence5_t>::type
214 >::value
215 ));
216
217 c = 0;
218 BOOST_TEST(
219 parse(
220 "aabcd",
221 post_order::traverse(
222 identity_transform(),
223 *ch_p('a') >> ((ch_p('b')[assign_a(c)] >> 'c') >> !ch_p('d'))
224 )
225 ).full
226 );
227 BOOST_TEST(c == 'b');
228
229///////////////////////////////////////////////////////////////////////////////
230// test: (a >> b) >> (c >> d)
231 typedef
232 sequence<
233 sequence<
234 kleene_star<chlit<> >,
235 action<chlit<>, assign_actor>
236 >,
237 sequence<
238 chlit<>,
239 optional<chlit<> >
240 >
241 > test_sequence6_t;
242
243 BOOST_STATIC_ASSERT((
244 ::boost::is_same<
245 test_sequence6_t,
246 post_order::result<identity_transform, test_sequence6_t>::type
247 >::value
248 ));
249
250 c = 0;
251 BOOST_TEST(
252 parse(
253 "aabcd",
254 post_order::traverse(
255 identity_transform(),
256 (*ch_p('a') >> ch_p('b')[assign_a(c)]) >> ('c' >> !ch_p('d'))
257 )
258 ).full
259 );
260 BOOST_TEST(c == 'b');
261}
262
263///////////////////////////////////////////////////////////////////////////////
264//
265// The following is a tracing identity_transform traverse metafunction
266//
267///////////////////////////////////////////////////////////////////////////////
268
269class trace_identity_transform
270: public transform_policies<trace_identity_transform> {
271
272public:
273 typedef trace_identity_transform self_t;
274 typedef transform_policies<trace_identity_transform> base_t;
275
276 template <typename ParserT, typename EnvT>
277 typename parser_traversal_plain_result<self_t, ParserT, EnvT>::type
278 generate_plain(ParserT const &parser_, EnvT const &env) const
279 {
280 OSSTREAM strout;
281 strout
282 << EnvT::node
283 << ": plain ("
284 << EnvT::level << ", "
285 << EnvT::index
286 << "): "
287 << parser_name(parser_);
288 traces.push_back(GETSTRING(strout));
289
290 return this->base_t::generate_plain(parser_, env);
291 }
292
293 template <typename UnaryT, typename SubjectT, typename EnvT>
294 typename parser_traversal_unary_result<self_t, UnaryT, SubjectT, EnvT>::type
295 generate_unary(UnaryT const &unary_, SubjectT const &subject_,
296 EnvT const &env) const
297 {
298 OSSTREAM strout;
299 strout
300 << EnvT::node << ": unary ("
301 << EnvT::level
302 << "): "
303 << parser_name(unary_);
304 traces.push_back(GETSTRING(strout));
305
306 return this->base_t::generate_unary(unary_, subject_, env);
307 }
308
309 template <typename ActionT, typename SubjectT, typename EnvT>
310 typename parser_traversal_action_result<self_t, ActionT, SubjectT, EnvT>::type
311 generate_action(ActionT const &action_, SubjectT const &subject_,
312 EnvT const &env) const
313 {
314 OSSTREAM strout;
315 strout
316 << EnvT::node << ": action("
317 << EnvT::level
318 << "): "
319 << parser_name(action_);
320 traces.push_back(GETSTRING(strout));
321
322 return this->base_t::generate_action(action_, subject_, env);
323 }
324
325 template <typename BinaryT, typename LeftT, typename RightT, typename EnvT>
326 typename parser_traversal_binary_result<self_t, BinaryT, LeftT, RightT, EnvT>::type
327 generate_binary(BinaryT const &binary_, LeftT const& left_,
328 RightT const& right_, EnvT const &env) const
329 {
330 OSSTREAM strout;
331 strout
332 << EnvT::node << ": binary("
333 << EnvT::level
334 << "): "
335 << parser_name(binary_);
336 traces.push_back(GETSTRING(strout));
337
338 return this->base_t::generate_binary(binary_, left_, right_, env);
339 }
340
11fdf7f2 341 std::vector<std::string> const &get_output() const { return traces; }
7c673cae
FG
342
343private:
344 mutable std::vector<std::string> traces;
345};
346
347template <typename ParserT>
348void
349post_order_trace_test(ParserT const &parser_, char const *first[], size_t cnt)
350{
351// traverse
352trace_identity_transform trace_vector;
353
354 post_order::traverse(trace_vector, parser_);
355
356// The following two re-find loops ensure, that both string arrays contain the
357// same entries, only their order may differ. The differences in the trace
358// string order is based on the different parameter evaluation order as it is
359// implemented by different compilers.
360
361// re-find all trace strings in the array of expected strings
362std::vector<std::string>::const_iterator it = trace_vector.get_output().begin();
363std::vector<std::string>::const_iterator end = trace_vector.get_output().end();
364
365 BOOST_TEST(cnt == trace_vector.get_output().size());
366 for (/**/; it != end; ++it)
367 {
368 if (std::find(first, first + cnt, *it) == first + cnt)
11fdf7f2 369 std::cerr << "node in question: " << *it << std::endl;
7c673cae
FG
370
371 BOOST_TEST(std::find(first, first + cnt, *it) != first + cnt);
372 }
373
374// re-find all expected strings in the vector of trace strings
375std::vector<std::string>::const_iterator begin = trace_vector.get_output().begin();
376char const *expected = first[0];
377
92f5a8d4 378 for (size_t i = 0; i < cnt - 1; expected = first[++i])
7c673cae
FG
379 {
380 if (std::find(begin, end, std::string(expected)) == end)
11fdf7f2 381 std::cerr << "node in question: " << expected << std::endl;
7c673cae
FG
382
383 BOOST_TEST(std::find(begin, end, std::string(expected)) != end);
384 }
385}
386
387#if defined(_countof)
388#undef _countof
389#endif
390#define _countof(x) (sizeof(x)/sizeof(x[0]))
391
392void
393traverse_trace_tests()
394{
395const char *test_result1[] = {
396 "0: plain (1, 0): chlit('a')",
397 "1: plain (1, 1): chlit('b')",
398 "2: binary(0): sequence[chlit('a'), chlit('b')]",
399 };
400
401 post_order_trace_test(
402 ch_p('a') >> 'b',
403 test_result1, _countof(test_result1)
404 );
405
406char c = 0;
407
408// test: ((a >> b) >> c) >> d
409const char *test_result2[] = {
410 "0: plain (4, 0): chlit('a')",
411 "1: unary (3): kleene_star[chlit('a')]",
412 "2: plain (4, 1): chlit('b')",
413 "3: action(3): action[chlit('b')]",
414 "4: binary(2): sequence[kleene_star[chlit('a')], action[chlit('b')]]",
415 "5: plain (2, 2): chlit('c')",
416 "6: binary(1): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')]",
417 "7: plain (2, 3): chlit('d')",
418 "8: unary (1): optional[chlit('d')]",
419 "9: binary(0): sequence[sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')], optional[chlit('d')]]",
420 };
421
422 post_order_trace_test(
423 ((*ch_p('a') >> ch_p('b')[assign_a(c)]) >> 'c') >> !ch_p('d'),
424 test_result2, _countof(test_result2)
425 );
426
427// test: (a >> (b >> c)) >> d
428const char *test_result3[] = {
429 "0: plain (3, 0): chlit('a')",
430 "1: unary (2): kleene_star[chlit('a')]",
431 "2: plain (4, 1): chlit('b')",
432 "3: action(3): action[chlit('b')]",
433 "4: plain (3, 2): chlit('c')",
434 "5: binary(2): sequence[action[chlit('b')], chlit('c')]",
435 "6: binary(1): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]]",
436 "7: plain (2, 3): chlit('d')",
437 "8: unary (1): optional[chlit('d')]",
438 "9: binary(0): sequence[sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]], optional[chlit('d')]]",
439 };
440
441 post_order_trace_test(
442 (*ch_p('a') >> (ch_p('b')[assign_a(c)] >> 'c')) >> !ch_p('d'),
443 test_result3, _countof(test_result3)
444 );
445
446// test: a >> (b >> (c >> d))
447const char *test_result4[] = {
448 "0: plain (2, 0): chlit('a')",
449 "1: unary (1): kleene_star[chlit('a')]",
450 "2: plain (3, 1): chlit('b')",
451 "3: action(2): action[chlit('b')]",
452 "4: plain (3, 2): chlit('c')",
453 "5: plain (4, 3): chlit('d')",
454 "6: unary (3): optional[chlit('d')]",
455 "7: binary(2): sequence[chlit('c'), optional[chlit('d')]]",
456 "8: binary(1): sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]",
457 "9: binary(0): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]]",
458 };
459
460 post_order_trace_test(
461 *ch_p('a') >> (ch_p('b')[assign_a(c)] >> ('c' >> !ch_p('d'))),
462 test_result4, _countof(test_result4)
463 );
464
465// test: a >> ((b >> c) >> d)
466const char *test_result5[] = {
467 "0: plain (2, 0): chlit('a')",
468 "1: unary (1): kleene_star[chlit('a')]",
469 "2: plain (4, 1): chlit('b')",
470 "3: action(3): action[chlit('b')]",
471 "4: plain (3, 2): chlit('c')",
472 "5: binary(2): sequence[action[chlit('b')], chlit('c')]",
473 "6: plain (3, 3): chlit('d')",
474 "7: unary (2): optional[chlit('d')]",
475 "8: binary(1): sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]",
476 "9: binary(0): sequence[kleene_star[chlit('a')], sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]]",
477 };
478
479 post_order_trace_test(
480 *ch_p('a') >> ((ch_p('b')[assign_a(c)] >> 'c') >> !ch_p('d')),
481 test_result5, _countof(test_result5)
482 );
483
484// test: (a >> b) >> (c >> d)
485const char *test_result6[] = {
486 "0: plain (3, 0): chlit('a')",
487 "1: unary (2): kleene_star[chlit('a')]",
488 "2: plain (3, 1): chlit('b')",
489 "3: action(2): action[chlit('b')]",
490 "4: binary(1): sequence[kleene_star[chlit('a')], action[chlit('b')]]",
491 "5: plain (2, 2): chlit('c')",
492 "6: plain (3, 3): chlit('d')",
493 "7: unary (2): optional[chlit('d')]",
494 "8: binary(1): sequence[chlit('c'), optional[chlit('d')]]",
495 "9: binary(0): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], sequence[chlit('c'), optional[chlit('d')]]]",
496 };
497
498 post_order_trace_test(
499 (*ch_p('a') >> ch_p('b')[assign_a(c)]) >> ('c' >> !ch_p('d')),
500 test_result6, _countof(test_result6)
501 );
502}
503
504///////////////////////////////////////////////////////////////////////////////
505//
506// Main
507//
508///////////////////////////////////////////////////////////////////////////////
509int
510main()
511{
512 traverse_identity_tests();
513 traverse_trace_tests();
514
515 return boost::report_errors();
516}
517