1 /*=============================================================================
2     Copyright (c) 2004 Stefan Slapeta
3     Copyright (c) 2002-2003 Martin Wille
4     http://spirit.sourceforge.net/
5 
6     Use, modification and distribution is subject to the Boost Software
7     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8     http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 // vi:ts=4:sw=4:et
11 // Tests for BOOST_SPIRIT_CLASSIC_NS::if_p
12 // [28-Dec-2002]
13 ////////////////////////////////////////////////////////////////////////////////
14 #include <iostream>
15 #include <cstring>
16 #include <boost/spirit/include/classic_core.hpp>
17 #include <boost/spirit/include/classic_if.hpp>
18 #include <boost/spirit/include/classic_assign_actor.hpp>
19 #include <boost/ref.hpp>
20 #include "impl/string_length.hpp"
21 
22 namespace local
23 {
24     template <typename T>
25     struct var_wrapper
26         : public ::boost::reference_wrapper<T>
27     {
28         typedef ::boost::reference_wrapper<T> parent;
29 
var_wrapperlocal::var_wrapper30         explicit inline var_wrapper(T& t) : parent(t) {}
31 
operator ()local::var_wrapper32         inline T& operator()() const { return parent::get(); }
33     };
34 
35     template <typename T>
36     inline var_wrapper<T>
var(T & t)37     var(T& t)
38     {
39         return var_wrapper<T>(t);
40     }
41 }
42 
43 typedef ::BOOST_SPIRIT_CLASSIC_NS::rule<> rule_t;
44 typedef ::BOOST_SPIRIT_CLASSIC_NS::rule<BOOST_SPIRIT_CLASSIC_NS::no_actions_scanner<>::type >
45     no_actions_rule_t;
46 
47 unsigned int test_count = 0;
48 unsigned int error_count = 0;
49 
50 unsigned int number_result;
51 static const unsigned int kError = 999;
52 static const bool good = true;
53 static const bool bad = false;
54 
55 rule_t hex_prefix;
56 no_actions_rule_t oct_prefix;
57 rule_t hex_rule, oct_rule, dec_rule;
58 
59 rule_t auto_number_rule;
60 rule_t hex_or_dec_number_rule;
61 
62 void
test_number(char const * s,unsigned int wanted,rule_t const & r)63 test_number(char const *s, unsigned int wanted, rule_t const &r)
64 {
65     using namespace std;
66 
67     ++test_count;
68 
69     number_result = wanted-1;
70     ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(s, s + test_impl::string_length(s), r);
71 
72     bool result = wanted == kError?(m.full?bad:good): (number_result==wanted);
73 
74     if (m.full && (m.length != test_impl::string_length(s)))
75         result = bad;
76 
77 
78     if (result==good)
79         cout << "PASSED";
80     else
81     {
82         ++error_count;
83         cout << "FAILED";
84     }
85 
86     cout << ": \"" << s << "\" ==> ";
87     if (number_result==wanted-1)
88         cout << "<error>";
89     else
90         cout << number_result;
91 
92     cout << "\n";
93 }
94 
95 void
test_enclosed_fail()96 test_enclosed_fail()
97 {
98     using namespace std;
99 
100     using ::BOOST_SPIRIT_CLASSIC_NS::if_p;
101     using ::BOOST_SPIRIT_CLASSIC_NS::str_p;
102     using ::BOOST_SPIRIT_CLASSIC_NS::nothing_p;
103 
104   cout << "\nfail enclosed parser:\n";
105 
106     const char *p = "abc";
107 
108     ::BOOST_SPIRIT_CLASSIC_NS::strlit<const char*> success_p = str_p(p);
109     ::BOOST_SPIRIT_CLASSIC_NS::strlit<const char*> fail_p = str_p("xxx");
110 
111     ::BOOST_SPIRIT_CLASSIC_NS::rule<> r = if_p(success_p)[nothing_p];
112 
113     ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(p, r);
114 
115     if (m.full) {
116         cout << "FAILED: if --> match" << endl;
117         ++error_count;
118     } else {
119         cout << "PASSED: if --> no_match" << endl;
120     }
121 
122     r = if_p(fail_p)[success_p].else_p[nothing_p];
123 
124     m = ::BOOST_SPIRIT_CLASSIC_NS::parse(p, r);
125 
126     if (m.full) {
127         cout << "FAILED: else --> match" << endl;
128         ++error_count;
129     } else {
130         cout << "PASSED: else --> no_match" << endl;
131     }
132 }
133 
134 int
main()135 main()
136 {
137     using namespace std;
138     using ::BOOST_SPIRIT_CLASSIC_NS::if_p;
139     using ::BOOST_SPIRIT_CLASSIC_NS::uint_p;
140     using ::BOOST_SPIRIT_CLASSIC_NS::oct_p;
141     using ::BOOST_SPIRIT_CLASSIC_NS::hex_p;
142     using ::BOOST_SPIRIT_CLASSIC_NS::str_p;
143     using ::BOOST_SPIRIT_CLASSIC_NS::ch_p;
144     using ::BOOST_SPIRIT_CLASSIC_NS::assign_a;
145 
146     cout << "/////////////////////////////////////////////////////////\n";
147     cout << "\n";
148     cout << "          if_p test\n";
149     cout << "\n";
150     cout << "/////////////////////////////////////////////////////////\n";
151     cout << "\n";
152 
153     bool    as_hex;
154 
155 #if qDebug
156     BOOST_SPIRIT_DEBUG_RULE(hex_prefix);
157     BOOST_SPIRIT_DEBUG_RULE(hex_rule);
158     BOOST_SPIRIT_DEBUG_RULE(oct_prefix);
159     BOOST_SPIRIT_DEBUG_RULE(oct_rule);
160     BOOST_SPIRIT_DEBUG_RULE(dec_rule);
161     BOOST_SPIRIT_DEBUG_RULE(auto_number_rule);
162     BOOST_SPIRIT_DEBUG_RULE(hex_or_dec_number_rule);
163 #endif
164 
165     hex_prefix = str_p("0x");
166     oct_prefix = ch_p('0');
167 
168     hex_rule = hex_p[assign_a(number_result)];
169     oct_rule = oct_p[assign_a(number_result)];
170     dec_rule = uint_p[assign_a(number_result)];
171 
172     auto_number_rule =
173         if_p(hex_prefix)
174             [hex_rule]
175         .else_p
176         [
177             if_p(::BOOST_SPIRIT_CLASSIC_NS::eps_p(oct_prefix))
178                 [oct_rule]
179             .else_p
180                 [dec_rule]
181         ];
182 
183     hex_or_dec_number_rule =
184         if_p(local::var(as_hex))[hex_prefix>>hex_rule].else_p[dec_rule];
185 
186     cout << "auto:\n";
187     test_number("",   kError, auto_number_rule);
188     test_number("0",       0, auto_number_rule);
189     test_number("1",       1, auto_number_rule);
190     test_number("00",      0, auto_number_rule);
191     test_number("0x", kError, auto_number_rule);
192     test_number("0x0",     0, auto_number_rule);
193     test_number("0755",  493, auto_number_rule);
194     test_number("0x100", 256, auto_number_rule);
195 
196     cout << "\ndecimal:\n";
197     as_hex = false;
198     test_number("",      kError, hex_or_dec_number_rule);
199     test_number("100",      100, hex_or_dec_number_rule);
200     test_number("0x100", kError, hex_or_dec_number_rule);
201     test_number("0xff",  kError, hex_or_dec_number_rule);
202 
203     cout << "\nhexadecimal:\n";
204     as_hex = true;
205     test_number("",      kError, hex_or_dec_number_rule);
206     test_number("0x100",    256, hex_or_dec_number_rule);
207     test_number("0xff",     255, hex_or_dec_number_rule);
208 
209     //////////////////////////////////
210     // tests for if_p without else-parser
211     cout << "\nno-else:\n";
212     rule_t r = if_p(::BOOST_SPIRIT_CLASSIC_NS::eps_p('0'))[oct_rule];
213 
214     test_number("0", 0, r);
215 
216     ++test_count;
217     ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse("", r);
218     if (!m.hit || !m.full || m.length!=0)
219     {
220         std::cout << "FAILED: \"\" ==> <error>\n";
221         ++error_count;
222     }
223     else
224         std::cout << "PASSED: \"\" ==> <empty match>\n";
225 
226     ++test_count;
227     m = ::BOOST_SPIRIT_CLASSIC_NS::parse("junk", r);
228     if (!m.hit || m.full || m.length!=0)
229     {
230         std::cout << "FAILED: \"junk\" ==> <error>\n";
231         ++error_count;
232     }
233     else
234         std::cout << "PASSED: \"junk\" ==> <empty match>\n";
235 
236     test_enclosed_fail();
237 
238 
239     //////////////////////////////////
240     // report results
241     std::cout << "\n    ";
242     if (error_count==0)
243         cout << "All " << test_count << " if_p-tests passed.\n"
244              << "Test concluded successfully\n";
245     else
246         cout << error_count << " of " << test_count << " if_p-tests failed\n"
247              << "Test failed\n";
248 
249     return error_count!=0;
250 }
251