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>
10 #include <boost/detail/lightweight_test.hpp>
11
12
13 #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6
14 #define BOOST_SPIRIT_SELECT_LIMIT 6
15 #define PHOENIX_LIMIT 6
16
17 //#define BOOST_SPIRIT_DEBUG
18 #include <boost/mpl/list.hpp>
19 #include <boost/mpl/for_each.hpp>
20
21 #include <boost/spirit/include/classic_primitives.hpp>
22 #include <boost/spirit/include/classic_numerics.hpp>
23 #include <boost/spirit/include/classic_actions.hpp>
24 #include <boost/spirit/include/classic_operators.hpp>
25 #include <boost/spirit/include/classic_rule.hpp>
26 #include <boost/spirit/include/classic_grammar.hpp>
27 #include <boost/spirit/include/classic_switch.hpp>
28 #include <boost/spirit/include/classic_select.hpp>
29 #include <boost/spirit/include/classic_closure.hpp>
30
31 using namespace BOOST_SPIRIT_CLASSIC_NS;
32
33 namespace test_grammars {
34
35 ///////////////////////////////////////////////////////////////////////////////
36 // Test the direct switch_p usage (with default_p)
37 struct switch_grammar_direct_default4
38 : public grammar<switch_grammar_direct_default4>
39 {
40 template <typename ScannerT>
41 struct definition
42 {
definitiontest_grammars::switch_grammar_direct_default4::definition43 definition(switch_grammar_direct_default4 const& /*self*/)
44 {
45 r = switch_p [(
46 case_p<'a'>(int_p),
47 case_p<'b'>(ch_p(',')),
48 case_p<'c'>(str_p("bcd")),
49 default_p
50 )];
51 }
52
53 rule<ScannerT> r;
starttest_grammars::switch_grammar_direct_default4::definition54 rule<ScannerT> const& start() const { return r; }
55 };
56 };
57
58 struct switch_grammar_direct_default5
59 : public grammar<switch_grammar_direct_default5>
60 {
61 template <typename ScannerT>
62 struct definition
63 {
definitiontest_grammars::switch_grammar_direct_default5::definition64 definition(switch_grammar_direct_default5 const& /*self*/)
65 {
66 r = switch_p [(
67 case_p<'a'>(int_p),
68 case_p<'b'>(ch_p(',')),
69 default_p,
70 case_p<'c'>(str_p("bcd"))
71 )];
72 }
73
74 rule<ScannerT> r;
starttest_grammars::switch_grammar_direct_default5::definition75 rule<ScannerT> const& start() const { return r; }
76 };
77 };
78
79 struct switch_grammar_direct_default6
80 : public grammar<switch_grammar_direct_default6>
81 {
82 template <typename ScannerT>
83 struct definition
84 {
definitiontest_grammars::switch_grammar_direct_default6::definition85 definition(switch_grammar_direct_default6 const& /*self*/)
86 {
87 r = switch_p [(
88 default_p,
89 case_p<'a'>(int_p),
90 case_p<'b'>(ch_p(',')),
91 case_p<'c'>(str_p("bcd"))
92 )];
93 }
94
95 rule<ScannerT> r;
starttest_grammars::switch_grammar_direct_default6::definition96 rule<ScannerT> const& start() const { return r; }
97 };
98 };
99
100 ///////////////////////////////////////////////////////////////////////////////
101 // Test the switch_p usage given a parser as the switch condition
102 struct switch_grammar_parser_default4
103 : public grammar<switch_grammar_parser_default4>
104 {
105 template <typename ScannerT>
106 struct definition
107 {
definitiontest_grammars::switch_grammar_parser_default4::definition108 definition(switch_grammar_parser_default4 const& /*self*/)
109 {
110 r = switch_p(anychar_p) [(
111 case_p<'a'>(int_p),
112 case_p<'b'>(ch_p(',')),
113 case_p<'c'>(str_p("bcd")),
114 default_p
115 )];
116 }
117
118 rule<ScannerT> r;
starttest_grammars::switch_grammar_parser_default4::definition119 rule<ScannerT> const& start() const { return r; }
120 };
121 };
122
123 struct switch_grammar_parser_default5
124 : public grammar<switch_grammar_parser_default5>
125 {
126 template <typename ScannerT>
127 struct definition
128 {
definitiontest_grammars::switch_grammar_parser_default5::definition129 definition(switch_grammar_parser_default5 const& /*self*/)
130 {
131 r = switch_p(anychar_p) [(
132 case_p<'a'>(int_p),
133 case_p<'b'>(ch_p(',')),
134 default_p,
135 case_p<'c'>(str_p("bcd"))
136 )];
137 }
138
139 rule<ScannerT> r;
starttest_grammars::switch_grammar_parser_default5::definition140 rule<ScannerT> const& start() const { return r; }
141 };
142 };
143
144 struct switch_grammar_parser_default6
145 : public grammar<switch_grammar_parser_default6>
146 {
147 template <typename ScannerT>
148 struct definition
149 {
definitiontest_grammars::switch_grammar_parser_default6::definition150 definition(switch_grammar_parser_default6 const& /*self*/)
151 {
152 r = switch_p(anychar_p) [(
153 default_p,
154 case_p<'a'>(int_p),
155 case_p<'b'>(ch_p(',')),
156 case_p<'c'>(str_p("bcd"))
157 )];
158 }
159
160 rule<ScannerT> r;
starttest_grammars::switch_grammar_parser_default6::definition161 rule<ScannerT> const& start() const { return r; }
162 };
163 };
164
165 ///////////////////////////////////////////////////////////////////////////////
166 // Test the switch_p usage given an actor as the switch condition
167 struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int>
168 {
169 member1 val;
170 };
171
172 struct switch_grammar_actor_default4
173 : public grammar<switch_grammar_actor_default4>
174 {
175 template <typename ScannerT>
176 struct definition
177 {
definitiontest_grammars::switch_grammar_actor_default4::definition178 definition(switch_grammar_actor_default4 const& /*self*/)
179 {
180 using phoenix::arg1;
181 r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >>
182 switch_p(r.val) [(
183 case_p<0>(int_p),
184 case_p<1>(ch_p(',')),
185 case_p<2>(str_p("bcd")),
186 default_p
187 )];
188 }
189
190 rule<ScannerT, select_result::context_t> r;
191 rule<ScannerT, select_result::context_t> const&
starttest_grammars::switch_grammar_actor_default4::definition192 start() const { return r; }
193 };
194 };
195
196 struct switch_grammar_actor_default5
197 : public grammar<switch_grammar_actor_default5>
198 {
199 template <typename ScannerT>
200 struct definition
201 {
definitiontest_grammars::switch_grammar_actor_default5::definition202 definition(switch_grammar_actor_default5 const& /*self*/)
203 {
204 using phoenix::arg1;
205 r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >>
206 switch_p(r.val) [(
207 case_p<0>(int_p),
208 case_p<1>(ch_p(',')),
209 default_p,
210 case_p<2>(str_p("bcd"))
211 )];
212 }
213
214 rule<ScannerT, select_result::context_t> r;
215 rule<ScannerT, select_result::context_t> const&
starttest_grammars::switch_grammar_actor_default5::definition216 start() const { return r; }
217 };
218 };
219
220 struct switch_grammar_actor_default6
221 : public grammar<switch_grammar_actor_default6>
222 {
223 template <typename ScannerT>
224 struct definition
225 {
definitiontest_grammars::switch_grammar_actor_default6::definition226 definition(switch_grammar_actor_default6 const& /*self*/)
227 {
228 using phoenix::arg1;
229 r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >>
230 switch_p(r.val) [(
231 default_p,
232 case_p<0>(int_p),
233 case_p<1>(ch_p(',')),
234 case_p<2>(str_p("bcd"))
235 )];
236 }
237
238 rule<ScannerT, select_result::context_t> r;
239 rule<ScannerT, select_result::context_t> const&
starttest_grammars::switch_grammar_actor_default6::definition240 start() const { return r; }
241 };
242 };
243
244 } // namespace test_grammars
245
246 ///////////////////////////////////////////////////////////////////////////////
247 namespace tests {
248
249 // Tests for known (to the grammars) sequences
250 struct check_grammar_known {
251
252 template <typename GrammarT>
operator ()tests::check_grammar_known253 void operator()(GrammarT)
254 {
255 GrammarT g;
256
257 BOOST_TEST(parse("a1", g).full);
258 BOOST_TEST(!parse("a,", g).hit);
259 BOOST_TEST(!parse("abcd", g).hit);
260
261 BOOST_TEST(parse("a 1", g, space_p).full);
262 BOOST_TEST(!parse("a ,", g, space_p).hit);
263 BOOST_TEST(!parse("a bcd", g, space_p).hit);
264
265 BOOST_TEST(!parse("b1", g).hit);
266 BOOST_TEST(parse("b,", g).full);
267 BOOST_TEST(!parse("bbcd", g).hit);
268
269 BOOST_TEST(!parse("b 1", g, space_p).hit);
270 BOOST_TEST(parse("b ,", g, space_p).full);
271 BOOST_TEST(!parse("b bcd", g, space_p).hit);
272
273 BOOST_TEST(!parse("c1", g).hit);
274 BOOST_TEST(!parse("c,", g).hit);
275 BOOST_TEST(parse("cbcd", g).full);
276
277 BOOST_TEST(!parse("c 1", g, space_p).hit);
278 BOOST_TEST(!parse("c ,", g, space_p).hit);
279 BOOST_TEST(parse("c bcd", g, space_p).full);
280 }
281 };
282
283 // Tests for known (to the grammars) sequences
284 // Tests for the default branches (without parsers) of the grammars
285 struct check_grammar_default_plain {
286
287 template <typename GrammarT>
operator ()tests::check_grammar_default_plain288 void operator()(GrammarT)
289 {
290 GrammarT g;
291
292 BOOST_TEST(parse("d", g).full);
293 BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to
294 // avoid post skip problems
295 }
296 };
297
298 } // namespace tests
299
300 int
main()301 main()
302 {
303 // Test switch_p parsers containing special (epsilon) default_p case
304 // branches
305 typedef boost::mpl::list<
306 // switch_p syntax
307 test_grammars::switch_grammar_direct_default4,
308 test_grammars::switch_grammar_direct_default5,
309 test_grammars::switch_grammar_direct_default6,
310
311 // switch_p(parser) syntax
312 test_grammars::switch_grammar_parser_default4,
313 test_grammars::switch_grammar_parser_default5,
314 test_grammars::switch_grammar_parser_default6,
315
316 // switch_p(actor) syntax
317 test_grammars::switch_grammar_actor_default4,
318 test_grammars::switch_grammar_actor_default5,
319 test_grammars::switch_grammar_actor_default6
320 > default_epsilon_list_t;
321
322 boost::mpl::for_each<default_epsilon_list_t>(tests::check_grammar_known());
323 boost::mpl::for_each<default_epsilon_list_t>(
324 tests::check_grammar_default_plain());
325
326 return boost::report_errors();
327 }
328