1 /*=============================================================================
2     Phoenix V1.0
3     Copyright (c) 2002-2003 Martin Wille
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 // vi:ts=4:sw=4:et
10 // Tests for BOOST_SPIRIT_CLASSIC_NS::while_p
11 // [28-Dec-2002]
12 ////////////////////////////////////////////////////////////////////////////////
13 #define qDebug 0
14 #include <iostream>
15 #include <cstring>
16 #if qDebug
17 #define BOOST_SPIRIT_DEBUG
18 #endif
19 
20 #include "impl/string_length.hpp"
21 #include <boost/spirit/include/classic_core.hpp>
22 #include <boost/spirit/include/classic_assign_actor.hpp>
23 #include <boost/spirit/include/classic_while.hpp>
24 #include <boost/ref.hpp>
25 
26 namespace local
27 {
28     template <typename T>
29     struct var_wrapper
30         : public ::boost::reference_wrapper<T>
31     {
32         typedef boost::reference_wrapper<T> parent;
33 
var_wrapperlocal::var_wrapper34         explicit inline var_wrapper(T& t) : parent(t) {}
35 
operator ()local::var_wrapper36         inline T& operator()() const { return parent::get(); }
37     };
38 
39     template <typename T>
40     inline var_wrapper<T>
var(T & t)41     var(T& t)
42     {
43         return var_wrapper<T>(t);
44     }
45 }
46 
47 namespace
48 {
49     template <typename T>
50     class add_actor
51     {
52     public:
add_actor(T & ref_)53         explicit add_actor(T &ref_) : ref(ref_) {}
54 
55         template <typename T2>
operator ()(T2 const & val) const56         void operator()(T2 const &val) const
57         { ref += val; }
58 
59     private:
60         T& ref;
61     };
62 
63     template <typename T>
64     inline add_actor<T> const
add(T & ref)65     add(T& ref)
66     {
67         return add_actor<T>(ref);
68     }
69 }
70 
71 typedef BOOST_SPIRIT_CLASSIC_NS::rule<> rule_t;
72 
73 unsigned int test_count = 0;
74 unsigned int error_count = 0;
75 unsigned int iterations_performed;
76 
77 unsigned int number_result;
78 static const unsigned int kError = 999;
79 static const bool good = true;
80 static const bool bad = false;
81 
82 rule_t while_rule;
83 rule_t do_while_rule;
84 
85 void
test_while(char const * s,unsigned int wanted,rule_t const & r,unsigned int iterations_wanted)86 test_while(
87     char const *s,
88     unsigned int wanted,
89     rule_t const &r,
90     unsigned int iterations_wanted)
91 {
92     using namespace std;
93 
94     ++test_count;
95 
96     number_result = 0;
97     iterations_performed = 0;
98 
99     BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = BOOST_SPIRIT_CLASSIC_NS::parse(s, s+ test_impl::string_length(s), r);
100 
101     bool result = wanted == kError?(m.full?bad:good): (number_result==wanted);
102 
103     result &= iterations_performed == iterations_wanted;
104 
105     if (m.full && (m.length != test_impl::string_length(s)))
106         result = bad;
107 
108     if (result==good)
109         cout << "PASSED";
110     else
111     {
112         ++error_count;
113         cout << "FAILED";
114     }
115 
116     cout << ": \"" << s << "\" ==> ";
117     if (!m.full)
118         cout << "<error>";
119     else
120         cout << number_result;
121     cout << "     " << iterations_performed << " of "
122          << iterations_wanted << " iterations\n";
123 }
124 
125 template<typename T>
126 struct inc_actor
127 {
inc_actorinc_actor128     explicit inc_actor(T &t) : var(t) {}
129     template<typename IteratorT>
operator ()inc_actor130     void operator()(IteratorT const &, IteratorT const &) const
131     {
132         ++var;
133     }
134     template<typename U>
operator ()inc_actor135     void operator()(U) const
136     {
137         ++var;
138     }
139     T &var;
140 };
141 
142 template<typename T>
143 inc_actor<T>
inc(T & t)144 inc(T &t)
145 {
146     return inc_actor<T>(t);
147 }
148 
149 int
main()150 main()
151 {
152     using namespace std;
153     using ::BOOST_SPIRIT_CLASSIC_NS::uint_p;
154     using ::BOOST_SPIRIT_CLASSIC_NS::while_p;
155     using ::BOOST_SPIRIT_CLASSIC_NS::do_p;
156     using ::BOOST_SPIRIT_CLASSIC_NS::assign_a;
157 
158 #if qDebug
159     BOOST_SPIRIT_DEBUG_RULE(while_rule);
160     BOOST_SPIRIT_DEBUG_RULE(do_while_rule);
161 #endif
162 
163     while_rule
164         =   uint_p[assign_a(number_result)]
165         >>  while_p('+')
166             [
167                 uint_p[add(number_result)][inc(iterations_performed)]
168             ];
169 
170     do_while_rule
171         =   do_p
172             [
173                 uint_p[add(number_result)][inc(iterations_performed)]
174             ].while_p('+');
175 
176     cout << "/////////////////////////////////////////////////////////\n";
177     cout << "\n";
178     cout << "          while_p test\n";
179     cout << "\n";
180     cout << "/////////////////////////////////////////////////////////\n";
181     cout << "\n";
182 
183     cout << "while_p()[]\n";
184     test_while("",       kError, while_rule, 0);
185     test_while("1",           1, while_rule, 0);
186     test_while("1+1",         2, while_rule, 1);
187     test_while("1+1+12",     14, while_rule, 2);
188     test_while("1+1+x",  kError, while_rule, 1);
189 
190     cout << "do_p[].while_p()\n";
191     test_while("",       kError, do_while_rule, 0);
192     test_while("1",           1, do_while_rule, 1);
193     test_while("1+1",         2, do_while_rule, 2);
194     test_while("1+1+12",     14, do_while_rule, 3);
195     test_while("1+1+x",  kError, do_while_rule, 2);
196 
197     std::cout << "\n    ";
198     if (error_count==0)
199         cout << "All " << test_count << " while_p-tests passed.\n"
200              << "Test concluded successfully\n";
201     else
202         cout << error_count << " of " << test_count << " while_p-tests failed\n"
203              << "Test failed\n";
204 
205     return error_count!=0;
206 }
207