]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2003 Hartmut Kaiser | |
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 | #include <iostream> | |
7c673cae FG |
10 | |
11 | ||
12 | #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6 | |
13 | #define BOOST_SPIRIT_SELECT_LIMIT 6 | |
14 | #define PHOENIX_LIMIT 6 | |
15 | ||
16 | //#define BOOST_SPIRIT_DEBUG | |
17 | #include <boost/mpl/list.hpp> | |
18 | #include <boost/mpl/for_each.hpp> | |
19 | ||
20 | #include <boost/spirit/include/classic_primitives.hpp> | |
21 | #include <boost/spirit/include/classic_numerics.hpp> | |
22 | #include <boost/spirit/include/classic_actions.hpp> | |
23 | #include <boost/spirit/include/classic_operators.hpp> | |
24 | #include <boost/spirit/include/classic_rule.hpp> | |
25 | #include <boost/spirit/include/classic_grammar.hpp> | |
26 | #include <boost/spirit/include/classic_switch.hpp> | |
27 | #include <boost/spirit/include/classic_select.hpp> | |
28 | #include <boost/spirit/include/classic_closure.hpp> | |
29 | ||
1e59de90 TL |
30 | #include <boost/core/lightweight_test.hpp> |
31 | ||
7c673cae FG |
32 | using namespace BOOST_SPIRIT_CLASSIC_NS; |
33 | ||
34 | namespace test_grammars { | |
35 | ||
36 | /////////////////////////////////////////////////////////////////////////////// | |
37 | // Test the direct switch_p usage | |
38 | struct switch_grammar_direct_single | |
39 | : public grammar<switch_grammar_direct_single> | |
40 | { | |
41 | template <typename ScannerT> | |
42 | struct definition | |
43 | { | |
44 | definition(switch_grammar_direct_single const& /*self*/) | |
45 | { | |
46 | r = switch_p [ | |
47 | case_p<'a'>(int_p) | |
48 | ]; | |
49 | } | |
50 | ||
51 | rule<ScannerT> r; | |
52 | rule<ScannerT> const& start() const { return r; } | |
53 | }; | |
54 | }; | |
55 | ||
56 | struct switch_grammar_direct_default_single1 | |
57 | : public grammar<switch_grammar_direct_default_single1> | |
58 | { | |
59 | template <typename ScannerT> | |
60 | struct definition | |
61 | { | |
62 | definition(switch_grammar_direct_default_single1 const& /*self*/) | |
63 | { | |
64 | r = switch_p [ | |
65 | default_p(str_p("default")) | |
66 | ]; | |
67 | } | |
68 | ||
69 | rule<ScannerT> r; | |
70 | rule<ScannerT> const& start() const { return r; } | |
71 | }; | |
72 | }; | |
73 | ||
74 | struct switch_grammar_direct_default_single2 | |
75 | : public grammar<switch_grammar_direct_default_single2> | |
76 | { | |
77 | template <typename ScannerT> | |
78 | struct definition | |
79 | { | |
80 | definition(switch_grammar_direct_default_single2 const& /*self*/) | |
81 | { | |
82 | r = switch_p [ | |
83 | default_p | |
84 | ]; | |
85 | } | |
86 | ||
87 | rule<ScannerT> r; | |
88 | rule<ScannerT> const& start() const { return r; } | |
89 | }; | |
90 | }; | |
91 | ||
92 | /////////////////////////////////////////////////////////////////////////////// | |
93 | // Test the switch_p usage given a parser as the switch condition | |
94 | struct switch_grammar_parser_single | |
95 | : public grammar<switch_grammar_parser_single> | |
96 | { | |
97 | template <typename ScannerT> | |
98 | struct definition | |
99 | { | |
100 | definition(switch_grammar_parser_single const& /*self*/) | |
101 | { | |
102 | r = switch_p(anychar_p) [ | |
103 | case_p<'a'>(int_p) | |
104 | ]; | |
105 | } | |
106 | ||
107 | rule<ScannerT> r; | |
108 | rule<ScannerT> const& start() const { return r; } | |
109 | }; | |
110 | }; | |
111 | ||
112 | struct switch_grammar_parser_default_single1 | |
113 | : public grammar<switch_grammar_parser_default_single1> | |
114 | { | |
115 | template <typename ScannerT> | |
116 | struct definition | |
117 | { | |
118 | definition(switch_grammar_parser_default_single1 const& /*self*/) | |
119 | { | |
120 | r = switch_p(anychar_p) [ | |
121 | default_p(str_p("default")) | |
122 | ]; | |
123 | } | |
124 | ||
125 | rule<ScannerT> r; | |
126 | rule<ScannerT> const& start() const { return r; } | |
127 | }; | |
128 | }; | |
129 | ||
130 | struct switch_grammar_parser_default_single2 | |
131 | : public grammar<switch_grammar_parser_default_single2> | |
132 | { | |
133 | template <typename ScannerT> | |
134 | struct definition | |
135 | { | |
136 | definition(switch_grammar_parser_default_single2 const& /*self*/) | |
137 | { | |
138 | r = switch_p(anychar_p) [ | |
139 | default_p | |
140 | ]; | |
141 | } | |
142 | ||
143 | rule<ScannerT> r; | |
144 | rule<ScannerT> const& start() const { return r; } | |
145 | }; | |
146 | }; | |
147 | ||
148 | /////////////////////////////////////////////////////////////////////////////// | |
149 | // Test the switch_p usage given an actor as the switch condition | |
150 | struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int> | |
151 | { | |
152 | member1 val; | |
153 | }; | |
154 | ||
155 | struct switch_grammar_actor_single | |
156 | : public grammar<switch_grammar_actor_single> | |
157 | { | |
158 | template <typename ScannerT> | |
159 | struct definition | |
160 | { | |
161 | definition(switch_grammar_actor_single const& /*self*/) | |
162 | { | |
163 | using phoenix::arg1; | |
164 | r = select_p('a')[r.val = arg1] >> | |
165 | switch_p(r.val) [ | |
166 | case_p<0>(int_p) | |
167 | ]; | |
168 | } | |
169 | ||
170 | rule<ScannerT, select_result::context_t> r; | |
171 | rule<ScannerT, select_result::context_t> const& | |
172 | start() const { return r; } | |
173 | }; | |
174 | }; | |
175 | ||
176 | struct switch_grammar_actor_default_single1 | |
177 | : public grammar<switch_grammar_actor_default_single1> | |
178 | { | |
179 | template <typename ScannerT> | |
180 | struct definition | |
181 | { | |
182 | definition(switch_grammar_actor_default_single1 const& /*self*/) | |
183 | { | |
184 | using phoenix::arg1; | |
185 | r = select_p('d')[r.val = arg1] >> | |
186 | switch_p(r.val) [ | |
187 | default_p(str_p("default")) | |
188 | ]; | |
189 | } | |
190 | ||
191 | rule<ScannerT, select_result::context_t> r; | |
192 | rule<ScannerT, select_result::context_t> const& | |
193 | start() const { return r; } | |
194 | }; | |
195 | }; | |
196 | ||
197 | struct switch_grammar_actor_default_single2 | |
198 | : public grammar<switch_grammar_actor_default_single2> | |
199 | { | |
200 | template <typename ScannerT> | |
201 | struct definition | |
202 | { | |
203 | definition(switch_grammar_actor_default_single2 const& /*self*/) | |
204 | { | |
205 | using phoenix::arg1; | |
206 | r = select_p('d')[r.val = arg1] >> | |
207 | switch_p(r.val) [ | |
208 | default_p | |
209 | ]; | |
210 | } | |
211 | ||
212 | rule<ScannerT, select_result::context_t> r; | |
213 | rule<ScannerT, select_result::context_t> const& | |
214 | start() const { return r; } | |
215 | }; | |
216 | }; | |
217 | ||
218 | } // namespace test_grammars | |
219 | ||
220 | /////////////////////////////////////////////////////////////////////////////// | |
221 | namespace tests { | |
222 | ||
223 | // Tests for known (to the grammars) sequences | |
224 | struct check_grammar_unknown { | |
225 | ||
226 | template <typename GrammarT> | |
227 | void operator()(GrammarT) | |
228 | { | |
229 | GrammarT g; | |
230 | ||
231 | BOOST_TEST(!parse("a1", g).hit); | |
232 | BOOST_TEST(!parse("a,", g).hit); | |
233 | BOOST_TEST(!parse("abcd", g).hit); | |
234 | ||
235 | BOOST_TEST(!parse("a 1", g, space_p).hit); | |
236 | BOOST_TEST(!parse("a ,", g, space_p).hit); | |
237 | BOOST_TEST(!parse("a bcd", g, space_p).hit); | |
238 | ||
239 | BOOST_TEST(!parse("b1", g).hit); | |
240 | BOOST_TEST(!parse("b,", g).hit); | |
241 | BOOST_TEST(!parse("bbcd", g).hit); | |
242 | ||
243 | BOOST_TEST(!parse("b 1", g, space_p).hit); | |
244 | BOOST_TEST(!parse("b ,", g, space_p).hit); | |
245 | BOOST_TEST(!parse("b bcd", g, space_p).hit); | |
246 | ||
247 | BOOST_TEST(!parse("c1", g).hit); | |
248 | BOOST_TEST(!parse("c,", g).hit); | |
249 | BOOST_TEST(!parse("cbcd", g).hit); | |
250 | ||
251 | BOOST_TEST(!parse("c 1", g, space_p).hit); | |
252 | BOOST_TEST(!parse("c ,", g, space_p).hit); | |
253 | BOOST_TEST(!parse("c bcd", g, space_p).hit); | |
254 | } | |
255 | }; | |
256 | ||
257 | // Tests for the default branches (with parsers) of the grammars | |
258 | struct check_grammar_default { | |
259 | ||
260 | template <typename GrammarT> | |
261 | void operator()(GrammarT) | |
262 | { | |
263 | GrammarT g; | |
264 | ||
265 | BOOST_TEST(parse("ddefault", g).full); | |
266 | BOOST_TEST(parse("d default", g, space_p).full); | |
267 | } | |
268 | }; | |
269 | ||
270 | // Tests for the default branches (without parsers) of the grammars | |
271 | struct check_grammar_default_plain { | |
272 | ||
273 | template <typename GrammarT> | |
274 | void operator()(GrammarT) | |
275 | { | |
276 | GrammarT g; | |
277 | ||
278 | BOOST_TEST(parse("d", g).full); | |
279 | BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to | |
280 | // avoid post skip problems | |
281 | } | |
282 | }; | |
283 | ||
284 | // Tests grammars with a single case_p branch | |
285 | struct check_grammar_single { | |
286 | ||
287 | template <typename GrammarT> | |
288 | void operator()(GrammarT) | |
289 | { | |
290 | GrammarT g; | |
291 | ||
292 | BOOST_TEST(parse("a1", g).full); | |
293 | BOOST_TEST(!parse("a,", g).hit); | |
294 | BOOST_TEST(!parse("abcd", g).hit); | |
295 | ||
296 | BOOST_TEST(parse("a 1", g, space_p).full); | |
297 | BOOST_TEST(!parse("a ,", g, space_p).hit); | |
298 | BOOST_TEST(!parse("a bcd", g, space_p).hit); | |
299 | ||
300 | BOOST_TEST(!parse("b1", g).hit); | |
301 | BOOST_TEST(!parse("b,", g).hit); | |
302 | BOOST_TEST(!parse("bbcd", g).hit); | |
303 | ||
304 | BOOST_TEST(!parse("b 1", g, space_p).hit); | |
305 | BOOST_TEST(!parse("b ,", g, space_p).hit); | |
306 | BOOST_TEST(!parse("b bcd", g, space_p).hit); | |
307 | ||
308 | BOOST_TEST(!parse("c1", g).hit); | |
309 | BOOST_TEST(!parse("c,", g).hit); | |
310 | BOOST_TEST(!parse("cbcd", g).hit); | |
311 | ||
312 | BOOST_TEST(!parse("c 1", g, space_p).hit); | |
313 | BOOST_TEST(!parse("c ,", g, space_p).hit); | |
314 | BOOST_TEST(!parse("c bcd", g, space_p).hit); | |
315 | } | |
316 | }; | |
317 | ||
318 | } // namespace tests | |
319 | ||
320 | int | |
321 | main() | |
322 | { | |
323 | // Test switch_p with a single case_p branch | |
324 | typedef boost::mpl::list< | |
325 | test_grammars::switch_grammar_direct_single, | |
326 | test_grammars::switch_grammar_parser_single, | |
327 | test_grammars::switch_grammar_actor_single | |
328 | > single_list_t; | |
329 | ||
330 | boost::mpl::for_each<single_list_t>(tests::check_grammar_single()); | |
331 | ||
332 | typedef boost::mpl::list< | |
333 | test_grammars::switch_grammar_direct_default_single1, | |
334 | test_grammars::switch_grammar_parser_default_single1, | |
335 | test_grammars::switch_grammar_actor_default_single1 | |
336 | > default_single_t; | |
337 | ||
338 | boost::mpl::for_each<default_single_t>(tests::check_grammar_default()); | |
339 | boost::mpl::for_each<default_single_t>(tests::check_grammar_unknown()); | |
340 | ||
341 | typedef boost::mpl::list< | |
342 | test_grammars::switch_grammar_direct_default_single2, | |
343 | test_grammars::switch_grammar_parser_default_single2, | |
344 | test_grammars::switch_grammar_actor_default_single2 | |
345 | > default_plain_single_t; | |
346 | ||
347 | boost::mpl::for_each<default_plain_single_t>( | |
348 | tests::check_grammar_default_plain()); | |
349 | ||
350 | return boost::report_errors(); | |
351 | } |