]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/support/terminal.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / support / terminal.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 Thomas Heller
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8==============================================================================*/
9#if !defined(BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM)
10#define BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/config.hpp>
17#include <boost/spirit/include/phoenix_core.hpp>
18#include <boost/spirit/include/phoenix_function.hpp>
19#include <boost/proto/proto.hpp>
20#include <boost/spirit/home/support/meta_compiler.hpp>
21#include <boost/spirit/home/support/detail/make_vector.hpp>
22#include <boost/spirit/home/support/unused.hpp>
23#include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
24#include <boost/preprocessor/tuple/elem.hpp>
25
26#include <boost/spirit/home/support/terminal_expression.hpp>
27
28namespace boost { namespace spirit
29{
30 template <typename Terminal, typename Args>
31 struct terminal_ex
32 {
33 typedef Terminal terminal_type;
34 typedef Args args_type;
35
36 terminal_ex(Args const& args_)
37 : args(args_) {}
38 terminal_ex(Args const& args_, Terminal const& term_)
39 : args(args_), term(term_) {}
40
41 Args args; // Args is guaranteed to be a fusion::vectorN so you
42 // can use that template for detection and specialization
43 Terminal term;
44 };
45
46 template <typename Terminal, typename Actor, int Arity>
47 struct lazy_terminal
48 {
49 typedef Terminal terminal_type;
50 typedef Actor actor_type;
51 static int const arity = Arity;
52
53 lazy_terminal(Actor const& actor_)
54 : actor(actor_) {}
55 lazy_terminal(Actor const& actor_, Terminal const& term_)
56 : actor(actor_), term(term_) {}
57
58 Actor actor;
59 Terminal term;
60 };
61
62 template <typename Domain, typename Terminal, int Arity, typename Enable = void>
63 struct use_lazy_terminal : mpl::false_ {};
64
65 template <typename Domain, typename Terminal, int Arity, typename Enable = void>
66 struct use_lazy_directive : mpl::false_ {};
67
68 template <typename Terminal>
69 struct terminal;
70
71 template <typename Domain, typename Terminal>
72 struct use_terminal<Domain, terminal<Terminal> >
73 : use_terminal<Domain, Terminal> {};
74
75 template <typename Domain, typename Terminal, int Arity, typename Actor>
76 struct use_terminal<Domain, lazy_terminal<Terminal, Actor, Arity> >
77 : use_lazy_terminal<Domain, Terminal, Arity> {};
78
79 template <typename Domain, typename Terminal, int Arity, typename Actor>
80 struct use_directive<Domain, lazy_terminal<Terminal, Actor, Arity> >
81 : use_lazy_directive<Domain, Terminal, Arity> {};
82
83 template <
84 typename F
85 , typename A0 = unused_type
86 , typename A1 = unused_type
87 , typename A2 = unused_type
88 , typename Unused = unused_type
89 >
90 struct make_lazy;
91
92 template <typename F, typename A0>
93 struct make_lazy<F, A0>
94 {
95 typedef typename
96 proto::terminal<
97 lazy_terminal<
98 typename F::terminal_type
99 , typename phoenix::detail::expression::function_eval<F, A0>::type
100 , 1 // arity
101 >
102 >::type
103 result_type;
104 typedef result_type type;
105
106 result_type
107 operator()(F f, A0 const& _0_) const
108 {
109 typedef typename result_type::proto_child0 child_type;
110 return result_type::make(child_type(
111 phoenix::detail::expression::function_eval<F, A0>::make(f, _0_)
112 , f.proto_base().child0
113 ));
114 }
115 };
116
117 template <typename F, typename A0, typename A1>
118 struct make_lazy<F, A0, A1>
119 {
120 typedef typename
121 proto::terminal<
122 lazy_terminal<
123 typename F::terminal_type
124 , typename phoenix::detail::expression::function_eval<F, A0, A1>::type
125 , 2 // arity
126 >
127 >::type
128 result_type;
129 typedef result_type type;
130
131 result_type
132 operator()(F f, A0 const& _0_, A1 const& _1_) const
133 {
134 typedef typename result_type::proto_child0 child_type;
135 return result_type::make(child_type(
136 phoenix::detail::expression::function_eval<F, A0, A1>::make(f, _0_, _1_)
137 , f.proto_base().child0
138 ));
139 }
140 };
141
142 template <typename F, typename A0, typename A1, typename A2>
143 struct make_lazy<F, A0, A1, A2>
144 {
145 typedef typename
146 proto::terminal<
147 lazy_terminal<
148 typename F::terminal_type
149 , typename phoenix::detail::expression::function_eval<F, A0, A1, A2>::type
150 , 3 // arity
151 >
152 >::type
153 result_type;
154 typedef result_type type;
155
156 result_type
157 operator()(F f, A0 const& _0_, A1 const& _1_, A2 const& _2_) const
158 {
159 typedef typename result_type::proto_child0 child_type;
160 return result_type::make(child_type(
161 phoenix::detail::expression::function_eval<F, A0, A1, A2>::make(f, _0_, _1_, _2_)
162 , f.proto_base().child0
163 ));
164 }
165 };
166
167 namespace detail
168 {
169 // Helper struct for SFINAE purposes
170 template <bool C> struct bool_;
171
172 template <>
173 struct bool_<true> : mpl::bool_<true>
174 {
175 typedef bool_<true>* is_true;
176 };
177
178 template <>
179 struct bool_<false> : mpl::bool_<false>
180 {
181 typedef bool_<false>* is_false;
182 };
183
184 // Metafunction to detect if at least one arg is a Phoenix actor
185 template <
186 typename A0
187 , typename A1 = unused_type
188 , typename A2 = unused_type
189 >
190 struct contains_actor
191 : bool_<
192 phoenix::is_actor<A0>::value
193 || phoenix::is_actor<A1>::value
194 || phoenix::is_actor<A2>::value
195 >
196 {};
197
198 // to_lazy_arg: convert a terminal arg type to the type make_lazy needs
199 template <typename A>
200 struct to_lazy_arg
201 : phoenix::as_actor<A> // wrap A in a Phoenix actor if not already one
202 {};
203
204 template <typename A>
205 struct to_lazy_arg<const A>
206 : to_lazy_arg<A>
207 {};
208
209 template <typename A>
210 struct to_lazy_arg<A &>
211 : to_lazy_arg<A>
212 {};
213
214 template <>
215 struct to_lazy_arg<unused_type>
216 {
217 // unused arg: make_lazy wants unused_type
218 typedef unused_type type;
219 };
220
221 // to_nonlazy_arg: convert a terminal arg type to the type make_vector needs
222 template <typename A>
223 struct to_nonlazy_arg
224 {
225 // identity
226 typedef A type;
227 };
228
229 template <typename A>
230 struct to_nonlazy_arg<const A>
231 : to_nonlazy_arg<A>
232 {};
233
234 template <typename A>
235 struct to_nonlazy_arg<A &>
236 : to_nonlazy_arg<A>
237 {};
238
239 // incomplete type: should not be appeared unused_type in nonlazy arg.
240 template <>
241 struct to_nonlazy_arg<unused_type>;
242 }
243
244 template <typename Terminal>
245 struct terminal
246 : proto::extends<
247 typename proto::terminal<Terminal>::type
248 , terminal<Terminal>
249 >
250 {
251 typedef terminal<Terminal> this_type;
252 typedef Terminal terminal_type;
253
254 typedef proto::extends<
255 typename proto::terminal<Terminal>::type
256 , terminal<Terminal>
257 > base_type;
258
259 terminal() {}
260
261 terminal(Terminal const& t)
262 : base_type(proto::terminal<Terminal>::type::make(t))
263 {}
264
265#if defined(BOOST_MSVC)
266#pragma warning(push)
267// warning C4348: 'boost::spirit::terminal<...>::result_helper': redefinition of default parameter: parameter 3, 4
268#pragma warning(disable: 4348)
269#endif
270
271 template <
272 bool Lazy
273 , typename A0
274 , typename A1 = unused_type
275 , typename A2 = unused_type
276 >
277 struct result_helper;
278
279#if defined(BOOST_MSVC)
280#pragma warning(pop)
281#endif
282
283 template <
284 typename A0
285 >
286 struct result_helper<false, A0>
287 {
288 typedef typename
289 proto::terminal<
290 terminal_ex<
291 Terminal
292 , typename detail::result_of::make_vector<
293 typename detail::to_nonlazy_arg<A0>::type>::type>
294 >::type
295 type;
296 };
297
298 template <
299 typename A0
300 , typename A1
301 >
302 struct result_helper<false, A0, A1>
303 {
304 typedef typename
305 proto::terminal<
306 terminal_ex<
307 Terminal
308 , typename detail::result_of::make_vector<
309 typename detail::to_nonlazy_arg<A0>::type
310 , typename detail::to_nonlazy_arg<A1>::type>::type>
311 >::type
312 type;
313 };
314
315 template <
316 typename A0
317 , typename A1
318 , typename A2
319 >
320 struct result_helper<false, A0, A1, A2>
321 {
322 typedef typename
323 proto::terminal<
324 terminal_ex<
325 Terminal
326 , typename detail::result_of::make_vector<
327 typename detail::to_nonlazy_arg<A0>::type
328 , typename detail::to_nonlazy_arg<A1>::type
329 , typename detail::to_nonlazy_arg<A2>::type>::type>
330 >::type
331 type;
332 };
333
334 template <
335 typename A0
336 , typename A1
337 , typename A2
338 >
339 struct result_helper<true, A0, A1, A2>
340 {
341 typedef typename
342 make_lazy<this_type
343 , typename detail::to_lazy_arg<A0>::type
344 , typename detail::to_lazy_arg<A1>::type
345 , typename detail::to_lazy_arg<A2>::type>::type
346 type;
347 };
348
349 // FIXME: we need to change this to conform to the result_of protocol
350 template <
351 typename A0
352 , typename A1 = unused_type
353 , typename A2 = unused_type // Support up to 3 args
354 >
355 struct result
356 {
357 typedef typename
358 result_helper<
359 detail::contains_actor<A0, A1, A2>::value
360 , A0, A1, A2
361 >::type
362 type;
363 };
364
365 template <typename This, typename A0>
366 struct result<This(A0)>
367 {
368 typedef typename
369 result_helper<
370 detail::contains_actor<A0, unused_type, unused_type>::value
371 , A0, unused_type, unused_type
372 >::type
373 type;
374 };
375
376 template <typename This, typename A0, typename A1>
377 struct result<This(A0, A1)>
378 {
379 typedef typename
380 result_helper<
381 detail::contains_actor<A0, A1, unused_type>::value
382 , A0, A1, unused_type
383 >::type
384 type;
385 };
386
387
388 template <typename This, typename A0, typename A1, typename A2>
389 struct result<This(A0, A1, A2)>
390 {
391 typedef typename
392 result_helper<
393 detail::contains_actor<A0, A1, A2>::value
394 , A0, A1, A2
395 >::type
396 type;
397 };
398
399 // Note: in the following overloads, SFINAE cannot
400 // be done on return type because of gcc bug #24915:
401 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915
402 // Hence an additional, fake argument is used for SFINAE,
403 // using a type which can never be a real argument type.
404
405 // Non-lazy overloads. Only enabled when all
406 // args are immediates (no Phoenix actor).
407
408 template <typename A0>
409 typename result<A0>::type
410 operator()(A0 const& _0_
411 , typename detail::contains_actor<A0>::is_false = 0) const
412 {
413 typedef typename result<A0>::type result_type;
414 typedef typename result_type::proto_child0 child_type;
415 return result_type::make(
416 child_type(
417 detail::make_vector(_0_)
418 , this->proto_base().child0)
419 );
420 }
421
422 template <typename A0, typename A1>
423 typename result<A0, A1>::type
424 operator()(A0 const& _0_, A1 const& _1_
425 , typename detail::contains_actor<A0, A1>::is_false = 0) const
426 {
427 typedef typename result<A0, A1>::type result_type;
428 typedef typename result_type::proto_child0 child_type;
429 return result_type::make(
430 child_type(
431 detail::make_vector(_0_, _1_)
432 , this->proto_base().child0)
433 );
434 }
435
436 template <typename A0, typename A1, typename A2>
437 typename result<A0, A1, A2>::type
438 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
439 , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const
440 {
441 typedef typename result<A0, A1, A2>::type result_type;
442 typedef typename result_type::proto_child0 child_type;
443 return result_type::make(
444 child_type(
445 detail::make_vector(_0_, _1_, _2_)
446 , this->proto_base().child0)
447 );
448 }
449
450 // Lazy overloads. Enabled when at
451 // least one arg is a Phoenix actor.
452 template <typename A0>
453 typename result<A0>::type
454 operator()(A0 const& _0_
455 , typename detail::contains_actor<A0>::is_true = 0) const
456 {
457 return make_lazy<this_type
458 , typename phoenix::as_actor<A0>::type>()(*this
459 , phoenix::as_actor<A0>::convert(_0_));
460 }
461
462 template <typename A0, typename A1>
463 typename result<A0, A1>::type
464 operator()(A0 const& _0_, A1 const& _1_
465 , typename detail::contains_actor<A0, A1>::is_true = 0) const
466 {
467 return make_lazy<this_type
468 , typename phoenix::as_actor<A0>::type
469 , typename phoenix::as_actor<A1>::type>()(*this
470 , phoenix::as_actor<A0>::convert(_0_)
471 , phoenix::as_actor<A1>::convert(_1_));
472 }
473
474 template <typename A0, typename A1, typename A2>
475 typename result<A0, A1, A2>::type
476 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
477 , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const
478 {
479 return make_lazy<this_type
480 , typename phoenix::as_actor<A0>::type
481 , typename phoenix::as_actor<A1>::type
482 , typename phoenix::as_actor<A2>::type>()(*this
483 , phoenix::as_actor<A0>::convert(_0_)
484 , phoenix::as_actor<A1>::convert(_1_)
485 , phoenix::as_actor<A2>::convert(_2_));
486 }
487
488 private:
489 // silence MSVC warning C4512: assignment operator could not be generated
490 terminal& operator= (terminal const&);
491 };
492
493 ///////////////////////////////////////////////////////////////////////////
494 namespace result_of
495 {
496 // Calculate the type of the compound terminal if generated by one of
497 // the spirit::terminal::operator() overloads above
498
499 // The terminal type itself is passed through without modification
500 template <typename Tag>
501 struct terminal
502 {
503 typedef spirit::terminal<Tag> type;
504 };
505
506 template <typename Tag, typename A0>
507 struct terminal<Tag(A0)>
508 {
509 typedef typename spirit::terminal<Tag>::
510 template result<A0>::type type;
511 };
512
513 template <typename Tag, typename A0, typename A1>
514 struct terminal<Tag(A0, A1)>
515 {
516 typedef typename spirit::terminal<Tag>::
517 template result<A0, A1>::type type;
518 };
519
520 template <typename Tag, typename A0, typename A1, typename A2>
521 struct terminal<Tag(A0, A1, A2)>
522 {
523 typedef typename spirit::terminal<Tag>::
524 template result<A0, A1, A2>::type type;
525 };
526 }
527
528 ///////////////////////////////////////////////////////////////////////////
529 // support for stateful tag types
530 namespace tag
531 {
532 template <
533 typename Data, typename Tag
534 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
535 struct stateful_tag
536 {
537 BOOST_SPIRIT_IS_TAG()
538
539 typedef Data data_type;
540
541 stateful_tag() {}
542 stateful_tag(data_type const& data) : data_(data) {}
543
544 data_type data_;
545
546 private:
547 // silence MSVC warning C4512: assignment operator could not be generated
548 stateful_tag& operator= (stateful_tag const&);
549 };
550 }
551
552 template <
553 typename Data, typename Tag
554 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
555 struct stateful_tag_type
556 : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> >
557 {
558 typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type;
559
560 stateful_tag_type() {}
561 stateful_tag_type(Data const& data)
562 : spirit::terminal<tag_type>(data)
563 {}
564
565 private:
566 // silence MSVC warning C4512: assignment operator could not be generated
567 stateful_tag_type& operator= (stateful_tag_type const&);
568 };
569
570 namespace detail
571 {
572 // extract expression if this is a Tag
573 template <typename StatefulTag>
574 struct get_stateful_data
575 {
576 typedef typename StatefulTag::data_type data_type;
577
578 // is invoked if given tag is != Tag
579 template <typename Tag_>
580 static data_type call(Tag_) { return data_type(); }
581
582 // this is invoked if given tag is same as'Tag'
583 static data_type const& call(StatefulTag const& t) { return t.data_; }
584 };
585 }
586
587}}
588
589namespace boost { namespace phoenix
590{
591 template <typename Tag>
592 struct is_custom_terminal<Tag, typename Tag::is_spirit_tag>
593 : mpl::true_
594 {};
595
596 template <typename Tag>
597 struct custom_terminal<Tag, typename Tag::is_spirit_tag>
598 {
599#ifndef BOOST_PHOENIX_NO_SPECIALIZE_CUSTOM_TERMINAL
600 typedef void _is_default_custom_terminal; // fix for #7730
601#endif
602
603 typedef spirit::terminal<Tag> result_type;
604
605 template <typename Context>
606 result_type operator()(Tag const & t, Context const &)
607 {
608 return spirit::terminal<Tag>(t);
609 }
610 };
611}}
612
613// Define a spirit terminal. This macro may be placed in any namespace.
614// Common placeholders are placed in the main boost::spirit namespace
615// (see common_terminals.hpp)
616
617#define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y
618#define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X
619#define BOOST_SPIRIT_TERMINAL_X0
620#define BOOST_SPIRIT_TERMINAL_Y0
621
622#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
623
624#define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
625 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
626 typedef boost::proto::terminal<tag::name>::type type_name; \
627 type_name const name = {{}}; \
628 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
629 /***/
630
631#else
632
633#define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
634 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
635 typedef boost::proto::terminal<tag::name>::type type_name; \
636 /***/
637
638#endif
639
640#define BOOST_SPIRIT_TERMINAL(name) \
641 BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \
642 /***/
643
644#define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \
645 BOOST_SPIRIT_TERMINAL_NAME( \
646 BOOST_PP_TUPLE_ELEM(2, 0, names), \
647 BOOST_PP_TUPLE_ELEM(2, 1, names) \
648 ) \
649 /***/
650
651#define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \
652 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \
653 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
654 /***/
655
656// Define a spirit extended terminal. This macro may be placed in any namespace.
657// Common placeholders are placed in the main boost::spirit namespace
658// (see common_terminals.hpp)
659
660#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
661
662#define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
663 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
664 typedef boost::spirit::terminal<tag::name> type_name; \
665 type_name const name = type_name(); \
666 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
667 /***/
668
669#else
670
671#define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
672 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
673 typedef boost::spirit::terminal<tag::name> type_name; \
674 /***/
675
676#endif
677
678#define BOOST_SPIRIT_TERMINAL_EX(name) \
679 BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \
680 /***/
681
682#define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \
683 BOOST_SPIRIT_TERMINAL_NAME_EX( \
684 BOOST_PP_TUPLE_ELEM(2, 0, names), \
685 BOOST_PP_TUPLE_ELEM(2, 1, names) \
686 ) \
687 /***/
688
689#define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \
690 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \
691 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
692 /***/
693
694#endif
695
696