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