/*============================================================================= Copyright (c) 2002-2003 Joel de Guzman Copyright (c) 2002-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) =============================================================================*/ #if !defined(BOOST_SPIRIT_SUBRULE_IPP) #define BOOST_SPIRIT_SUBRULE_IPP namespace boost { namespace spirit { template struct subrule_list; template struct subrule_parser; namespace impl { #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template struct get_subrule; template struct get_subrule_chooser { static ListT t(); static char test(nil_t); static int test(...); // Set value to // 0: ListT is empty // 1: ListT's first item has same ID // 2: ListT's first item has a different ID enum { id = ListT::first_t::id, is_same_id = N == id, is_nil_t = sizeof(char) == sizeof(test(t())), value = is_nil_t ? 0 : (is_same_id ? 1 : 2) }; }; template struct subrule_chooser; template <> struct subrule_chooser<0> { // First case. ListT is empty template struct result { typedef nil_t type; }; }; template <> struct subrule_chooser<1> { // Second case. ListT is non-empty and the list's // first item has the ID we are looking for. template struct result { typedef typename ListT::first_t::def_t type; }; }; template <> struct subrule_chooser<2> { // Third case. ListT is non-empty but the list's // first item does not have the ID we are looking for. template struct result { typedef typename get_subrule::type type; }; }; template struct get_subrule { enum { n = get_subrule_chooser::value }; typedef typename subrule_chooser::template result::type type; }; #else template struct get_subrule { // First case. ListT is non-empty but the list's // first item does not have the ID we are looking for. typedef typename get_subrule::type type; }; template struct get_subrule< ID, subrule_list< subrule_parser, RestT> > { // Second case. ListT is non-empty and the list's // first item has the ID we are looking for. typedef DefT type; }; template struct get_subrule { // Third case. ListT is empty typedef nil_t type; }; #endif template struct get_result_t { // If the result type dictated by the context is nil_t (no closures // present), then the whole subrule_parser return type is equal to // the return type of the right hand side of this subrule_parser, // otherwise it is equal to the dictated return value. typedef typename mpl::if_< boost::is_same, T2, T1 >::type type; }; template struct get_subrule_result { typedef typename impl::get_subrule::type parser_t; typedef typename parser_result::type def_result_t; typedef typename match_result::type context_result_t; typedef typename get_result_t::type type; }; template struct get_subrule_parser_result { typedef typename parser_result::type def_result_t; typedef typename match_result::type context_result_t; typedef typename get_result_t::type type; }; template struct same_subrule_id { BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID)); }; template struct parse_subrule { template static void do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_) { r = list.first.rhs.parse(scan); } template static void do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::false_) { typedef typename ListT::rest_t::first_t subrule_t; mpl::bool_::value> same_id; do_parse(r, scan, list.rest, same_id); } static void do_(RT& r, ScannerT const& scan) { typedef typename ScannerT::list_t::first_t subrule_t; mpl::bool_::value> same_id; do_parse(r, scan, scan.list, same_id); } }; }}} // namespace boost::spirit::impl #endif