1/*============================================================================= 2 Copyright (c) 2002-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Hartmut Kaiser 4 http://spirit.sourceforge.net/ 5 6 Use, modification and distribution is subject to the Boost Software 7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 http://www.boost.org/LICENSE_1_0.txt) 9=============================================================================*/ 10#if !defined(BOOST_SPIRIT_SUBRULE_IPP) 11#define BOOST_SPIRIT_SUBRULE_IPP 12 13#include <boost/mpl/if.hpp> 14 15namespace boost { namespace spirit { 16 17BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 18 19 template <typename FirstT, typename RestT> 20 struct subrule_list; 21 22 template <int ID, typename DefT, typename ContextT> 23 struct subrule_parser; 24 25 namespace impl { 26 27 28 template <int N, typename ListT> 29 struct get_subrule 30 { 31 // First case. ListT is non-empty but the list's 32 // first item does not have the ID we are looking for. 33 34 typedef typename get_subrule<N, typename ListT::rest_t>::type type; 35 }; 36 37 template <int ID, typename DefT, typename ContextT, typename RestT> 38 struct get_subrule< 39 ID, 40 subrule_list< 41 subrule_parser<ID, DefT, ContextT>, 42 RestT> > 43 { 44 // Second case. ListT is non-empty and the list's 45 // first item has the ID we are looking for. 46 47 typedef DefT type; 48 }; 49 50 template <int ID> 51 struct get_subrule<ID, nil_t> 52 { 53 // Third case. ListT is empty 54 typedef nil_t type; 55 }; 56 57 58 template <typename T1, typename T2> 59 struct get_result_t { 60 61 // If the result type dictated by the context is nil_t (no closures 62 // present), then the whole subrule_parser return type is equal to 63 // the return type of the right hand side of this subrule_parser, 64 // otherwise it is equal to the dictated return value. 65 66 typedef typename mpl::if_< 67 boost::is_same<T1, nil_t>, T2, T1 68 >::type type; 69 }; 70 71 template <int ID, typename ScannerT, typename ContextResultT> 72 struct get_subrule_result 73 { 74 typedef typename 75 impl::get_subrule<ID, typename ScannerT::list_t>::type 76 parser_t; 77 78 typedef typename parser_result<parser_t, ScannerT>::type 79 def_result_t; 80 81 typedef typename match_result<ScannerT, ContextResultT>::type 82 context_result_t; 83 84 typedef typename get_result_t<context_result_t, def_result_t>::type 85 type; 86 }; 87 88 template <typename DefT, typename ScannerT, typename ContextResultT> 89 struct get_subrule_parser_result 90 { 91 typedef typename parser_result<DefT, ScannerT>::type 92 def_result_t; 93 94 typedef typename match_result<ScannerT, ContextResultT>::type 95 context_result_t; 96 97 typedef typename get_result_t<context_result_t, def_result_t>::type 98 type; 99 }; 100 101 template <typename SubruleT, int ID> 102 struct same_subrule_id 103 { 104 BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID)); 105 }; 106 107 template <typename RT, typename ScannerT, int ID> 108 struct parse_subrule 109 { 110 template <typename ListT> 111 static void 112 do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_) 113 { 114 r = list.first.rhs.parse(scan); 115 } 116 117 template <typename ListT> 118 static void 119 do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::false_) 120 { 121 typedef typename ListT::rest_t::first_t subrule_t; 122 mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id; 123 do_parse(r, scan, list.rest, same_id); 124 } 125 126 static void 127 do_(RT& r, ScannerT const& scan) 128 { 129 typedef typename ScannerT::list_t::first_t subrule_t; 130 mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id; 131 do_parse(r, scan, scan.list, same_id); 132 } 133 }; 134 135} 136 137BOOST_SPIRIT_CLASSIC_NAMESPACE_END 138 139}} // namespace boost::spirit::impl 140 141#endif 142 143