File indexing completed on 2025-01-18 09:52:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #if !defined(BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM)
0010 #define BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/config.hpp>
0017 #include <boost/spirit/home/support/meta_compiler.hpp>
0018 #include <boost/spirit/home/support/detail/make_vector.hpp>
0019 #include <boost/spirit/home/support/unused.hpp>
0020 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
0021 #include <boost/spirit/home/support/terminal_expression.hpp>
0022 #include <boost/phoenix/core/as_actor.hpp>
0023 #include <boost/phoenix/core/is_actor.hpp>
0024 #include <boost/phoenix/core/terminal_fwd.hpp>
0025 #include <boost/phoenix/core/value.hpp> // includes as_actor specialization
0026 #include <boost/phoenix/function/function.hpp>
0027 #include <boost/preprocessor/tuple/elem.hpp>
0028 #include <boost/proto/extends.hpp>
0029 #include <boost/proto/traits.hpp>
0030
0031 namespace boost { namespace spirit
0032 {
0033 template <typename Terminal, typename Args>
0034 struct terminal_ex
0035 {
0036 typedef Terminal terminal_type;
0037 typedef Args args_type;
0038
0039 terminal_ex(Args const& args_)
0040 : args(args_) {}
0041 terminal_ex(Args const& args_, Terminal const& term_)
0042 : args(args_), term(term_) {}
0043
0044 Args args;
0045
0046 Terminal term;
0047 };
0048
0049 template <typename Terminal, typename Actor, int Arity>
0050 struct lazy_terminal
0051 {
0052 typedef Terminal terminal_type;
0053 typedef Actor actor_type;
0054 static int const arity = Arity;
0055
0056 lazy_terminal(Actor const& actor_)
0057 : actor(actor_) {}
0058 lazy_terminal(Actor const& actor_, Terminal const& term_)
0059 : actor(actor_), term(term_) {}
0060
0061 Actor actor;
0062 Terminal term;
0063 };
0064
0065 template <typename Domain, typename Terminal, int Arity, typename Enable = void>
0066 struct use_lazy_terminal : mpl::false_ {};
0067
0068 template <typename Domain, typename Terminal, int Arity, typename Enable = void>
0069 struct use_lazy_directive : mpl::false_ {};
0070
0071 template <typename Terminal>
0072 struct terminal;
0073
0074 template <typename Domain, typename Terminal>
0075 struct use_terminal<Domain, terminal<Terminal> >
0076 : use_terminal<Domain, Terminal> {};
0077
0078 template <typename Domain, typename Terminal, int Arity, typename Actor>
0079 struct use_terminal<Domain, lazy_terminal<Terminal, Actor, Arity> >
0080 : use_lazy_terminal<Domain, Terminal, Arity> {};
0081
0082 template <typename Domain, typename Terminal, int Arity, typename Actor>
0083 struct use_directive<Domain, lazy_terminal<Terminal, Actor, Arity> >
0084 : use_lazy_directive<Domain, Terminal, Arity> {};
0085
0086 template <
0087 typename F
0088 , typename A0 = unused_type
0089 , typename A1 = unused_type
0090 , typename A2 = unused_type
0091 , typename Unused = unused_type
0092 >
0093 struct make_lazy;
0094
0095 template <typename F, typename A0>
0096 struct make_lazy<F, A0>
0097 {
0098 typedef typename
0099 proto::terminal<
0100 lazy_terminal<
0101 typename F::terminal_type
0102 , typename phoenix::detail::expression::function_eval<F, A0>::type
0103 , 1
0104 >
0105 >::type
0106 result_type;
0107 typedef result_type type;
0108
0109 result_type
0110 operator()(F f, A0 const& _0_) const
0111 {
0112 typedef typename result_type::proto_child0 child_type;
0113 return result_type::make(child_type(
0114 phoenix::detail::expression::function_eval<F, A0>::make(f, _0_)
0115 , f.proto_base().child0
0116 ));
0117 }
0118 };
0119
0120 template <typename F, typename A0, typename A1>
0121 struct make_lazy<F, A0, A1>
0122 {
0123 typedef typename
0124 proto::terminal<
0125 lazy_terminal<
0126 typename F::terminal_type
0127 , typename phoenix::detail::expression::function_eval<F, A0, A1>::type
0128 , 2
0129 >
0130 >::type
0131 result_type;
0132 typedef result_type type;
0133
0134 result_type
0135 operator()(F f, A0 const& _0_, A1 const& _1_) const
0136 {
0137 typedef typename result_type::proto_child0 child_type;
0138 return result_type::make(child_type(
0139 phoenix::detail::expression::function_eval<F, A0, A1>::make(f, _0_, _1_)
0140 , f.proto_base().child0
0141 ));
0142 }
0143 };
0144
0145 template <typename F, typename A0, typename A1, typename A2>
0146 struct make_lazy<F, A0, A1, A2>
0147 {
0148 typedef typename
0149 proto::terminal<
0150 lazy_terminal<
0151 typename F::terminal_type
0152 , typename phoenix::detail::expression::function_eval<F, A0, A1, A2>::type
0153 , 3
0154 >
0155 >::type
0156 result_type;
0157 typedef result_type type;
0158
0159 result_type
0160 operator()(F f, A0 const& _0_, A1 const& _1_, A2 const& _2_) const
0161 {
0162 typedef typename result_type::proto_child0 child_type;
0163 return result_type::make(child_type(
0164 phoenix::detail::expression::function_eval<F, A0, A1, A2>::make(f, _0_, _1_, _2_)
0165 , f.proto_base().child0
0166 ));
0167 }
0168 };
0169
0170 namespace detail
0171 {
0172
0173 template <bool C> struct bool_;
0174
0175 template <>
0176 struct bool_<true> : mpl::bool_<true>
0177 {
0178 typedef bool_<true>* is_true;
0179 };
0180
0181 template <>
0182 struct bool_<false> : mpl::bool_<false>
0183 {
0184 typedef bool_<false>* is_false;
0185 };
0186
0187
0188 template <
0189 typename A0
0190 , typename A1 = unused_type
0191 , typename A2 = unused_type
0192 >
0193 struct contains_actor
0194 : bool_<
0195 phoenix::is_actor<A0>::value
0196 || phoenix::is_actor<A1>::value
0197 || phoenix::is_actor<A2>::value
0198 >
0199 {};
0200
0201
0202 template <typename A>
0203 struct to_lazy_arg
0204 : phoenix::as_actor<A>
0205 {};
0206
0207 template <typename A>
0208 struct to_lazy_arg<const A>
0209 : to_lazy_arg<A>
0210 {};
0211
0212 template <typename A>
0213 struct to_lazy_arg<A &>
0214 : to_lazy_arg<A>
0215 {};
0216
0217 template <>
0218 struct to_lazy_arg<unused_type>
0219 {
0220
0221 typedef unused_type type;
0222 };
0223
0224
0225 template <typename A>
0226 struct to_nonlazy_arg
0227 {
0228
0229 typedef A type;
0230 };
0231
0232 template <typename A>
0233 struct to_nonlazy_arg<const A>
0234 : to_nonlazy_arg<A>
0235 {};
0236
0237 template <typename A>
0238 struct to_nonlazy_arg<A &>
0239 : to_nonlazy_arg<A>
0240 {};
0241
0242
0243 template <>
0244 struct to_nonlazy_arg<unused_type>;
0245 }
0246
0247 template <typename Terminal>
0248 struct terminal
0249 : proto::extends<
0250 typename proto::terminal<Terminal>::type
0251 , terminal<Terminal>
0252 >
0253 {
0254 typedef terminal<Terminal> this_type;
0255 typedef Terminal terminal_type;
0256
0257 typedef proto::extends<
0258 typename proto::terminal<Terminal>::type
0259 , terminal<Terminal>
0260 > base_type;
0261
0262 terminal() {}
0263
0264 terminal(Terminal const& t)
0265 : base_type(proto::terminal<Terminal>::type::make(t))
0266 {}
0267
0268 #if defined(BOOST_MSVC)
0269 #pragma warning(push)
0270
0271 #pragma warning(disable: 4348)
0272 #endif
0273
0274 template <
0275 bool Lazy
0276 , typename A0
0277 , typename A1 = unused_type
0278 , typename A2 = unused_type
0279 >
0280 struct result_helper;
0281
0282 #if defined(BOOST_MSVC)
0283 #pragma warning(pop)
0284 #endif
0285
0286 template <
0287 typename A0
0288 >
0289 struct result_helper<false, A0>
0290 {
0291 typedef typename
0292 proto::terminal<
0293 terminal_ex<
0294 Terminal
0295 , typename detail::result_of::make_vector<
0296 typename detail::to_nonlazy_arg<A0>::type>::type>
0297 >::type
0298 type;
0299 };
0300
0301 template <
0302 typename A0
0303 , typename A1
0304 >
0305 struct result_helper<false, A0, A1>
0306 {
0307 typedef typename
0308 proto::terminal<
0309 terminal_ex<
0310 Terminal
0311 , typename detail::result_of::make_vector<
0312 typename detail::to_nonlazy_arg<A0>::type
0313 , typename detail::to_nonlazy_arg<A1>::type>::type>
0314 >::type
0315 type;
0316 };
0317
0318 template <
0319 typename A0
0320 , typename A1
0321 , typename A2
0322 >
0323 struct result_helper<false, A0, A1, A2>
0324 {
0325 typedef typename
0326 proto::terminal<
0327 terminal_ex<
0328 Terminal
0329 , typename detail::result_of::make_vector<
0330 typename detail::to_nonlazy_arg<A0>::type
0331 , typename detail::to_nonlazy_arg<A1>::type
0332 , typename detail::to_nonlazy_arg<A2>::type>::type>
0333 >::type
0334 type;
0335 };
0336
0337 template <
0338 typename A0
0339 , typename A1
0340 , typename A2
0341 >
0342 struct result_helper<true, A0, A1, A2>
0343 {
0344 typedef typename
0345 make_lazy<this_type
0346 , typename detail::to_lazy_arg<A0>::type
0347 , typename detail::to_lazy_arg<A1>::type
0348 , typename detail::to_lazy_arg<A2>::type>::type
0349 type;
0350 };
0351
0352
0353 template <
0354 typename A0
0355 , typename A1 = unused_type
0356 , typename A2 = unused_type
0357 >
0358 struct result
0359 {
0360 typedef typename
0361 result_helper<
0362 detail::contains_actor<A0, A1, A2>::value
0363 , A0, A1, A2
0364 >::type
0365 type;
0366 };
0367
0368 template <typename This, typename A0>
0369 struct result<This(A0)>
0370 {
0371 typedef typename
0372 result_helper<
0373 detail::contains_actor<A0, unused_type, unused_type>::value
0374 , A0, unused_type, unused_type
0375 >::type
0376 type;
0377 };
0378
0379 template <typename This, typename A0, typename A1>
0380 struct result<This(A0, A1)>
0381 {
0382 typedef typename
0383 result_helper<
0384 detail::contains_actor<A0, A1, unused_type>::value
0385 , A0, A1, unused_type
0386 >::type
0387 type;
0388 };
0389
0390
0391 template <typename This, typename A0, typename A1, typename A2>
0392 struct result<This(A0, A1, A2)>
0393 {
0394 typedef typename
0395 result_helper<
0396 detail::contains_actor<A0, A1, A2>::value
0397 , A0, A1, A2
0398 >::type
0399 type;
0400 };
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 template <typename A0>
0412 typename result<A0>::type
0413 operator()(A0 const& _0_
0414 , typename detail::contains_actor<A0>::is_false = 0) const
0415 {
0416 typedef typename result<A0>::type result_type;
0417 typedef typename result_type::proto_child0 child_type;
0418 return result_type::make(
0419 child_type(
0420 detail::make_vector(_0_)
0421 , this->proto_base().child0)
0422 );
0423 }
0424
0425 template <typename A0, typename A1>
0426 typename result<A0, A1>::type
0427 operator()(A0 const& _0_, A1 const& _1_
0428 , typename detail::contains_actor<A0, A1>::is_false = 0) const
0429 {
0430 typedef typename result<A0, A1>::type result_type;
0431 typedef typename result_type::proto_child0 child_type;
0432 return result_type::make(
0433 child_type(
0434 detail::make_vector(_0_, _1_)
0435 , this->proto_base().child0)
0436 );
0437 }
0438
0439 template <typename A0, typename A1, typename A2>
0440 typename result<A0, A1, A2>::type
0441 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
0442 , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const
0443 {
0444 typedef typename result<A0, A1, A2>::type result_type;
0445 typedef typename result_type::proto_child0 child_type;
0446 return result_type::make(
0447 child_type(
0448 detail::make_vector(_0_, _1_, _2_)
0449 , this->proto_base().child0)
0450 );
0451 }
0452
0453
0454
0455 template <typename A0>
0456 typename result<A0>::type
0457 operator()(A0 const& _0_
0458 , typename detail::contains_actor<A0>::is_true = 0) const
0459 {
0460 return make_lazy<this_type
0461 , typename phoenix::as_actor<A0>::type>()(*this
0462 , phoenix::as_actor<A0>::convert(_0_));
0463 }
0464
0465 template <typename A0, typename A1>
0466 typename result<A0, A1>::type
0467 operator()(A0 const& _0_, A1 const& _1_
0468 , typename detail::contains_actor<A0, A1>::is_true = 0) const
0469 {
0470 return make_lazy<this_type
0471 , typename phoenix::as_actor<A0>::type
0472 , typename phoenix::as_actor<A1>::type>()(*this
0473 , phoenix::as_actor<A0>::convert(_0_)
0474 , phoenix::as_actor<A1>::convert(_1_));
0475 }
0476
0477 template <typename A0, typename A1, typename A2>
0478 typename result<A0, A1, A2>::type
0479 operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
0480 , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const
0481 {
0482 return make_lazy<this_type
0483 , typename phoenix::as_actor<A0>::type
0484 , typename phoenix::as_actor<A1>::type
0485 , typename phoenix::as_actor<A2>::type>()(*this
0486 , phoenix::as_actor<A0>::convert(_0_)
0487 , phoenix::as_actor<A1>::convert(_1_)
0488 , phoenix::as_actor<A2>::convert(_2_));
0489 }
0490 };
0491
0492
0493 namespace result_of
0494 {
0495
0496
0497
0498
0499 template <typename Tag>
0500 struct terminal
0501 {
0502 typedef spirit::terminal<Tag> type;
0503 };
0504
0505 template <typename Tag, typename A0>
0506 struct terminal<Tag(A0)>
0507 {
0508 typedef typename spirit::terminal<Tag>::
0509 template result<A0>::type type;
0510 };
0511
0512 template <typename Tag, typename A0, typename A1>
0513 struct terminal<Tag(A0, A1)>
0514 {
0515 typedef typename spirit::terminal<Tag>::
0516 template result<A0, A1>::type type;
0517 };
0518
0519 template <typename Tag, typename A0, typename A1, typename A2>
0520 struct terminal<Tag(A0, A1, A2)>
0521 {
0522 typedef typename spirit::terminal<Tag>::
0523 template result<A0, A1, A2>::type type;
0524 };
0525 }
0526
0527
0528
0529 namespace tag
0530 {
0531 template <
0532 typename Data, typename Tag
0533 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
0534 struct stateful_tag
0535 {
0536 BOOST_SPIRIT_IS_TAG()
0537
0538 typedef Data data_type;
0539
0540 stateful_tag() {}
0541 stateful_tag(data_type const& data) : data_(data) {}
0542
0543 data_type data_;
0544 };
0545 }
0546
0547 template <
0548 typename Data, typename Tag
0549 , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
0550 struct stateful_tag_type
0551 : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> >
0552 {
0553 typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type;
0554
0555 stateful_tag_type() {}
0556 stateful_tag_type(Data const& data)
0557 : spirit::terminal<tag_type>(data)
0558 {}
0559 };
0560
0561 namespace detail
0562 {
0563
0564 template <typename StatefulTag>
0565 struct get_stateful_data
0566 {
0567 typedef typename StatefulTag::data_type data_type;
0568
0569
0570 template <typename Tag_>
0571 static data_type call(Tag_) { return data_type(); }
0572
0573
0574 static data_type const& call(StatefulTag const& t) { return t.data_; }
0575 };
0576 }
0577
0578 }}
0579
0580 namespace boost { namespace phoenix
0581 {
0582 template <typename Tag>
0583 struct is_custom_terminal<Tag, typename Tag::is_spirit_tag>
0584 : mpl::true_
0585 {};
0586
0587 template <typename Tag>
0588 struct custom_terminal<Tag, typename Tag::is_spirit_tag>
0589 {
0590 #ifndef BOOST_PHOENIX_NO_SPECIALIZE_CUSTOM_TERMINAL
0591 typedef void _is_default_custom_terminal;
0592 #endif
0593
0594 typedef spirit::terminal<Tag> result_type;
0595
0596 template <typename Context>
0597 result_type operator()(Tag const & t, Context const &)
0598 {
0599 return spirit::terminal<Tag>(t);
0600 }
0601 };
0602 }}
0603
0604
0605
0606
0607
0608 #define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y
0609 #define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X
0610 #define BOOST_SPIRIT_TERMINAL_X0
0611 #define BOOST_SPIRIT_TERMINAL_Y0
0612
0613 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0614
0615 #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
0616 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
0617 typedef boost::proto::terminal<tag::name>::type type_name; \
0618 type_name const name = {{}}; \
0619 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
0620
0621
0622 #else
0623
0624 #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
0625 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
0626 typedef boost::proto::terminal<tag::name>::type type_name; \
0627
0628
0629 #endif
0630
0631 #define BOOST_SPIRIT_TERMINAL(name) \
0632 BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \
0633
0634
0635 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \
0636 BOOST_SPIRIT_TERMINAL_NAME( \
0637 BOOST_PP_TUPLE_ELEM(2, 0, names), \
0638 BOOST_PP_TUPLE_ELEM(2, 1, names) \
0639 ) \
0640
0641
0642 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \
0643 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \
0644 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
0645
0646
0647
0648
0649
0650
0651 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0652
0653 #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
0654 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
0655 typedef boost::spirit::terminal<tag::name> type_name; \
0656 type_name const name = type_name(); \
0657 inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
0658
0659
0660 #else
0661
0662 #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
0663 namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
0664 typedef boost::spirit::terminal<tag::name> type_name; \
0665
0666
0667 #endif
0668
0669 #define BOOST_SPIRIT_TERMINAL_EX(name) \
0670 BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \
0671
0672
0673 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \
0674 BOOST_SPIRIT_TERMINAL_NAME_EX( \
0675 BOOST_PP_TUPLE_ELEM(2, 0, names), \
0676 BOOST_PP_TUPLE_ELEM(2, 1, names) \
0677 ) \
0678
0679
0680 #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \
0681 BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \
0682 BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
0683
0684
0685 #endif
0686
0687