| /*============================================================================= |
| 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 { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| template <typename FirstT, typename RestT> |
| struct subrule_list; |
| |
| template <int ID, typename DefT, typename ContextT> |
| struct subrule_parser; |
| |
| namespace impl { |
| |
| #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
| |
| template <int N, typename ListT> |
| struct get_subrule; |
| |
| template <int N, typename ListT> |
| 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 <int N> |
| struct subrule_chooser; |
| |
| template <> |
| struct subrule_chooser<0> |
| { |
| // First case. ListT is empty |
| |
| template <int N, typename ListT> |
| 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 <int N, typename ListT> |
| 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 <int N, typename ListT> |
| struct result |
| { typedef typename get_subrule<N, ListT::rest_t>::type type; }; |
| }; |
| |
| template <int N, typename ListT> |
| struct get_subrule |
| { |
| enum { n = get_subrule_chooser<N, ListT>::value }; |
| typedef typename subrule_chooser<n>::template |
| result<N, ListT>::type type; |
| }; |
| |
| #else |
| |
| template <int N, typename ListT> |
| 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<N, typename ListT::rest_t>::type type; |
| }; |
| |
| template <int ID, typename DefT, typename ContextT, typename RestT> |
| struct get_subrule< |
| ID, |
| subrule_list< |
| subrule_parser<ID, DefT, ContextT>, |
| RestT> > |
| { |
| // Second case. ListT is non-empty and the list's |
| // first item has the ID we are looking for. |
| |
| typedef DefT type; |
| }; |
| |
| template <int ID> |
| struct get_subrule<ID, nil_t> |
| { |
| // Third case. ListT is empty |
| typedef nil_t type; |
| }; |
| |
| #endif |
| |
| template <typename T1, typename T2> |
| 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<T1, nil_t>, T2, T1 |
| >::type type; |
| }; |
| |
| template <int ID, typename ScannerT, typename ContextResultT> |
| struct get_subrule_result |
| { |
| typedef typename |
| impl::get_subrule<ID, typename ScannerT::list_t>::type |
| parser_t; |
| |
| typedef typename parser_result<parser_t, ScannerT>::type |
| def_result_t; |
| |
| typedef typename match_result<ScannerT, ContextResultT>::type |
| context_result_t; |
| |
| typedef typename get_result_t<context_result_t, def_result_t>::type |
| type; |
| }; |
| |
| template <typename DefT, typename ScannerT, typename ContextResultT> |
| struct get_subrule_parser_result |
| { |
| typedef typename parser_result<DefT, ScannerT>::type |
| def_result_t; |
| |
| typedef typename match_result<ScannerT, ContextResultT>::type |
| context_result_t; |
| |
| typedef typename get_result_t<context_result_t, def_result_t>::type |
| type; |
| }; |
| |
| template <typename SubruleT, int ID> |
| struct same_subrule_id |
| { |
| BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID)); |
| }; |
| |
| template <typename RT, typename ScannerT, int ID> |
| struct parse_subrule |
| { |
| template <typename ListT> |
| static void |
| do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_) |
| { |
| r = list.first.rhs.parse(scan); |
| } |
| |
| template <typename ListT> |
| 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_<same_subrule_id<subrule_t, ID>::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_<same_subrule_id<subrule_t, ID>::value> same_id; |
| do_parse(r, scan, scan.list, same_id); |
| } |
| }; |
| |
| } |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace boost::spirit::impl |
| |
| #endif |
| |