1 /*=============================================================================
2     Copyright (c) 2003 Martin Wille
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 // vi:ts=4:sw=4:et
10 // Tests for spirit::for_p
11 // [13-Jan-2003]
12 ////////////////////////////////////////////////////////////////////////////////
13 #define qDebug 0
14 #include <iostream>
15 #include <cstring>
16 #if qDebug
17 #define SPIRIT_DEBUG
18 #endif
19 #include <string>
20 #include <boost/spirit/include/classic_core.hpp>
21 #include <boost/spirit/include/classic_assign_actor.hpp>
22 #include <boost/spirit/include/classic_for.hpp>
23 #include <boost/ref.hpp>
24 #include "impl/string_length.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 
76 unsigned int iterations_performed;
77 unsigned int iterations_desired;
78 std::string  input_matched;
79 
80 //static const unsigned int kError = 999;
81 static const bool good = true;
82 static const bool bad = false;
83 
84 rule_t for_rule;
85 rule_t for_rule2;
86 
87 void
test_for(char const * s,bool succeed,rule_t const & r,unsigned int iterations_expected)88 test_for
89 (
90     char const *s,
91     bool succeed,
92     rule_t const &r,
93     unsigned int iterations_expected
94 )
95 {
96     using namespace std;
97 
98     ++test_count;
99 
100     iterations_performed = 0;
101 
102     ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(s, s + test_impl::string_length(s), r);
103 
104     bool result = (succeed==m.full)?good:bad;
105 
106     if (m.full && (m.length != test_impl::string_length(s)))
107         result = bad;
108 
109     result &= iterations_expected == iterations_performed;
110 
111     if (result==good)
112         cout << "PASSED";
113     else
114     {
115         ++error_count;
116         cout << "FAILED";
117     }
118 
119     cout << ": \"" << s << "\" ==> ";
120     if (!m.full)
121         cout << "<error>";
122     else
123         cout << '"' << input_matched << '"';
124 
125     cout << "     " << iterations_performed << " of "
126          << iterations_desired << " iterations\n";
127 }
128 
129 namespace
130 {
zero()131     void zero() { iterations_performed = 0; }
132 
133     struct inc
134     {
operator ()__anon5460ecdf0211::inc135         inline void operator()() const { ++iterations_performed; }
136     };
137     struct cmp
138     {
operator ()__anon5460ecdf0211::cmp139         inline bool operator()() const
140         {
141             return iterations_performed<iterations_desired;
142         }
143     };
144 }
145 
146 int
main()147 main()
148 {
149     using namespace std;
150 
151     using BOOST_SPIRIT_CLASSIC_NS::uint_p;
152     using BOOST_SPIRIT_CLASSIC_NS::for_p;
153     using BOOST_SPIRIT_CLASSIC_NS::assign_a;
154 
155 #if qDebug
156     SPIRIT_DEBUG_RULE(for_rule);
157     SPIRIT_DEBUG_RULE(for_rule2);
158 #endif
159 
160     for_rule
161         =   uint_p[assign_a(iterations_desired)] >> ':'
162         >>  for_p(&zero, cmp(), inc())["xy"]
163             [assign_a(input_matched)]
164         ;
165 
166     for_rule2
167         =   for_p(&zero, '.', inc())["xy"]
168             [assign_a(input_matched)]
169         ;
170 
171     cout << "/////////////////////////////////////////////////////////\n";
172     cout << "\n";
173     cout << "          for_p test\n";
174     cout << "\n";
175     cout << "/////////////////////////////////////////////////////////\n";
176     cout << "\n";
177 
178     test_for("3:xyxyxy",    true, for_rule, 3);
179     test_for("3:",         false, for_rule, 0);
180     test_for("3:xyxy",     false, for_rule, 2);
181     test_for("3:xyxyxyxy", false, for_rule, 3);
182 
183     test_for(".xy.xy.xy", true, for_rule2, 3);
184     test_for(".xy.xy.xy.", false, for_rule2, 3);
185 
186     std::cout << "\n    ";
187     if (error_count==0)
188         cout << "All " << test_count << " for_p-tests passed.\n"
189              << "Test concluded successfully\n";
190     else
191         cout << error_count << " of " << test_count << " for_p-tests failed\n"
192              << "Test failed\n";
193 
194     return error_count!=0;
195 }
196 
197