text: /*=============================================================================
      Copyright (c) 2003 Hartmut Kaiser
      http://spirit.sourceforge.net/
  
      Use, modification and distribution is subject to 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_SPIRIT_SWITCH_IPP
  #define BOOST_SPIRIT_SWITCH_IPP
  
  #include <boost/mpl/if.hpp>
  #include <boost/type_traits/is_same.hpp>
  #include <boost/static_assert.hpp>
  
  #include <boost/preprocessor/cat.hpp>
  #include <boost/preprocessor/inc.hpp>
  #include <boost/preprocessor/repeat.hpp>
  #include <boost/preprocessor/repeat_from_to.hpp>
  
  #include <boost/spirit/core/parser.hpp>
  #include <boost/spirit/core/primitives/primitives.hpp>
  #include <boost/spirit/core/composite/composite.hpp>
  #include <boost/spirit/meta/as_parser.hpp>
  
  #include <boost/spirit/phoenix/actor.hpp>
  #include <boost/spirit/phoenix/tuples.hpp>
  
  ///////////////////////////////////////////////////////////////////////////////
  namespace boost { namespace spirit {
  
  // forward declaration
  template <int N, typename ParserT, bool IsDefault> struct case_parser;
  
  ///////////////////////////////////////////////////////////////////////////////
  namespace impl {
  
  ///////////////////////////////////////////////////////////////////////////////
  //  parse helper functions
  template <typename ParserT, typename ScannerT>
  inline typename parser_result<ParserT, ScannerT>::type
  delegate_parse(ParserT const &p, ScannerT const &scan,
      typename ScannerT::iterator_t const save)
  {
      typedef typename parser_result<ParserT, ScannerT>::type result_t;
  
      result_t result (p.subject().parse(scan));
      if (!result)
          scan.first = save;
      return result;
  }
  
  ///////////////////////////////////////////////////////////////////////////////
  //  General default case handling (no default_p case branch given).
  //  First try to match the current parser node (if the condition value is
  //  matched) and, if that fails, return a no_match
  template <int N, bool IsDefault, bool HasDefault>
  struct default_delegate_parse {
  
      template <
          typename ParserT, typename DefaultT,
          typename ValueT, typename ScannerT
      >
      static typename parser_result<ParserT, ScannerT>::type
      parse (ValueT const &value, ParserT const &p, DefaultT const &,
          ScannerT const &scan, typename ScannerT::iterator_t const save)
      {
          if (value == N)
              return delegate_parse(p, scan, save);
          return scan.no_match();
      }
  };
  
  //  The current case parser node is the default parser.
  //  Ignore the given case value and try to match the given default parser.
  template <int N, bool HasDefault>
  struct default_delegate_parse<N, true, HasDefault> {
  
      template <
          typename ParserT, typename DefaultT,
          typename ValueT, typename ScannerT
      >
      static typename parser_result<ParserT, ScannerT>::type
      parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d,
          ScannerT const &scan, typename ScannerT::iterator_t const save)
      {
          //  Since there is a default_p case branch defined, the corresponding
          //  parser shouldn't be the nothing_parser
          BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
          return delegate_parse(d, scan, save);
      }
  };
  
  //  The current case parser node is not the default parser, but there is a
  //  default_p branch given inside the switch_p parser.
  //  First try to match the current parser node (if the condition value is
  //  matched) and, if that fails, match the given default_p parser.
  template <int N>
  struct default_delegate_parse<N, false, true> {
  
      template <
          typename ParserT, typename DefaultT,
          typename ValueT, typename ScannerT
      >
      static typename parser_result<ParserT, ScannerT>::type
      parse (ValueT const &value, ParserT const &p, DefaultT const &d,
          ScannerT const &scan, typename ScannerT::iterator_t const save)
      {
          //  Since there is a default_p case branch defined, the corresponding
          //  parser shouldn't be the nothing_parser
          BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
          if (value == N)
              return delegate_parse(p, scan, save);
  
          return delegate_parse(d, scan, save);
      }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  Look through the case parser chain to test, if there is a default case
  //  branch defined (returned by 'value').
  template <typename CaseT, bool IsSimple = CaseT::is_simple>
  struct default_case;
  
  ////////////////////////////////////////
  template <typename ResultT, bool IsDefault>
  struct get_default_parser {
  
      template <typename ParserT>
      static ResultT
      get(parser<ParserT> const &p)
      {
          return default_case<typename ParserT::derived_t::left_t>::
              get(p.derived().left());
      }
  };
  
  template <typename ResultT>
  struct get_default_parser<ResultT, true> {
  
      template <typename ParserT>
      static ResultT
      get(parser<ParserT> const &p) { return p.derived().right(); }
  };
  
  ////////////////////////////////////////
  template <typename CaseT, bool IsSimple>
  struct default_case {
  
      //  The 'value' constant is true, if the current case_parser or one of its
      //  left siblings is a default_p generated case_parser.
      BOOST_STATIC_CONSTANT(bool, value =
          (CaseT::is_default || default_case<typename CaseT::left_t>::value));
  
      //  The 'is_epsilon' constant is true, if the current case_parser or one of
      //  its left siblings is a default_p generated parser with an attached
      //  epsilon_p (this is generated by the plain default_p).
      BOOST_STATIC_CONSTANT(bool, is_epsilon = (
          (CaseT::is_default && CaseT::is_epsilon) ||
              default_case<typename CaseT::left_t>::is_epsilon
      ));
  
      //  The computed 'type' represents the type of the default case branch
      //  parser (if there is one) or nothing_parser (if there isn't any default
      //  case branch).
      typedef typename boost::mpl::if_c<
              CaseT::is_default, typename CaseT::right_embed_t,
              typename default_case<typename CaseT::left_t>::type
          >::type type;
  
      //  The get function returns the parser attached to the default case branch
      //  (if there is one) or an instance of a nothing_parser (if there isn't
      //  any default case branch).
      template <typename ParserT>
      static type
      get(parser<ParserT> const &p)
      { return get_default_parser<type, CaseT::is_default>::get(p); }
  };
  
  ////////////////////////////////////////
  template <typename ResultT, bool IsDefault>
  struct get_default_parser_simple {
  
      template <typename ParserT>
      static ResultT
      get(parser<ParserT> const &p) { return p.derived(); }
  };
  
  template <typename ResultT>
  struct get_default_parser_simple<ResultT, false> {
  
      template <typename ParserT>
      static nothing_parser
      get(parser<ParserT> const &) { return nothing_p; }
  };
  
  ////////////////////////////////////////
  //  Specialization of the default_case template for the last (leftmost) element
  //  of the case parser chain.
  template <typename CaseT>
  struct default_case<CaseT, true> {
  
      //  The 'value' and 'is_epsilon' constant, the 'type' type and the function
      //  'get' are described above.
  
      BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default);
      BOOST_STATIC_CONSTANT(bool, is_epsilon = (
          CaseT::is_default && CaseT::is_epsilon
      ));
  
      typedef typename boost::mpl::if_c<
              CaseT::is_default, CaseT, nothing_parser
          >::type type;
  
      template <typename ParserT>
      static type
      get(parser<ParserT> const &p)
      { return get_default_parser_simple<type, value>::get(p); }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The case_chain template calculates recursivly the depth of the left
  //  subchain of the given case branch node.
  template <typename CaseT, bool IsSimple = CaseT::is_simple>
  struct case_chain {
  
      BOOST_STATIC_CONSTANT(int, depth = (
          case_chain<typename CaseT::left_t>::depth + 1
      ));
  };
  
  template <typename CaseT>
  struct case_chain<CaseT, true> {
  
      BOOST_STATIC_CONSTANT(int, depth = 0);
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The chain_parser template is used to extract the type and the instance of
  //  a left or a right parser, burried arbitrary deep inside the case parser
  //  chain.
  template <int Depth, typename CaseT>
  struct chain_parser {
  
      typedef typename CaseT::left_t our_left_t;
  
      typedef typename chain_parser<Depth-1, our_left_t>::left_t  left_t;
      typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t;
  
      static left_t
      left(CaseT const &p)
      { return chain_parser<Depth-1, our_left_t>::left(p.left()); }
  
      static right_t
      right(CaseT const &p)
      { return chain_parser<Depth-1, our_left_t>::right(p.left()); }
  };
  
  template <typename CaseT>
  struct chain_parser<1, CaseT> {
  
      typedef typename CaseT::left_t  left_t;
      typedef typename CaseT::right_t right_t;
  
      static left_t left(CaseT const &p) { return p.left(); }
      static right_t right(CaseT const &p) { return p.right(); }
  };
  
  template <typename CaseT>
  struct chain_parser<0, CaseT>;      // shouldn't be instantiated
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The parse_switch::do_ functions dispatch to the correct parser, which is
  //  selected through the given conditional switch value.
  template <int Value, int Depth, bool IsDefault>
  struct parse_switch;
  
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  The following generates a couple of parse_switch template specializations
  //  with an increasing number of handled case branches (for 1..N).
  //
  //      template <int Value, bool IsDefault>
  //      struct parse_switch<Value, N, IsDefault> {
  //
  //          template <typename ParserT, typename ScannerT>
  //          static typename parser_result<ParserT, ScannerT>::type
  //          do_(ParserT const &p, ScannerT const &scan, long cond_value,
  //              typename ScannerT::iterator_t const &save)
  //          {
  //              typedef ParserT left_t0;
  //              typedef typename left_t0::left left_t1;
  //              ...
  //
  //              switch (cond_value) {
  //              case left_tN::value:
  //                  return delegate_parse(chain_parser<
  //                          case_chain<ParserT>::depth, ParserT
  //                      >::left(p), scan, save);
  //              ...
  //              case left_t1::value:
  //                  return delegate_parse(chain_parser<
  //                          1, left_t1
  //                      >::right(p.left()), scan, save);
  //
  //              case left_t0::value:
  //              default:
  //                  typedef default_case<ParserT> default_t;
  //                  typedef default_delegate_parse<
  //                              Value, IsDefault, default_t::value>
  //                      default_parse_t;
  //
  //                  return default_parse_t::parse(cond_value, p.right(),
  //                      default_t::get(p), scan, save);
  //              }
  //          }
  //      };
  //
  ///////////////////////////////////////////////////////////////////////////////
  #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _)                         \
      typedef typename BOOST_PP_CAT(left_t, N)::left_t                        \
          BOOST_PP_CAT(left_t, BOOST_PP_INC(N));                              \
      /**/
  
  #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _)                            \
      case BOOST_PP_CAT(left_t, N)::value:                                    \
          return delegate_parse(chain_parser<N, left_t1>::right(p.left()),    \
              scan, save);                                                    \
      /**/
  
  #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _)                                \
      template <int Value, bool IsDefault>                                    \
      struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> {                \
                                                                              \
          template <typename ParserT, typename ScannerT>                      \
          static typename parser_result<ParserT, ScannerT>::type              \
          do_(ParserT const &p, ScannerT const &scan, long cond_value,        \
              typename ScannerT::iterator_t const &save)                      \
          {                                                                   \
              typedef ParserT left_t0;                                        \
              BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N),               \
                  BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _)                      \
                                                                              \
              switch (cond_value) {                                           \
              case BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value:              \
                  return delegate_parse(                                      \
                      chain_parser<                                           \
                          case_chain<ParserT>::depth, ParserT                 \
                      >::left(p), scan, save);                                \
                                                                              \
              BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N),               \
                  BOOST_SPIRIT_PARSE_SWITCH_CASES, _)                         \
                                                                              \
              case left_t0::value:                                            \
              default:                                                        \
                  typedef default_case<ParserT> default_t;                    \
                  typedef                                                     \
                      default_delegate_parse<Value, IsDefault, default_t::value> \
                      default_parse_t;                                        \
                                                                              \
                  return default_parse_t::parse(cond_value, p.right(),        \
                      default_t::get(p), scan, save);                         \
              }                                                               \
          }                                                                   \
      };                                                                      \
      /**/
  
  BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT),
      BOOST_SPIRIT_PARSE_SWITCHES, _)
  
  #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS
  #undef BOOST_SPIRIT_PARSE_SWITCH_CASES
  #undef BOOST_SPIRIT_PARSE_SWITCHES
  ///////////////////////////////////////////////////////////////////////////////
  
  ///////////////////////////////////////////////////////////////////////////////
  //  Type computing meta function for calculating the type of the return value
  //  of the used conditional switch expression
  template <typename TargetT, typename ScannerT>
  struct condition_result {
  
      typedef typename TargetT::template result<ScannerT>::type type;
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  template <typename LeftT, typename RightT, bool IsDefault>
  struct compound_case_parser
  :   public binary<LeftT, RightT,
          parser<compound_case_parser<LeftT, RightT, IsDefault> > >
  {
      typedef compound_case_parser<LeftT, RightT, IsDefault>    self_t;
      typedef binary_parser_category                  parser_category_t;
      typedef binary<LeftT, RightT, parser<self_t> >  base_t;
  
      BOOST_STATIC_CONSTANT(int, value = RightT::value);
      BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
      BOOST_STATIC_CONSTANT(bool, is_simple = false);
      BOOST_STATIC_CONSTANT(bool, is_epsilon = (
          is_default &&
              boost::is_same<typename RightT::subject_t, epsilon_parser>::value
      ));
  
      compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs)
      :   base_t(lhs.derived(), rhs.derived())
      {}
  
      template <typename ScannerT>
      struct result
      {
          typedef typename match_result<ScannerT, nil_t>::type type;
      };
  
      template <typename ScannerT, typename CondT>
      typename parser_result<self_t, ScannerT>::type
      parse(ScannerT const& scan, CondT const &cond) const
      {
          scan.at_end();    // allow skipper to take effect
          return parse_switch<value, case_chain<self_t>::depth, is_default>::
              do_(*this, scan, cond(scan), scan.first);
      }
  
      template <int N1, typename ParserT1, bool IsDefault1>
      compound_case_parser<
          self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
      >
      operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
      {
          //  If the following compile time assertion fires, you've probably used
          //  more than one default_p case inside the switch_p parser construct.
          BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1);
  
          //  If this compile time assertion fires, you've probably want to use
          //  more case_p/default_p case branches, than possible.
          BOOST_STATIC_ASSERT(
              case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT
          );
  
          typedef case_parser<N1, ParserT1, IsDefault1> right_t;
          return compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
      }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The switch condition is to be evaluated from a parser result value.
  template <typename ParserT>
  struct cond_functor {
  
      typedef cond_functor<ParserT> self_t;
  
      cond_functor(ParserT const &p_)
      :   p(p_)
      {}
  
      template <typename ScannerT>
      struct result
      {
          typedef typename parser_result<ParserT, ScannerT>::type::attr_t type;
      };
  
      template <typename ScannerT>
      typename condition_result<self_t, ScannerT>::type
      operator()(ScannerT const &scan) const
      {
          typedef typename parser_result<ParserT, ScannerT>::type result_t;
          typedef typename result_t::attr_t attr_t;
  
          result_t result(p.parse(scan));
          return !result ? attr_t() : result.value();
      }
  
      typename ParserT::embed_t p;
  };
  
  template <typename ParserT>
  struct make_cond_functor {
  
      typedef as_parser<ParserT> as_parser_t;
  
      static cond_functor<typename as_parser_t::type>
      do_(ParserT const &cond)
      {
          return cond_functor<typename as_parser_t::type>(
              as_parser_t::convert(cond));
      }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The switch condition is to be evaluated from a phoenix actor
  template <typename ActorT>
  struct cond_actor {
  
      typedef cond_actor<ActorT> self_t;
  
      cond_actor(ActorT const &actor_)
      :   actor(actor_)
      {}
  
      template <typename ScannerT>
      struct result
      {
          typedef typename phoenix::actor_result<ActorT, phoenix::tuple<> >::type
              type;
      };
  
      template <typename ScannerT>
      typename condition_result<self_t, ScannerT>::type
      operator()(ScannerT const& /*scan*/) const
      {
          return actor();
      }
  
      ActorT const &actor;
  };
  
  template <typename ActorT>
  struct make_cond_functor<phoenix::actor<ActorT> > {
  
      static cond_actor<phoenix::actor<ActorT> >
      do_(phoenix::actor<ActorT> const &actor)
      {
          return cond_actor<phoenix::actor<ActorT> >(actor);
      }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  //  The switch condition is to be taken directly from the input stream
  struct get_next_token_cond {
  
      typedef get_next_token_cond self_t;
  
      template <typename ScannerT>
      struct result
      {
          typedef typename ScannerT::value_t type;
      };
  
      template <typename ScannerT>
      typename condition_result<self_t, ScannerT>::type
      operator()(ScannerT const &scan) const
      {
          typename ScannerT::value_t val(*scan);
          ++scan.first;
          return val;
      }
  };
  
  template <>
  struct make_cond_functor<get_next_token_cond> {
  
      static get_next_token_cond
      do_(get_next_token_cond const &cond)
      {
          return cond;
      }
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  }   // namespace impl
  }}  // namespace boost::spirit
  
  #endif  // BOOST_SPIRIT_SWITCH_IPP
  