Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/spirit/test/traverse_tests.cpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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