Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:47:40

0001 /*==============================================================================
0002     Copyright (c) 2001-2010 Joel de Guzman
0003     Copyright (c) 2010 Thomas Heller
0004 
0005     Distributed under the Boost Software License, Version 1.0. (See accompanying
0006     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 ==============================================================================*/
0008 #ifndef BOOST_PHOENIX_STATEMENT_SWITCH_HPP
0009 #define BOOST_PHOENIX_STATEMENT_SWITCH_HPP
0010 
0011 #include <boost/phoenix/core/limits.hpp>
0012 #include <boost/fusion/iterator/advance.hpp>
0013 #include <boost/phoenix/core/call.hpp>
0014 #include <boost/phoenix/core/expression.hpp>
0015 #include <boost/phoenix/core/meta_grammar.hpp>
0016 #include <boost/phoenix/core/is_nullary.hpp>
0017 #include <boost/phoenix/support/iterate.hpp>
0018 #include <boost/proto/make_expr.hpp>
0019 #include <boost/proto/fusion.hpp>
0020 
0021 #ifdef _MSC_VER
0022 #pragma warning(push)
0023 #pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
0024 #endif
0025 
0026 BOOST_PHOENIX_DEFINE_EXPRESSION(
0027     (boost)(phoenix)(switch_case)
0028   , (proto::terminal<proto::_>)
0029     (meta_grammar)
0030 )
0031 
0032 BOOST_PHOENIX_DEFINE_EXPRESSION(
0033     (boost)(phoenix)(switch_default_case)
0034   , (meta_grammar)
0035 )
0036 
0037 namespace boost { namespace phoenix
0038 {
0039     namespace detail
0040     {
0041         struct switch_case_grammar;
0042         struct switch_case_with_default_grammar;
0043         struct switch_grammar
0044             : proto::or_<
0045                 proto::when<
0046                     detail::switch_case_grammar
0047                   , mpl::false_()
0048                 >
0049               , proto::when<
0050                     detail::switch_case_with_default_grammar
0051                   , mpl::true_()
0052                 >
0053             >
0054         {};
0055     }
0056 
0057     namespace detail
0058     {
0059         struct switch_case_is_nullary
0060             : proto::or_<
0061                 proto::when<
0062                     proto::comma<
0063                         switch_case_is_nullary
0064                       , proto::or_<phoenix::rule::switch_default_case, phoenix::rule::switch_case>
0065                     >
0066                   , mpl::and_<
0067                         switch_case_is_nullary(
0068                             proto::_child_c<0>
0069                           , proto::_state
0070                         )
0071                       , switch_case_is_nullary(
0072                             proto::_child_c<1>
0073                           , proto::_state
0074                         )
0075                     >()
0076                 >
0077               , proto::when<
0078                     proto::or_<phoenix::rule::switch_default_case, phoenix::rule::switch_case>
0079                   , evaluator(proto::_child_c<0>, proto::_state)
0080                 >
0081             >
0082         {};
0083 
0084         struct switch_case_grammar
0085             : proto::or_<
0086                 proto::comma<switch_case_grammar, phoenix::rule::switch_case>
0087               , proto::when<phoenix::rule::switch_case, proto::_>
0088             >
0089         {};
0090 
0091         struct switch_case_with_default_grammar
0092             : proto::or_<
0093                 proto::comma<switch_case_grammar, phoenix::rule::switch_default_case>
0094               , proto::when<phoenix::rule::switch_default_case, proto::_>
0095             >
0096         {};
0097 
0098         struct switch_size
0099             : proto::or_<
0100                 proto::when<
0101                     proto::comma<switch_size, proto::_>
0102                   , mpl::next<switch_size(proto::_left)>()
0103                 >
0104               , proto::when<proto::_, mpl::int_<1>()>
0105             >
0106         {};
0107     }
0108 }}
0109 
0110 BOOST_PHOENIX_DEFINE_EXPRESSION(
0111     (boost)(phoenix)(switch_)
0112   , (meta_grammar)           // Cond
0113     (detail::switch_grammar) // Cases
0114 )
0115 
0116 namespace boost { namespace phoenix {
0117 
0118     template <typename Dummy>
0119     struct is_nullary::when<rule::switch_, Dummy>
0120         : proto::and_<
0121             evaluator(proto::_child_c<0>, _context)
0122           , detail::switch_case_is_nullary(proto::_child_c<1>, _context)
0123         >
0124     {};
0125 
0126     struct switch_eval
0127     {
0128         typedef void result_type;
0129         
0130         template <typename Context>
0131         result_type
0132         operator()(Context const &) const
0133         {
0134         }
0135 
0136         template <typename Cond, typename Cases, typename Context>
0137         result_type
0138         operator()(Cond const & cond, Cases const & cases, Context const & ctx) const
0139         {
0140             this->evaluate(
0141                     ctx
0142                   , cond
0143                   , cases
0144                   , typename detail::switch_size::impl<Cases, int, proto::empty_env>::result_type()
0145                   , typename detail::switch_grammar::impl<Cases, int, proto::empty_env>::result_type()
0146                 );
0147         }
0148 
0149         private:
0150             template <typename Context, typename Cond, typename Cases>
0151             result_type
0152             evaluate(
0153                 Context const & ctx
0154               , Cond const & cond
0155               , Cases const & cases
0156               , mpl::int_<1>
0157               , mpl::false_
0158             ) const
0159             {
0160                 typedef
0161                     typename proto::result_of::value<
0162                         typename proto::result_of::child_c<
0163                             Cases
0164                           , 0
0165                         >::type
0166                     >::type
0167                     case_label;
0168 
0169                 switch(boost::phoenix::eval(cond, ctx))
0170                 {
0171                     case case_label::value:
0172                         boost::phoenix::eval(proto::child_c<1>(cases), ctx);
0173                 }
0174             }
0175             
0176             template <typename Context, typename Cond, typename Cases>
0177             result_type
0178             evaluate(
0179                 Context const & ctx
0180               , Cond const & cond
0181               , Cases const & cases
0182               , mpl::int_<1>
0183               , mpl::true_
0184             ) const
0185             {
0186                 switch(boost::phoenix::eval(cond, ctx))
0187                 {
0188                     default:
0189                         boost::phoenix::eval(proto::child_c<0>(cases), ctx);
0190                 }
0191             }
0192 
0193             // Bring in the evaluation functions
0194             #include <boost/phoenix/statement/detail/switch.hpp>
0195     };
0196     
0197     template <typename Dummy>
0198     struct default_actions::when<rule::switch_, Dummy>
0199         : call<switch_eval>
0200     {};
0201 
0202     template <int N, typename A>
0203     inline
0204     typename proto::result_of::make_expr<
0205         tag::switch_case
0206       , proto::basic_default_domain
0207       , mpl::int_<N>
0208       , A
0209     >::type const
0210     case_(A const & a)
0211     {
0212         return
0213             proto::make_expr<
0214                 tag::switch_case
0215               , proto::basic_default_domain
0216             >(
0217                 mpl::int_<N>()
0218               , a
0219             );
0220     }
0221 
0222     template <typename A>
0223     inline
0224     typename proto::result_of::make_expr<
0225         tag::switch_default_case
0226       , proto::basic_default_domain
0227       , A
0228     >::type const
0229     default_(A const& a)
0230     {
0231         return
0232             proto::make_expr<
0233                 tag::switch_default_case
0234               , proto::basic_default_domain
0235             >(a);
0236     }
0237 
0238     template <typename Cond>
0239     struct switch_gen
0240     {
0241         switch_gen(Cond const& cond_) : cond(cond_) {}
0242 
0243         template <typename Cases>
0244         typename expression::switch_<
0245             Cond
0246           , Cases
0247         >::type
0248         operator[](Cases const& cases) const
0249         {
0250             return
0251                 this->generate(
0252                     cases
0253                   , proto::matches<Cases, detail::switch_grammar>()
0254                 );
0255         }
0256 
0257         private:
0258             Cond const& cond;
0259 
0260             template <typename Cases>
0261             typename expression::switch_<
0262                 Cond
0263               , Cases
0264             >::type
0265             generate(Cases const & cases, mpl::true_) const
0266             {
0267                 return expression::switch_<Cond, Cases>::make(cond, cases);
0268             }
0269             
0270             template <typename Cases>
0271             typename expression::switch_<
0272                 Cond
0273               , Cases
0274             >::type
0275             generate(Cases const &, mpl::false_) const
0276             {
0277                 BOOST_MPL_ASSERT_MSG(
0278                     false
0279                   , INVALID_SWITCH_CASE_STATEMENT
0280                   , (Cases)
0281                 );
0282             }
0283     };
0284 
0285     template <typename Cond>
0286     inline
0287     switch_gen<Cond> const
0288     switch_(Cond const& cond)
0289     {
0290         return switch_gen<Cond>(cond);
0291     }
0292 
0293 }}
0294 
0295 #ifdef _MSC_VER
0296 #pragma warning(pop)
0297 #endif
0298 
0299 #endif
0300