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 | #ifndef BOOST_SPIRIT_SWITCH_IPP |
---|
10 | #define BOOST_SPIRIT_SWITCH_IPP |
---|
11 | |
---|
12 | #include <boost/mpl/if.hpp> |
---|
13 | #include <boost/type_traits/is_same.hpp> |
---|
14 | #include <boost/static_assert.hpp> |
---|
15 | |
---|
16 | #include <boost/preprocessor/cat.hpp> |
---|
17 | #include <boost/preprocessor/inc.hpp> |
---|
18 | #include <boost/preprocessor/repeat.hpp> |
---|
19 | #include <boost/preprocessor/repeat_from_to.hpp> |
---|
20 | |
---|
21 | #include <boost/spirit/core/parser.hpp> |
---|
22 | #include <boost/spirit/core/primitives/primitives.hpp> |
---|
23 | #include <boost/spirit/core/composite/composite.hpp> |
---|
24 | #include <boost/spirit/meta/as_parser.hpp> |
---|
25 | |
---|
26 | #include <boost/spirit/phoenix/actor.hpp> |
---|
27 | #include <boost/spirit/phoenix/tuples.hpp> |
---|
28 | |
---|
29 | /////////////////////////////////////////////////////////////////////////////// |
---|
30 | namespace boost { namespace spirit { |
---|
31 | |
---|
32 | // forward declaration |
---|
33 | template <int N, typename ParserT, bool IsDefault> struct case_parser; |
---|
34 | |
---|
35 | /////////////////////////////////////////////////////////////////////////////// |
---|
36 | namespace impl { |
---|
37 | |
---|
38 | /////////////////////////////////////////////////////////////////////////////// |
---|
39 | // parse helper functions |
---|
40 | template <typename ParserT, typename ScannerT> |
---|
41 | inline typename parser_result<ParserT, ScannerT>::type |
---|
42 | delegate_parse(ParserT const &p, ScannerT const &scan, |
---|
43 | typename ScannerT::iterator_t const save) |
---|
44 | { |
---|
45 | typedef typename parser_result<ParserT, ScannerT>::type result_t; |
---|
46 | |
---|
47 | result_t result (p.subject().parse(scan)); |
---|
48 | if (!result) |
---|
49 | scan.first = save; |
---|
50 | return result; |
---|
51 | } |
---|
52 | |
---|
53 | /////////////////////////////////////////////////////////////////////////////// |
---|
54 | // General default case handling (no default_p case branch given). |
---|
55 | // First try to match the current parser node (if the condition value is |
---|
56 | // matched) and, if that fails, return a no_match |
---|
57 | template <int N, bool IsDefault, bool HasDefault> |
---|
58 | struct default_delegate_parse { |
---|
59 | |
---|
60 | template < |
---|
61 | typename ParserT, typename DefaultT, |
---|
62 | typename ValueT, typename ScannerT |
---|
63 | > |
---|
64 | static typename parser_result<ParserT, ScannerT>::type |
---|
65 | parse (ValueT const &value, ParserT const &p, DefaultT const &, |
---|
66 | ScannerT const &scan, typename ScannerT::iterator_t const save) |
---|
67 | { |
---|
68 | if (value == N) |
---|
69 | return delegate_parse(p, scan, save); |
---|
70 | return scan.no_match(); |
---|
71 | } |
---|
72 | }; |
---|
73 | |
---|
74 | // The current case parser node is the default parser. |
---|
75 | // Ignore the given case value and try to match the given default parser. |
---|
76 | template <int N, bool HasDefault> |
---|
77 | struct default_delegate_parse<N, true, HasDefault> { |
---|
78 | |
---|
79 | template < |
---|
80 | typename ParserT, typename DefaultT, |
---|
81 | typename ValueT, typename ScannerT |
---|
82 | > |
---|
83 | static typename parser_result<ParserT, ScannerT>::type |
---|
84 | parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d, |
---|
85 | ScannerT const &scan, typename ScannerT::iterator_t const save) |
---|
86 | { |
---|
87 | // Since there is a default_p case branch defined, the corresponding |
---|
88 | // parser shouldn't be the nothing_parser |
---|
89 | BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value)); |
---|
90 | return delegate_parse(d, scan, save); |
---|
91 | } |
---|
92 | }; |
---|
93 | |
---|
94 | // The current case parser node is not the default parser, but there is a |
---|
95 | // default_p branch given inside the switch_p parser. |
---|
96 | // First try to match the current parser node (if the condition value is |
---|
97 | // matched) and, if that fails, match the given default_p parser. |
---|
98 | template <int N> |
---|
99 | struct default_delegate_parse<N, false, true> { |
---|
100 | |
---|
101 | template < |
---|
102 | typename ParserT, typename DefaultT, |
---|
103 | typename ValueT, typename ScannerT |
---|
104 | > |
---|
105 | static typename parser_result<ParserT, ScannerT>::type |
---|
106 | parse (ValueT const &value, ParserT const &p, DefaultT const &d, |
---|
107 | ScannerT const &scan, typename ScannerT::iterator_t const save) |
---|
108 | { |
---|
109 | // Since there is a default_p case branch defined, the corresponding |
---|
110 | // parser shouldn't be the nothing_parser |
---|
111 | BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value)); |
---|
112 | if (value == N) |
---|
113 | return delegate_parse(p, scan, save); |
---|
114 | |
---|
115 | return delegate_parse(d, scan, save); |
---|
116 | } |
---|
117 | }; |
---|
118 | |
---|
119 | /////////////////////////////////////////////////////////////////////////////// |
---|
120 | // Look through the case parser chain to test, if there is a default case |
---|
121 | // branch defined (returned by 'value'). |
---|
122 | template <typename CaseT, bool IsSimple = CaseT::is_simple> |
---|
123 | struct default_case; |
---|
124 | |
---|
125 | //////////////////////////////////////// |
---|
126 | template <typename ResultT, bool IsDefault> |
---|
127 | struct get_default_parser { |
---|
128 | |
---|
129 | template <typename ParserT> |
---|
130 | static ResultT |
---|
131 | get(parser<ParserT> const &p) |
---|
132 | { |
---|
133 | return default_case<typename ParserT::derived_t::left_t>:: |
---|
134 | get(p.derived().left()); |
---|
135 | } |
---|
136 | }; |
---|
137 | |
---|
138 | template <typename ResultT> |
---|
139 | struct get_default_parser<ResultT, true> { |
---|
140 | |
---|
141 | template <typename ParserT> |
---|
142 | static ResultT |
---|
143 | get(parser<ParserT> const &p) { return p.derived().right(); } |
---|
144 | }; |
---|
145 | |
---|
146 | //////////////////////////////////////// |
---|
147 | template <typename CaseT, bool IsSimple> |
---|
148 | struct default_case { |
---|
149 | |
---|
150 | // The 'value' constant is true, if the current case_parser or one of its |
---|
151 | // left siblings is a default_p generated case_parser. |
---|
152 | BOOST_STATIC_CONSTANT(bool, value = |
---|
153 | (CaseT::is_default || default_case<typename CaseT::left_t>::value)); |
---|
154 | |
---|
155 | // The 'is_epsilon' constant is true, if the current case_parser or one of |
---|
156 | // its left siblings is a default_p generated parser with an attached |
---|
157 | // epsilon_p (this is generated by the plain default_p). |
---|
158 | BOOST_STATIC_CONSTANT(bool, is_epsilon = ( |
---|
159 | (CaseT::is_default && CaseT::is_epsilon) || |
---|
160 | default_case<typename CaseT::left_t>::is_epsilon |
---|
161 | )); |
---|
162 | |
---|
163 | // The computed 'type' represents the type of the default case branch |
---|
164 | // parser (if there is one) or nothing_parser (if there isn't any default |
---|
165 | // case branch). |
---|
166 | typedef typename boost::mpl::if_c< |
---|
167 | CaseT::is_default, typename CaseT::right_embed_t, |
---|
168 | typename default_case<typename CaseT::left_t>::type |
---|
169 | >::type type; |
---|
170 | |
---|
171 | // The get function returns the parser attached to the default case branch |
---|
172 | // (if there is one) or an instance of a nothing_parser (if there isn't |
---|
173 | // any default case branch). |
---|
174 | template <typename ParserT> |
---|
175 | static type |
---|
176 | get(parser<ParserT> const &p) |
---|
177 | { return get_default_parser<type, CaseT::is_default>::get(p); } |
---|
178 | }; |
---|
179 | |
---|
180 | //////////////////////////////////////// |
---|
181 | template <typename ResultT, bool IsDefault> |
---|
182 | struct get_default_parser_simple { |
---|
183 | |
---|
184 | template <typename ParserT> |
---|
185 | static ResultT |
---|
186 | get(parser<ParserT> const &p) { return p.derived(); } |
---|
187 | }; |
---|
188 | |
---|
189 | template <typename ResultT> |
---|
190 | struct get_default_parser_simple<ResultT, false> { |
---|
191 | |
---|
192 | template <typename ParserT> |
---|
193 | static nothing_parser |
---|
194 | get(parser<ParserT> const &) { return nothing_p; } |
---|
195 | }; |
---|
196 | |
---|
197 | //////////////////////////////////////// |
---|
198 | // Specialization of the default_case template for the last (leftmost) element |
---|
199 | // of the case parser chain. |
---|
200 | template <typename CaseT> |
---|
201 | struct default_case<CaseT, true> { |
---|
202 | |
---|
203 | // The 'value' and 'is_epsilon' constant, the 'type' type and the function |
---|
204 | // 'get' are described above. |
---|
205 | |
---|
206 | BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default); |
---|
207 | BOOST_STATIC_CONSTANT(bool, is_epsilon = ( |
---|
208 | CaseT::is_default && CaseT::is_epsilon |
---|
209 | )); |
---|
210 | |
---|
211 | typedef typename boost::mpl::if_c< |
---|
212 | CaseT::is_default, CaseT, nothing_parser |
---|
213 | >::type type; |
---|
214 | |
---|
215 | template <typename ParserT> |
---|
216 | static type |
---|
217 | get(parser<ParserT> const &p) |
---|
218 | { return get_default_parser_simple<type, value>::get(p); } |
---|
219 | }; |
---|
220 | |
---|
221 | /////////////////////////////////////////////////////////////////////////////// |
---|
222 | // The case_chain template calculates recursivly the depth of the left |
---|
223 | // subchain of the given case branch node. |
---|
224 | template <typename CaseT, bool IsSimple = CaseT::is_simple> |
---|
225 | struct case_chain { |
---|
226 | |
---|
227 | BOOST_STATIC_CONSTANT(int, depth = ( |
---|
228 | case_chain<typename CaseT::left_t>::depth + 1 |
---|
229 | )); |
---|
230 | }; |
---|
231 | |
---|
232 | template <typename CaseT> |
---|
233 | struct case_chain<CaseT, true> { |
---|
234 | |
---|
235 | BOOST_STATIC_CONSTANT(int, depth = 0); |
---|
236 | }; |
---|
237 | |
---|
238 | /////////////////////////////////////////////////////////////////////////////// |
---|
239 | // The chain_parser template is used to extract the type and the instance of |
---|
240 | // a left or a right parser, burried arbitrary deep inside the case parser |
---|
241 | // chain. |
---|
242 | template <int Depth, typename CaseT> |
---|
243 | struct chain_parser { |
---|
244 | |
---|
245 | typedef typename CaseT::left_t our_left_t; |
---|
246 | |
---|
247 | typedef typename chain_parser<Depth-1, our_left_t>::left_t left_t; |
---|
248 | typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t; |
---|
249 | |
---|
250 | static left_t |
---|
251 | left(CaseT const &p) |
---|
252 | { return chain_parser<Depth-1, our_left_t>::left(p.left()); } |
---|
253 | |
---|
254 | static right_t |
---|
255 | right(CaseT const &p) |
---|
256 | { return chain_parser<Depth-1, our_left_t>::right(p.left()); } |
---|
257 | }; |
---|
258 | |
---|
259 | template <typename CaseT> |
---|
260 | struct chain_parser<1, CaseT> { |
---|
261 | |
---|
262 | typedef typename CaseT::left_t left_t; |
---|
263 | typedef typename CaseT::right_t right_t; |
---|
264 | |
---|
265 | static left_t left(CaseT const &p) { return p.left(); } |
---|
266 | static right_t right(CaseT const &p) { return p.right(); } |
---|
267 | }; |
---|
268 | |
---|
269 | template <typename CaseT> |
---|
270 | struct chain_parser<0, CaseT>; // shouldn't be instantiated |
---|
271 | |
---|
272 | /////////////////////////////////////////////////////////////////////////////// |
---|
273 | // Type computing meta function for calculating the type of the return value |
---|
274 | // of the used conditional switch expression |
---|
275 | template <typename TargetT, typename ScannerT> |
---|
276 | struct condition_result { |
---|
277 | |
---|
278 | typedef typename TargetT::template result<ScannerT>::type type; |
---|
279 | }; |
---|
280 | |
---|
281 | /////////////////////////////////////////////////////////////////////////////// |
---|
282 | template <typename LeftT, typename RightT, bool IsDefault> |
---|
283 | struct compound_case_parser |
---|
284 | : public binary<LeftT, RightT, |
---|
285 | parser<compound_case_parser<LeftT, RightT, IsDefault> > > |
---|
286 | { |
---|
287 | typedef compound_case_parser<LeftT, RightT, IsDefault> self_t; |
---|
288 | typedef binary_parser_category parser_category_t; |
---|
289 | typedef binary<LeftT, RightT, parser<self_t> > base_t; |
---|
290 | |
---|
291 | BOOST_STATIC_CONSTANT(int, value = RightT::value); |
---|
292 | BOOST_STATIC_CONSTANT(bool, is_default = IsDefault); |
---|
293 | BOOST_STATIC_CONSTANT(bool, is_simple = false); |
---|
294 | BOOST_STATIC_CONSTANT(bool, is_epsilon = ( |
---|
295 | is_default && |
---|
296 | boost::is_same<typename RightT::subject_t, epsilon_parser>::value |
---|
297 | )); |
---|
298 | |
---|
299 | compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs) |
---|
300 | : base_t(lhs.derived(), rhs.derived()) |
---|
301 | {} |
---|
302 | |
---|
303 | template <typename ScannerT> |
---|
304 | struct result |
---|
305 | { |
---|
306 | typedef typename match_result<ScannerT, nil_t>::type type; |
---|
307 | }; |
---|
308 | |
---|
309 | template <typename ScannerT, typename CondT> |
---|
310 | typename parser_result<self_t, ScannerT>::type |
---|
311 | parse(ScannerT const& scan, CondT const &cond) const; |
---|
312 | |
---|
313 | template <int N1, typename ParserT1, bool IsDefault1> |
---|
314 | compound_case_parser< |
---|
315 | self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1 |
---|
316 | > |
---|
317 | operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const |
---|
318 | { |
---|
319 | // If the following compile time assertion fires, you've probably used |
---|
320 | // more than one default_p case inside the switch_p parser construct. |
---|
321 | BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1); |
---|
322 | |
---|
323 | // If this compile time assertion fires, you've probably want to use |
---|
324 | // more case_p/default_p case branches, than possible. |
---|
325 | BOOST_STATIC_ASSERT( |
---|
326 | case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT |
---|
327 | ); |
---|
328 | |
---|
329 | typedef case_parser<N1, ParserT1, IsDefault1> right_t; |
---|
330 | return compound_case_parser<self_t, right_t, IsDefault1>(*this, p); |
---|
331 | } |
---|
332 | }; |
---|
333 | |
---|
334 | /////////////////////////////////////////////////////////////////////////////// |
---|
335 | // The parse_switch::do_ functions dispatch to the correct parser, which is |
---|
336 | // selected through the given conditional switch value. |
---|
337 | template <int Value, int Depth, bool IsDefault> |
---|
338 | struct parse_switch; |
---|
339 | |
---|
340 | /////////////////////////////////////////////////////////////////////////////// |
---|
341 | // |
---|
342 | // The following generates a couple of parse_switch template specializations |
---|
343 | // with an increasing number of handled case branches (for 1..N). |
---|
344 | // |
---|
345 | // template <int Value, bool IsDefault> |
---|
346 | // struct parse_switch<Value, N, IsDefault> { |
---|
347 | // |
---|
348 | // template <typename ParserT, typename ScannerT> |
---|
349 | // static typename parser_result<ParserT, ScannerT>::type |
---|
350 | // do_(ParserT const &p, ScannerT const &scan, long cond_value, |
---|
351 | // typename ScannerT::iterator_t const &save) |
---|
352 | // { |
---|
353 | // typedef ParserT left_t0; |
---|
354 | // typedef typename left_t0::left left_t1; |
---|
355 | // ... |
---|
356 | // |
---|
357 | // switch (cond_value) { |
---|
358 | // case left_tN::value: |
---|
359 | // return delegate_parse(chain_parser< |
---|
360 | // case_chain<ParserT>::depth, ParserT |
---|
361 | // >::left(p), scan, save); |
---|
362 | // ... |
---|
363 | // case left_t1::value: |
---|
364 | // return delegate_parse(chain_parser< |
---|
365 | // 1, left_t1 |
---|
366 | // >::right(p.left()), scan, save); |
---|
367 | // |
---|
368 | // case left_t0::value: |
---|
369 | // default: |
---|
370 | // typedef default_case<ParserT> default_t; |
---|
371 | // typedef default_delegate_parse< |
---|
372 | // Value, IsDefault, default_t::value> |
---|
373 | // default_parse_t; |
---|
374 | // |
---|
375 | // return default_parse_t::parse(cond_value, p.right(), |
---|
376 | // default_t::get(p), scan, save); |
---|
377 | // } |
---|
378 | // } |
---|
379 | // }; |
---|
380 | // |
---|
381 | /////////////////////////////////////////////////////////////////////////////// |
---|
382 | #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _) \ |
---|
383 | typedef typename BOOST_PP_CAT(left_t, N)::left_t \ |
---|
384 | BOOST_PP_CAT(left_t, BOOST_PP_INC(N)); \ |
---|
385 | /**/ |
---|
386 | |
---|
387 | #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _) \ |
---|
388 | case (long)(BOOST_PP_CAT(left_t, N)::value): \ |
---|
389 | return delegate_parse(chain_parser<N, left_t1>::right(p.left()), \ |
---|
390 | scan, save); \ |
---|
391 | /**/ |
---|
392 | |
---|
393 | #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _) \ |
---|
394 | template <int Value, bool IsDefault> \ |
---|
395 | struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> { \ |
---|
396 | \ |
---|
397 | template <typename ParserT, typename ScannerT> \ |
---|
398 | static typename parser_result<ParserT, ScannerT>::type \ |
---|
399 | do_(ParserT const &p, ScannerT const &scan, long cond_value, \ |
---|
400 | typename ScannerT::iterator_t const &save) \ |
---|
401 | { \ |
---|
402 | typedef ParserT left_t0; \ |
---|
403 | BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N), \ |
---|
404 | BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _) \ |
---|
405 | \ |
---|
406 | switch (cond_value) { \ |
---|
407 | case (long)(BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value): \ |
---|
408 | return delegate_parse( \ |
---|
409 | chain_parser< \ |
---|
410 | case_chain<ParserT>::depth, ParserT \ |
---|
411 | >::left(p), scan, save); \ |
---|
412 | \ |
---|
413 | BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N), \ |
---|
414 | BOOST_SPIRIT_PARSE_SWITCH_CASES, _) \ |
---|
415 | \ |
---|
416 | case (long)(left_t0::value): \ |
---|
417 | default: \ |
---|
418 | typedef default_case<ParserT> default_t; \ |
---|
419 | typedef \ |
---|
420 | default_delegate_parse<Value, IsDefault, default_t::value> \ |
---|
421 | default_parse_t; \ |
---|
422 | \ |
---|
423 | return default_parse_t::parse(cond_value, p.right(), \ |
---|
424 | default_t::get(p), scan, save); \ |
---|
425 | } \ |
---|
426 | } \ |
---|
427 | }; \ |
---|
428 | /**/ |
---|
429 | |
---|
430 | BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT), |
---|
431 | BOOST_SPIRIT_PARSE_SWITCHES, _) |
---|
432 | |
---|
433 | #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS |
---|
434 | #undef BOOST_SPIRIT_PARSE_SWITCH_CASES |
---|
435 | #undef BOOST_SPIRIT_PARSE_SWITCHES |
---|
436 | /////////////////////////////////////////////////////////////////////////////// |
---|
437 | |
---|
438 | template <typename LeftT, typename RightT, bool IsDefault> |
---|
439 | template <typename ScannerT, typename CondT> |
---|
440 | inline typename parser_result< |
---|
441 | compound_case_parser<LeftT, RightT, IsDefault>, ScannerT |
---|
442 | >::type |
---|
443 | compound_case_parser<LeftT, RightT, IsDefault>:: |
---|
444 | parse(ScannerT const& scan, CondT const &cond) const |
---|
445 | { |
---|
446 | scan.at_end(); // allow skipper to take effect |
---|
447 | return parse_switch<value, case_chain<self_t>::depth, is_default>:: |
---|
448 | do_(*this, scan, cond(scan), scan.first); |
---|
449 | } |
---|
450 | |
---|
451 | /////////////////////////////////////////////////////////////////////////////// |
---|
452 | // The switch condition is to be evaluated from a parser result value. |
---|
453 | template <typename ParserT> |
---|
454 | struct cond_functor { |
---|
455 | |
---|
456 | typedef cond_functor<ParserT> self_t; |
---|
457 | |
---|
458 | cond_functor(ParserT const &p_) |
---|
459 | : p(p_) |
---|
460 | {} |
---|
461 | |
---|
462 | template <typename ScannerT> |
---|
463 | struct result |
---|
464 | { |
---|
465 | typedef typename parser_result<ParserT, ScannerT>::type::attr_t type; |
---|
466 | }; |
---|
467 | |
---|
468 | template <typename ScannerT> |
---|
469 | typename condition_result<self_t, ScannerT>::type |
---|
470 | operator()(ScannerT const &scan) const |
---|
471 | { |
---|
472 | typedef typename parser_result<ParserT, ScannerT>::type result_t; |
---|
473 | typedef typename result_t::attr_t attr_t; |
---|
474 | |
---|
475 | result_t result(p.parse(scan)); |
---|
476 | return !result ? attr_t() : result.value(); |
---|
477 | } |
---|
478 | |
---|
479 | typename ParserT::embed_t p; |
---|
480 | }; |
---|
481 | |
---|
482 | template <typename ParserT> |
---|
483 | struct make_cond_functor { |
---|
484 | |
---|
485 | typedef as_parser<ParserT> as_parser_t; |
---|
486 | |
---|
487 | static cond_functor<typename as_parser_t::type> |
---|
488 | do_(ParserT const &cond) |
---|
489 | { |
---|
490 | return cond_functor<typename as_parser_t::type>( |
---|
491 | as_parser_t::convert(cond)); |
---|
492 | } |
---|
493 | }; |
---|
494 | |
---|
495 | /////////////////////////////////////////////////////////////////////////////// |
---|
496 | // The switch condition is to be evaluated from a phoenix actor |
---|
497 | template <typename ActorT> |
---|
498 | struct cond_actor { |
---|
499 | |
---|
500 | typedef cond_actor<ActorT> self_t; |
---|
501 | |
---|
502 | cond_actor(ActorT const &actor_) |
---|
503 | : actor(actor_) |
---|
504 | {} |
---|
505 | |
---|
506 | template <typename ScannerT> |
---|
507 | struct result |
---|
508 | { |
---|
509 | typedef typename phoenix::actor_result<ActorT, phoenix::tuple<> >::type |
---|
510 | type; |
---|
511 | }; |
---|
512 | |
---|
513 | template <typename ScannerT> |
---|
514 | typename condition_result<self_t, ScannerT>::type |
---|
515 | operator()(ScannerT const& /*scan*/) const |
---|
516 | { |
---|
517 | return actor(); |
---|
518 | } |
---|
519 | |
---|
520 | ActorT const &actor; |
---|
521 | }; |
---|
522 | |
---|
523 | template <typename ActorT> |
---|
524 | struct make_cond_functor<phoenix::actor<ActorT> > { |
---|
525 | |
---|
526 | static cond_actor<phoenix::actor<ActorT> > |
---|
527 | do_(phoenix::actor<ActorT> const &actor) |
---|
528 | { |
---|
529 | return cond_actor<phoenix::actor<ActorT> >(actor); |
---|
530 | } |
---|
531 | }; |
---|
532 | |
---|
533 | /////////////////////////////////////////////////////////////////////////////// |
---|
534 | // The switch condition is to be taken directly from the input stream |
---|
535 | struct get_next_token_cond { |
---|
536 | |
---|
537 | typedef get_next_token_cond self_t; |
---|
538 | |
---|
539 | template <typename ScannerT> |
---|
540 | struct result |
---|
541 | { |
---|
542 | typedef typename ScannerT::value_t type; |
---|
543 | }; |
---|
544 | |
---|
545 | template <typename ScannerT> |
---|
546 | typename condition_result<self_t, ScannerT>::type |
---|
547 | operator()(ScannerT const &scan) const |
---|
548 | { |
---|
549 | typename ScannerT::value_t val(*scan); |
---|
550 | ++scan.first; |
---|
551 | return val; |
---|
552 | } |
---|
553 | }; |
---|
554 | |
---|
555 | template <> |
---|
556 | struct make_cond_functor<get_next_token_cond> { |
---|
557 | |
---|
558 | static get_next_token_cond |
---|
559 | do_(get_next_token_cond const &cond) |
---|
560 | { |
---|
561 | return cond; |
---|
562 | } |
---|
563 | }; |
---|
564 | |
---|
565 | /////////////////////////////////////////////////////////////////////////////// |
---|
566 | } // namespace impl |
---|
567 | }} // namespace boost::spirit |
---|
568 | |
---|
569 | #endif // BOOST_SPIRIT_SWITCH_IPP |
---|