Chris@16: /*============================================================================== Chris@16: Copyright (c) 2001-2010 Joel de Guzman Chris@16: Copyright (c) 2010 Thomas Heller Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ==============================================================================*/ Chris@16: #ifndef BOOST_PHOENIX_STATEMENT_SWITCH_HPP Chris@16: #define BOOST_PHOENIX_STATEMENT_SWITCH_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef _MSC_VER Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels Chris@16: #endif Chris@16: Chris@16: BOOST_PHOENIX_DEFINE_EXPRESSION( Chris@16: (boost)(phoenix)(switch_case) Chris@16: , (proto::terminal) Chris@16: (meta_grammar) Chris@16: ) Chris@16: Chris@16: BOOST_PHOENIX_DEFINE_EXPRESSION( Chris@16: (boost)(phoenix)(switch_default_case) Chris@16: , (meta_grammar) Chris@16: ) Chris@16: Chris@16: namespace boost { namespace phoenix Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: struct switch_case_grammar; Chris@16: struct switch_case_with_default_grammar; Chris@16: struct switch_grammar Chris@16: : proto::or_< Chris@16: proto::when< Chris@16: detail::switch_case_grammar Chris@16: , mpl::false_() Chris@16: > Chris@16: , proto::when< Chris@16: detail::switch_case_with_default_grammar Chris@16: , mpl::true_() Chris@16: > Chris@16: > Chris@16: {}; Chris@16: } Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: struct switch_case_is_nullary Chris@16: : proto::or_< Chris@16: proto::when< Chris@16: proto::comma< Chris@16: switch_case_is_nullary Chris@16: , proto::or_ Chris@16: > Chris@16: , mpl::and_< Chris@16: switch_case_is_nullary( Chris@16: proto::_child_c<0> Chris@16: , proto::_state Chris@16: ) Chris@16: , switch_case_is_nullary( Chris@16: proto::_child_c<1> Chris@16: , proto::_state Chris@16: ) Chris@16: >() Chris@16: > Chris@16: , proto::when< Chris@16: proto::or_ Chris@16: , evaluator(proto::_child_c<0>, proto::_state) Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: struct switch_case_grammar Chris@16: : proto::or_< Chris@16: proto::comma Chris@16: , proto::when Chris@16: > Chris@16: {}; Chris@16: Chris@16: struct switch_case_with_default_grammar Chris@16: : proto::or_< Chris@16: proto::comma Chris@16: , proto::when Chris@16: > Chris@16: {}; Chris@16: Chris@16: struct switch_size Chris@16: : proto::or_< Chris@16: proto::when< Chris@16: proto::comma Chris@16: , mpl::next() Chris@16: > Chris@16: , proto::when()> Chris@16: > Chris@16: {}; Chris@16: } Chris@16: }} Chris@16: Chris@16: BOOST_PHOENIX_DEFINE_EXPRESSION( Chris@16: (boost)(phoenix)(switch_) Chris@16: , (meta_grammar) // Cond Chris@16: (detail::switch_grammar) // Cases Chris@16: ) Chris@16: Chris@16: namespace boost { namespace phoenix { Chris@16: Chris@16: template Chris@16: struct is_nullary::when Chris@16: : proto::and_< Chris@16: evaluator(proto::_child_c<0>, _context) Chris@16: , detail::switch_case_is_nullary(proto::_child_c<1>, _context) Chris@16: > Chris@16: {}; Chris@16: Chris@16: struct switch_eval Chris@16: { Chris@16: typedef void result_type; Chris@16: Chris@16: template Chris@16: result_type Chris@16: operator()(Context const &) const Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: result_type Chris@16: operator()(Cond const & cond, Cases const & cases, Context const & ctx) const Chris@16: { Chris@16: this->evaluate( Chris@16: ctx Chris@16: , cond Chris@16: , cases Chris@16: , typename detail::switch_size::impl::result_type() Chris@16: , typename detail::switch_grammar::impl::result_type() Chris@16: ); Chris@16: } Chris@16: Chris@16: private: Chris@16: template Chris@16: result_type Chris@16: evaluate( Chris@16: Context const & ctx Chris@16: , Cond const & cond Chris@16: , Cases const & cases Chris@16: , mpl::int_<1> Chris@16: , mpl::false_ Chris@16: ) const Chris@16: { Chris@16: typedef Chris@16: typename proto::result_of::value< Chris@16: typename proto::result_of::child_c< Chris@16: Cases Chris@16: , 0 Chris@16: >::type Chris@16: >::type Chris@16: case_label; Chris@16: Chris@16: switch(boost::phoenix::eval(cond, ctx)) Chris@16: { Chris@16: case case_label::value: Chris@16: boost::phoenix::eval(proto::child_c<1>(cases), ctx); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: result_type Chris@16: evaluate( Chris@16: Context const & ctx Chris@16: , Cond const & cond Chris@16: , Cases const & cases Chris@16: , mpl::int_<1> Chris@16: , mpl::true_ Chris@16: ) const Chris@16: { Chris@16: switch(boost::phoenix::eval(cond, ctx)) Chris@16: { Chris@16: default: Chris@16: boost::phoenix::eval(proto::child_c<0>(cases), ctx); Chris@16: } Chris@16: } Chris@16: Chris@16: // Bring in the evaluation functions Chris@16: #include Chris@16: }; Chris@16: Chris@16: template Chris@16: struct default_actions::when Chris@16: : call Chris@16: {}; Chris@16: Chris@16: template Chris@16: inline Chris@16: typename proto::result_of::make_expr< Chris@16: tag::switch_case Chris@16: , proto::basic_default_domain Chris@16: , mpl::int_ Chris@16: , A Chris@16: >::type const Chris@16: case_(A const & a) Chris@16: { Chris@16: return Chris@16: proto::make_expr< Chris@16: tag::switch_case Chris@16: , proto::basic_default_domain Chris@16: >( Chris@16: mpl::int_() Chris@16: , a Chris@16: ); Chris@16: } Chris@16: Chris@16: template Chris@16: inline Chris@16: typename proto::result_of::make_expr< Chris@16: tag::switch_default_case Chris@16: , proto::basic_default_domain Chris@16: , A Chris@16: >::type const Chris@16: default_(A const& a) Chris@16: { Chris@16: return Chris@16: proto::make_expr< Chris@16: tag::switch_default_case Chris@16: , proto::basic_default_domain Chris@16: >(a); Chris@16: } Chris@16: Chris@16: template Chris@16: struct switch_gen Chris@16: { Chris@101: switch_gen(Cond const& cond_) : cond(cond_) {} Chris@16: Chris@16: template Chris@16: typename expression::switch_< Chris@16: Cond Chris@16: , Cases Chris@16: >::type Chris@16: operator[](Cases const& cases) const Chris@16: { Chris@16: return Chris@16: this->generate( Chris@16: cases Chris@16: , proto::matches() Chris@16: ); Chris@16: } Chris@16: Chris@16: private: Chris@16: Cond const& cond; Chris@16: Chris@16: template Chris@16: typename expression::switch_< Chris@16: Cond Chris@16: , Cases Chris@16: >::type Chris@16: generate(Cases const & cases, mpl::true_) const Chris@16: { Chris@16: return expression::switch_::make(cond, cases); Chris@16: } Chris@16: Chris@16: template Chris@16: typename expression::switch_< Chris@16: Cond Chris@16: , Cases Chris@16: >::type Chris@16: generate(Cases const &, mpl::false_) const Chris@16: { Chris@16: BOOST_MPL_ASSERT_MSG( Chris@16: false Chris@16: , INVALID_SWITCH_CASE_STATEMENT Chris@16: , (Cases) Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline Chris@16: switch_gen const Chris@16: switch_(Cond const& cond) Chris@16: { Chris@16: return switch_gen(cond); Chris@16: } Chris@16: Chris@16: }} Chris@16: Chris@16: #ifdef _MSC_VER Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif Chris@16: