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