comparison DEPENDENCIES/generic/include/boost/spirit/home/support/terminal.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
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/spirit/include/phoenix_core.hpp>
17 #include <boost/spirit/include/phoenix_function.hpp>
18 #include <boost/proto/proto.hpp>
19 #include <boost/fusion/include/void.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
28 namespace 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 template <>
240 struct to_nonlazy_arg<unused_type>
241 {
242 // unused arg: make_vector wants fusion::void_
243 typedef fusion::void_ type;
244 };
245 }
246
247 template <typename Terminal>
248 struct terminal
249 : proto::extends<
250 typename proto::terminal<Terminal>::type
251 , terminal<Terminal>
252 >
253 {
254 typedef terminal<Terminal> this_type;
255 typedef Terminal terminal_type;
256
257 typedef proto::extends<
258 typename proto::terminal<Terminal>::type
259 , terminal<Terminal>
260 > base_type;
261
262 terminal() {}
263
264 terminal(Terminal const& t)
265 : base_type(proto::terminal<Terminal>::type::make(t))
266 {}
267
268 template <
269 bool Lazy
270 , typename A0
271 , typename A1
272 , typename A2
273 >
274 struct result_helper;
275
276 template <
277 typename A0
278 , typename A1
279 , typename A2
280 >
281 struct result_helper<false, A0, A1, A2>
282 {
283 typedef typename
284 proto::terminal<
285 terminal_ex<
286 Terminal
287 , typename detail::result_of::make_vector<
288 typename detail::to_nonlazy_arg<A0>::type
289 , typename detail::to_nonlazy_arg<A1>::type
290 , typename detail::to_nonlazy_arg<A2>::type>::type>
291 >::type
292 type;
293 };
294
295 template <
296 typename A0
297 , typename A1
298 , typename A2
299 >
300 struct result_helper<true, A0, A1, A2>
301 {
302 typedef typename
303 make_lazy<this_type
304 , typename detail::to_lazy_arg<A0>::type
305 , typename detail::to_lazy_arg<A1>::type
306 , typename detail::to_lazy_arg<A2>::type>::type
307 type;
308 };
309
310 // FIXME: we need to change this to conform to the result_of protocol
311 template <
312 typename A0
313 , typename A1 = unused_type
314 , typename A2 = unused_type // Support up to 3 args
315 >
316 struct result
317 {
318 typedef typename
319 result_helper<
320 detail::contains_actor<A0, A1, A2>::value
321 , A0, A1, A2
322 >::type
323 type;
324 };
325
326 template <typename This, typename A0>
327 struct result<This(A0)>
328 {
329 typedef typename
330 result_helper<
331 detail::contains_actor<A0, unused_type, unused_type>::value
332 , A0, unused_type, unused_type
333 >::type
334 type;
335 };
336
337 template <typename This, typename A0, typename A1>
338 struct result<This(A0, A1)>
339 {
340 typedef typename
341 result_helper<
342 detail::contains_actor<A0, A1, unused_type>::value
343 , A0, A1, unused_type
344 >::type
345 type;
346 };
347
348
349 template <typename This, typename A0, typename A1, typename A2>
350 struct result<This(A0, A1, A2)>
351 {
352 typedef typename
353 result_helper<
354 detail::contains_actor<A0, A1, A2>::value
355 , A0, A1, A2
356 >::type
357 type;
358 };
359
360 // Note: in the following overloads, SFINAE cannot
361 // be done on return type because of gcc bug #24915:
362 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915
363 // Hence an additional, fake argument is used for SFINAE,
364 // using a type which can never be a real argument type.
365
366 // Non-lazy overloads. Only enabled when all
367 // args are immediates (no Phoenix actor).
368
369 template <typename A0>
370 typename result<A0>::type
371 operator()(A0 const& _0_
372 , typename detail::contains_actor<A0>::is_false = 0) const
373 {
374 typedef typename result<A0>::type result_type;
375 typedef typename result_type::proto_child0 child_type;
376 return result_type::make(
377 child_type(
378 detail::make_vector(_0_)
379 , this->proto_base().child0)
380 );
381 }
382
383 template <typename A0, typename A1>
384 typename result<A0, A1>::type
385 operator()(A0 const& _0_, A1 const& _1_
386 , typename detail::contains_actor<A0, A1>::is_false = 0) const
387 {
388 typedef typename result<A0, A1>::type result_type;
389 typedef typename result_type::proto_child0 child_type;
390 return result_type::make(
391 child_type(
392 detail::make_vector(_0_, _1_)
393 , this->proto_base().child0)
394 );
395 }
396
397 template <typename A0, typename A1, typename A2>
398 typename result<A0, A1, A2>::type
399 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
400 , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const
401 {
402 typedef typename result<A0, A1, A2>::type result_type;
403 typedef typename result_type::proto_child0 child_type;
404 return result_type::make(
405 child_type(
406 detail::make_vector(_0_, _1_, _2_)
407 , this->proto_base().child0)
408 );
409 }
410
411 // Lazy overloads. Enabled when at
412 // least one arg is a Phoenix actor.
413 template <typename A0>
414 typename result<A0>::type
415 operator()(A0 const& _0_
416 , typename detail::contains_actor<A0>::is_true = 0) const
417 {
418 return make_lazy<this_type
419 , typename phoenix::as_actor<A0>::type>()(*this
420 , phoenix::as_actor<A0>::convert(_0_));
421 }
422
423 template <typename A0, typename A1>
424 typename result<A0, A1>::type
425 operator()(A0 const& _0_, A1 const& _1_
426 , typename detail::contains_actor<A0, A1>::is_true = 0) const
427 {
428 return make_lazy<this_type
429 , typename phoenix::as_actor<A0>::type
430 , typename phoenix::as_actor<A1>::type>()(*this
431 , phoenix::as_actor<A0>::convert(_0_)
432 , phoenix::as_actor<A1>::convert(_1_));
433 }
434
435 template <typename A0, typename A1, typename A2>
436 typename result<A0, A1, A2>::type
437 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
438 , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const
439 {
440 return make_lazy<this_type
441 , typename phoenix::as_actor<A0>::type
442 , typename phoenix::as_actor<A1>::type
443 , typename phoenix::as_actor<A2>::type>()(*this
444 , phoenix::as_actor<A0>::convert(_0_)
445 , phoenix::as_actor<A1>::convert(_1_)
446 , phoenix::as_actor<A2>::convert(_2_));
447 }
448
449 private:
450 // silence MSVC warning C4512: assignment operator could not be generated
451 terminal& operator= (terminal const&);
452 };
453
454 ///////////////////////////////////////////////////////////////////////////
455 namespace result_of
456 {
457 // Calculate the type of the compound terminal if generated by one of
458 // the spirit::terminal::operator() overloads above
459
460 // The terminal type itself is passed through without modification
461 template <typename Tag>
462 struct terminal
463 {
464 typedef spirit::terminal<Tag> type;
465 };
466
467 template <typename Tag, typename A0>
468 struct terminal<Tag(A0)>
469 {
470 typedef typename spirit::terminal<Tag>::
471 template result<A0>::type type;
472 };
473
474 template <typename Tag, typename A0, typename A1>
475 struct terminal<Tag(A0, A1)>
476 {
477 typedef typename spirit::terminal<Tag>::
478 template result<A0, A1>::type type;
479 };
480
481 template <typename Tag, typename A0, typename A1, typename A2>
482 struct terminal<Tag(A0, A1, A2)>
483 {
484 typedef typename spirit::terminal<Tag>::
485 template result<A0, A1, A2>::type type;
486 };
487 }
488
489 ///////////////////////////////////////////////////////////////////////////
490 // support for stateful tag types
491 namespace tag
492 {
493 template <
494 typename Data, typename Tag
495 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
496 struct stateful_tag
497 {
498 BOOST_SPIRIT_IS_TAG()
499
500 typedef Data data_type;
501
502 stateful_tag() {}
503 stateful_tag(data_type const& data) : data_(data) {}
504
505 data_type data_;
506
507 private:
508 // silence MSVC warning C4512: assignment operator could not be generated
509 stateful_tag& operator= (stateful_tag const&);
510 };
511 }
512
513 template <
514 typename Data, typename Tag
515 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
516 struct stateful_tag_type
517 : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> >
518 {
519 typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type;
520
521 stateful_tag_type() {}
522 stateful_tag_type(Data const& data)
523 : spirit::terminal<tag_type>(data)
524 {}
525
526 private:
527 // silence MSVC warning C4512: assignment operator could not be generated
528 stateful_tag_type& operator= (stateful_tag_type const&);
529 };
530
531 namespace detail
532 {
533 // extract expression if this is a Tag
534 template <typename StatefulTag>
535 struct get_stateful_data
536 {
537 typedef typename StatefulTag::data_type data_type;
538
539 // is invoked if given tag is != Tag
540 template <typename Tag_>
541 static data_type call(Tag_) { return data_type(); }
542
543 // this is invoked if given tag is same as'Tag'
544 static data_type const& call(StatefulTag const& t) { return t.data_; }
545 };
546 }
547
548 }}
549
550 #ifdef BOOST_SPIRIT_USE_PHOENIX_V3
551 namespace boost { namespace phoenix
552 {
553 template <typename Tag>
554 struct is_custom_terminal<Tag, typename Tag::is_spirit_tag>
555 : mpl::true_
556 {};
557
558 template <typename Tag>
559 struct custom_terminal<Tag, typename Tag::is_spirit_tag>
560 {
561 typedef spirit::terminal<Tag> result_type;
562
563 template <typename Context>
564 result_type operator()(Tag const & t, Context const &)
565 {
566 return spirit::terminal<Tag>(t);
567 }
568 };
569 }}
570 #endif
571
572 // Define a spirit terminal. This macro may be placed in any namespace.
573 // Common placeholders are placed in the main boost::spirit namespace
574 // (see common_terminals.hpp)
575
576 #define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y
577 #define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X
578 #define BOOST_SPIRIT_TERMINAL_X0
579 #define BOOST_SPIRIT_TERMINAL_Y0
580
581 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
582
583 #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
584 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
585 typedef boost::proto::terminal<tag::name>::type type_name; \
586 type_name const name = {{}}; \
587 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
588 /***/
589
590 #else
591
592 #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
593 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
594 typedef boost::proto::terminal<tag::name>::type type_name; \
595 /***/
596
597 #endif
598
599 #define BOOST_SPIRIT_TERMINAL(name) \
600 BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \
601 /***/
602
603 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \
604 BOOST_SPIRIT_TERMINAL_NAME( \
605 BOOST_PP_TUPLE_ELEM(2, 0, names), \
606 BOOST_PP_TUPLE_ELEM(2, 1, names) \
607 ) \
608 /***/
609
610 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \
611 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \
612 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
613 /***/
614
615 // Define a spirit extended terminal. This macro may be placed in any namespace.
616 // Common placeholders are placed in the main boost::spirit namespace
617 // (see common_terminals.hpp)
618
619 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
620
621 #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
622 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
623 typedef boost::spirit::terminal<tag::name> type_name; \
624 type_name const name = type_name(); \
625 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
626 /***/
627
628 #else
629
630 #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
631 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
632 typedef boost::spirit::terminal<tag::name> type_name; \
633 /***/
634
635 #endif
636
637 #define BOOST_SPIRIT_TERMINAL_EX(name) \
638 BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \
639 /***/
640
641 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \
642 BOOST_SPIRIT_TERMINAL_NAME_EX( \
643 BOOST_PP_TUPLE_ELEM(2, 0, names), \
644 BOOST_PP_TUPLE_ELEM(2, 1, names) \
645 ) \
646 /***/
647
648 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \
649 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \
650 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
651 /***/
652
653 #endif
654
655