1 /*=============================================================================
2     Copyright (c) 2003 Giovanni Bajo
3     Copyright (c) 2003 Joel de Guzman
4     Copyright (c) 2003 Vaclav Vesely
5     http://spirit.sourceforge.net/
6 
7     Use, modification and distribution is subject to the Boost Software
8     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9     http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
11 #include <boost/detail/lightweight_test.hpp>
12 #include <boost/spirit/include/classic_core.hpp>
13 #include <boost/spirit/include/classic_assign_actor.hpp>
14 
15 using namespace boost;
16 using namespace BOOST_SPIRIT_CLASSIC_NS;
17 
18 ///////////////////////////////////////////////////////////////////////////////
19 //
20 //  bug_001
21 //
22 //  access_node_d[] and access_match_d[] iterator bug
23 //  http://sf.net/mailarchive/forum.php?thread_id=1963157&forum_id=1595
24 //  http://sf.net/mailarchive/forum.php?thread_id=1966224&forum_id=1595
25 //
26 ///////////////////////////////////////////////////////////////////////////////
27 #include <boost/spirit/include/classic_ast.hpp>
28 
29 struct my_action
30 {
31     template <typename TreeT, typename IterT>
operator ()my_action32     void operator()(TreeT& /*t*/, IterT begin, IterT end) const
33     {
34         BOOST_TEST(*begin == '1');
35         BOOST_TEST(*end == '2');
36     }
37 };
38 
bug_001()39 void bug_001()
40 {
41     const char* text = "123";
42 
43     ast_parse(text, text+3, access_node_d[chlit<>('1')][my_action()]);
44     ast_parse(text, text+3, access_match_d[chlit<>('1')][my_action()]);
45 }
46 
47 ///////////////////////////////////////////////////////////////////////////////
48 //
49 //  bug_001
50 //
51 //  mismatch closure return type bug
52 //  http://article.gmane.org/gmane.comp.parsers.spirit.general/3678
53 //
54 ///////////////////////////////////////////////////////////////////////////////
55 #include <boost/spirit/include/classic_attribute.hpp>
56 #include <string>
57 
58 typedef std::string member_type;
59 
60 struct my_closure: closure<my_closure, member_type>
61 {
62     member1 val;
63 };
64 
bug_002()65 void bug_002()
66 {
67     rule<scanner<char const*>, my_closure::context_t> my_rule = real_p;
68     BOOST_TEST(parse("1", my_rule).full);
69 }
70 
71 ///////////////////////////////////////////////////////////////////////////////
72 //
73 //  bug_003
74 //
75 //  impl::detach_clear bug
76 //  http://sourceforge.net/mailarchive/forum.php?thread_id=2008510&forum_id=25901
77 //
78 ///////////////////////////////////////////////////////////////////////////////
79 #include <boost/spirit/include/classic_chset.hpp>
80 
bug_003()81 void bug_003()
82 {
83     chset<> set;
84     set = 'a';
85 }
86 
87 ///////////////////////////////////////////////////////////////////////////////
88 //
89 //  bug_004
90 //
91 //  chset<>::operator~(range<>) bug
92 //  operator&(chset<>, range<>) bug
93 //  operator&(range<>, chset<>) bug
94 //
95 ///////////////////////////////////////////////////////////////////////////////
96 #include <boost/limits.hpp>
97 #include <boost/spirit/include/classic_chset.hpp>
98 
bug_004()99 void bug_004()
100 {
101     const char min = (std::numeric_limits<char>::min)();
102     const char max = (std::numeric_limits<char>::max)();
103 
104     {
105         chset<> set(~range<>(min, max));
106         BOOST_TEST(set.test(min) == false);
107         BOOST_TEST(set.test(min) == false);
108     }
109 
110     {
111         chset<> set(chset<>(anychar_p) & range<>(min, max));
112         BOOST_TEST(set.test(min) == true);
113         BOOST_TEST(set.test(min) == true);
114     }
115 
116     {
117         chset<> set(range<>(min, max) & chset<>(anychar_p));
118         BOOST_TEST(set.test(min) == true);
119         BOOST_TEST(set.test(min) == true);
120     }
121 }
122 
123 ///////////////////////////////////////////////////////////////////////////////
124 //
125 //  bug_005
126 //
127 //  Most trailing space bug
128 //  http://article.gmane.org/gmane.comp.parsers.spirit.general/4029
129 //  JDG: Oct 18, 2005. We shall revert to the previous behavior where
130 //                     Post skips are not allowed. The reason is that
131 //                     there is a valid use case where input is obtained
132 //                     from cin and multi_pass which results in an infinite
133 //                     loop while the post skipper waits for a whitespace.
134 //                     For examples like below, the grammar must explicitly
135 //                     include the post whitespace. One possible way is to
136 //                     place an end_p at the end of the grammar. The end_p
137 //                     will trigger the post-skip.
138 //
139 ///////////////////////////////////////////////////////////////////////////////
140 #include <boost/spirit/include/classic_core.hpp>
141 
142 using namespace boost;
143 using namespace spirit;
144 
bug_005()145 void bug_005()
146 {
147     BOOST_TEST(
148         parse("   aaaaaaaaa     ", *ch_p('a') >> end_p, space_p).full
149     );
150 
151     BOOST_TEST(
152         parse("   aaaaaaaaa     ", lexeme_d[*ch_p('a')] >> end_p, space_p).full
153     );
154 
155 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
156     // not sure why Code Warrior 9.5 does not recognize ch_p(' ') as the
157     // same as space_p (see above) when the inputs are spaces. The
158     // tests below are redundant anyway.
159 #else
160 
161     BOOST_TEST(
162         parse("   aaaaaaaaa     ", *ch_p('a') >> end_p, ch_p(' ')).full
163     );
164 
165     BOOST_TEST(
166         parse("   aaaaaaaaa     ", lexeme_d[*ch_p('a')] >> end_p, ch_p(' ')).full
167     );
168 
169 #endif
170 }
171 
172 ///////////////////////////////////////////////////////////////////////////////
173 //
174 //  bug_006
175 //
176 //  confix bug
177 //
178 ///////////////////////////////////////////////////////////////////////////////
179 #include <boost/limits.hpp>
180 #include <boost/spirit/include/classic_confix.hpp>
181 
bug_006()182 void bug_006()
183 {
184     BOOST_TEST(parse("#some comment", comment_p('#')).full);
185 }
186 
187 ///////////////////////////////////////////////////////////////////////////////
188 //
189 //  bug_007
190 //
191 //  handling of trailing whitespace bug (ast_parse/pt_parse related)
192 //  JDG: Oct 18, 2005. We shall revert to the previous behavior where
193 //                     Post skips are not allowed. The reason is that
194 //                     there is a valid use case where input is obtained
195 //                     from cin and multi_pass which results in an infinite
196 //                     loop while the post skipper waits for a whitespace.
197 //                     For examples like below, the grammar must explicitly
198 //                     include the post whitespace. One possible way is to
199 //                     place an end_p at the end of the grammar. The end_p
200 //                     will trigger the post-skip.
201 //
202 ///////////////////////////////////////////////////////////////////////////////
203 #include <boost/spirit/include/classic_ast.hpp>
204 #include <boost/spirit/include/classic_parse_tree.hpp>
205 
bug_007()206 void bug_007()
207 {
208     BOOST_TEST(parse("test ", str_p("test") >> end_p, space_p).full);
209     BOOST_TEST(pt_parse("test ", str_p("test") >> end_p, space_p).full);
210     BOOST_TEST(ast_parse("test ", str_p("test") >> end_p, space_p).full);
211 }
212 
213 ///////////////////////////////////////////////////////////////////////////////
214 //
215 //  sf_bug_718903
216 //
217 //  see https://sourceforge.net/tracker/index.php
218 //  ?func=detail&aid=718903&group_id=28447&atid=393386
219 //
220 ///////////////////////////////////////////////////////////////////////////////
221 #include <boost/cstdlib.hpp>
222 #include <boost/spirit/include/classic_chset.hpp>
223 
sf_bug_718903()224 void sf_bug_718903()
225 {
226     empty_match_parser<chset<char> >
227         e(epsilon_p(chset_p("abc")));
228 }
229 
230 ///////////////////////////////////////////////////////////////////////////////
231 //
232 //  sf_bug_719322
233 //  range_run bug
234 //
235 //  see http://sourceforge.net/tracker/index.php
236 //  ?func=detail&aid=719322&group_id=28447&atid=393386
237 //
238 ///////////////////////////////////////////////////////////////////////////////
239 #include <boost/spirit/include/classic_basic_chset.hpp>
240 
sf_bug_719322()241 void sf_bug_719322()
242 {
243     basic_chset<int> s;
244     s.set(3, 3);
245     s.set(1, 5);
246     BOOST_TEST(s.test(5));
247 }
248 
249 ///////////////////////////////////////////////////////////////////////////////
250 //
251 //  sf_bug_742038
252 //
253 //  see http://sf.net/tracker/
254 //  ?func=detail&atid=393386&aid=742038&group_id=28447
255 //
256 ///////////////////////////////////////////////////////////////////////////////
257 #include <boost/spirit/include/classic_position_iterator.hpp>
258 #include <boost/spirit/include/classic_file_iterator.hpp>
259 #include <string>
260 #include <fstream>
261 #include <iostream>
262 #include <boost/detail/lightweight_test.hpp>
263 #include <stdio.h>
264 
265 template <typename IterT>
test_assign(IterT b,IterT e)266 void test_assign(IterT b, IterT e)
267 {
268     typedef scanner<IterT> scanner_t;
269 
270 #if     (defined(__GNUC__) && defined(__MINGW32__)) \
271     ||  (defined(__GNUC__) && (__GNUC_MINOR__ < 20))
272 
273 //  There's a bug in g++3.x on MinGW that makes basic_string assert
274 //  when assigning from IterT [f, l) where IterT is a position_iterator.
275 //  This issue is discussed here:
276 //
277 //  http://gcc.gnu.org/ml/libstdc++/2002-03/msg00196.html
278 //
279 //  Aparently, this bug is only present on MinGW. I'm clueless as
280 //  to why this is so. Regressions on linux seem to be OK! :(
281 //
282 //  With, g++3.1, assigning to basic_string from IterT [f, l) is a
283 //  compile error (a g++3.1 bug).
284 //
285 //  In both cases above, we use a vector instead of a string.
286 
287     typedef std::vector<char> store;
288 #else
289     typedef std::string store;
290 #endif
291 
292     store dst;
293     rule<scanner_t> r = (*alpha_p)[assign_a(dst)];
294 
295     parse(b, e, r);
296 
297     store::iterator d = dst.begin();
298 
299     while (b != e)
300     {
301         if (*d != *b)
302         BOOST_TEST(*d == *b);
303         ++b;
304         ++d;
305     }
306 }
307 
sf_bug_742038()308 void sf_bug_742038()
309 {
310     std::string src = "abcdef";
311     const char* tmpfilename = "sf_bug_742038.tmp";
312 
313     test_assign(src.begin(), src.end());
314 
315     position_iterator<std::string::iterator> b(src.begin(), src.end(), "");
316     position_iterator<std::string::iterator> e;
317     test_assign(b, e);
318 
319     {
320         std::fstream f(tmpfilename, std::ios::out);
321         f << src;
322         f.close();
323 
324         file_iterator<> b1(tmpfilename);
325         file_iterator<> e1(b1.make_end());
326         test_assign(b1, e1);
327     }
328 
329     std::remove(tmpfilename);
330 }
331 
332 ///////////////////////////////////////////////////////////////////////////////
333 //
334 //  bug_009
335 //
336 //  limit_d bug
337 //  http://article.gmane.org/gmane.comp.parsers.spirit.devel/1891/
338 //
339 ///////////////////////////////////////////////////////////////////////////////
340 void
bug_009()341 bug_009()
342 {
343     parse(
344         "test"
345       , limit_d(1U, 10U)[uint_p] | str_p("test"));
346 }
347 
348 int
main()349 main()
350 {
351     bug_001();
352     bug_002();
353     bug_003();
354     bug_004();
355     bug_005();
356     bug_006();
357     bug_007();
358     bug_009();
359 
360     sf_bug_718903();
361     sf_bug_719322();
362     sf_bug_742038();
363 
364     return boost::report_errors();
365 }
366