File indexing completed on 2025-01-18 09:47:40
0001
0002
0003
0004
0005
0006
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)
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)
0113 (detail::switch_grammar)
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
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