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