1 /*=============================================================================
2 Copyright (c) 2002-2003 Hartmut Kaiser
3 http://spirit.sourceforge.net/
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 ///////////////////////////////////////////////////////////////////////////////
13 ///////////////////////////////////////////////////////////////////////////////
15 #include <boost/detail/lightweight_test.hpp>
20 #include <boost/config.hpp>
21 #include <boost/static_assert.hpp>
23 #ifdef BOOST_NO_STRINGSTREAM
25 #define OSSTREAM std::ostrstream
26 std::string
GETSTRING(std::ostrstream
& ss
)
29 std::string rval
= ss
.str();
35 #define GETSTRING(ss) ss.str()
36 #define OSSTREAM std::ostringstream
39 #ifndef BOOST_SPIRIT_DEBUG
40 #define BOOST_SPIRIT_DEBUG // needed for parser_name functions
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>
47 using namespace BOOST_SPIRIT_CLASSIC_NS
;
49 typedef ref_value_actor
<char, assign_action
> assign_actor
;
51 ///////////////////////////////////////////////////////////////////////////////
53 // Test identity transformation
55 ///////////////////////////////////////////////////////////////////////////////
57 traverse_identity_tests()
60 typedef sequence
<chlit
<char>, chlit
<char> > test_sequence1_t
;
64 post_order::result
<identity_transform
, test_sequence1_t
>::type
68 // test (rough) runtime equality
72 post_order::traverse(identity_transform(), ch_p('a') >> 'b')
78 post_order::traverse(identity_transform(), ch_p('a') >> 'b')
82 ///////////////////////////////////////////////////////////////////////////
88 ch_p('a') >> 'b' >> 'c'
93 ///////////////////////////////////////////////////////////////////////////////
94 // Test more complex sequences
97 ///////////////////////////////////////////////////////////////////////////////
98 // test: ((a >> b) >> c) >> d
103 kleene_star
<chlit
<> >,
104 action
<chlit
<>, assign_actor
>
111 BOOST_STATIC_ASSERT((
114 post_order::result
<identity_transform
, test_sequence2_t
>::type
122 post_order::traverse(
123 identity_transform(),
124 ((*ch_p('a') >> ch_p('b')[assign_a(c
)]) >> 'c') >> !ch_p('d')
128 BOOST_TEST(c
== 'b');
130 ///////////////////////////////////////////////////////////////////////////////
131 // test: (a >> (b >> c)) >> d
135 kleene_star
<chlit
<> >,
137 action
<chlit
<>, assign_actor
>,
141 optional
<chlit
<char> >
144 BOOST_STATIC_ASSERT((
147 post_order::result
<identity_transform
, test_sequence3_t
>::type
155 post_order::traverse(
156 identity_transform(),
157 (*ch_p('a') >> (ch_p('b')[assign_a(c
)] >> 'c')) >> !ch_p('d')
161 BOOST_TEST(c
== 'b');
163 ///////////////////////////////////////////////////////////////////////////////
164 // test: a >> (b >> (c >> d))
167 kleene_star
<chlit
<> >,
169 action
<chlit
<>, assign_actor
>,
177 BOOST_STATIC_ASSERT((
180 post_order::result
<identity_transform
, test_sequence4_t
>::type
188 post_order::traverse(
189 identity_transform(),
190 *ch_p('a') >> (ch_p('b')[assign_a(c
)] >> ('c' >> !ch_p('d')))
194 BOOST_TEST(c
== 'b');
196 ///////////////////////////////////////////////////////////////////////////////
197 // test: a >> ((b >> c) >> d)
200 kleene_star
<chlit
<> >,
203 action
<chlit
<>, assign_actor
>,
210 BOOST_STATIC_ASSERT((
213 post_order::result
<identity_transform
, test_sequence5_t
>::type
221 post_order::traverse(
222 identity_transform(),
223 *ch_p('a') >> ((ch_p('b')[assign_a(c
)] >> 'c') >> !ch_p('d'))
227 BOOST_TEST(c
== 'b');
229 ///////////////////////////////////////////////////////////////////////////////
230 // test: (a >> b) >> (c >> d)
234 kleene_star
<chlit
<> >,
235 action
<chlit
<>, assign_actor
>
243 BOOST_STATIC_ASSERT((
246 post_order::result
<identity_transform
, test_sequence6_t
>::type
254 post_order::traverse(
255 identity_transform(),
256 (*ch_p('a') >> ch_p('b')[assign_a(c
)]) >> ('c' >> !ch_p('d'))
260 BOOST_TEST(c
== 'b');
263 ///////////////////////////////////////////////////////////////////////////////
265 // The following is a tracing identity_transform traverse metafunction
267 ///////////////////////////////////////////////////////////////////////////////
269 class trace_identity_transform
270 : public transform_policies
<trace_identity_transform
> {
273 typedef trace_identity_transform self_t
;
274 typedef transform_policies
<trace_identity_transform
> base_t
;
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
284 << EnvT::level
<< ", "
287 << parser_name(parser_
);
288 traces
.push_back(GETSTRING(strout
));
290 return this->base_t::generate_plain(parser_
, env
);
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
300 << EnvT::node
<< ": unary ("
303 << parser_name(unary_
);
304 traces
.push_back(GETSTRING(strout
));
306 return this->base_t::generate_unary(unary_
, subject_
, env
);
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
316 << EnvT::node
<< ": action("
319 << parser_name(action_
);
320 traces
.push_back(GETSTRING(strout
));
322 return this->base_t::generate_action(action_
, subject_
, env
);
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
332 << EnvT::node
<< ": binary("
335 << parser_name(binary_
);
336 traces
.push_back(GETSTRING(strout
));
338 return this->base_t::generate_binary(binary_
, left_
, right_
, env
);
341 std::vector
<std::string
> const &get_output() const { return traces
; }
344 mutable std::vector
<std::string
> traces
;
347 template <typename ParserT
>
349 post_order_trace_test(ParserT
const &parser_
, char const *first
[], size_t cnt
)
352 trace_identity_transform trace_vector
;
354 post_order::traverse(trace_vector
, parser_
);
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.
361 // re-find all trace strings in the array of expected strings
362 std::vector
<std::string
>::const_iterator it
= trace_vector
.get_output().begin();
363 std::vector
<std::string
>::const_iterator end
= trace_vector
.get_output().end();
365 BOOST_TEST(cnt
== trace_vector
.get_output().size());
366 for (/**/; it
!= end
; ++it
)
368 if (std::find(first
, first
+ cnt
, *it
) == first
+ cnt
)
369 std::cerr
<< "node in question: " << *it
<< std::endl
;
371 BOOST_TEST(std::find(first
, first
+ cnt
, *it
) != first
+ cnt
);
374 // re-find all expected strings in the vector of trace strings
375 std::vector
<std::string
>::const_iterator begin
= trace_vector
.get_output().begin();
376 char const *expected
= first
[0];
378 for (size_t i
= 0; i
< cnt
; expected
= first
[++i
])
380 if (std::find(begin
, end
, std::string(expected
)) == end
)
381 std::cerr
<< "node in question: " << expected
<< std::endl
;
383 BOOST_TEST(std::find(begin
, end
, std::string(expected
)) != end
);
387 #if defined(_countof)
390 #define _countof(x) (sizeof(x)/sizeof(x[0]))
393 traverse_trace_tests()
395 const 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')]",
401 post_order_trace_test(
403 test_result1
, _countof(test_result1
)
408 // test: ((a >> b) >> c) >> d
409 const 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')]]",
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
)
427 // test: (a >> (b >> c)) >> d
428 const 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')]]",
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
)
446 // test: a >> (b >> (c >> d))
447 const 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')]]]]",
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
)
465 // test: a >> ((b >> c) >> d)
466 const 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')]]]",
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
)
484 // test: (a >> b) >> (c >> d)
485 const 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')]]]",
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
)
504 ///////////////////////////////////////////////////////////////////////////////
508 ///////////////////////////////////////////////////////////////////////////////
512 traverse_identity_tests();
513 traverse_trace_tests();
515 return boost::report_errors();