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