1 /*============================================================================= 2 Copyright (c) 2002-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Hartmut Kaiser 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #if !defined(BOOST_SPIRIT_SUBRULE_HPP) 10 #define BOOST_SPIRIT_SUBRULE_HPP 11 12 #include <boost/config.hpp> 13 #include <boost/static_assert.hpp> 14 #include <boost/mpl/if.hpp> 15 #include <boost/mpl/bool.hpp> 16 #include <boost/type_traits/is_same.hpp> 17 18 #include <boost/spirit/home/classic/namespace.hpp> 19 #include <boost/spirit/home/classic/core/parser.hpp> 20 #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp> 21 22 #include <boost/spirit/home/classic/core/non_terminal/subrule_fwd.hpp> 23 #include <boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp> 24 25 namespace boost { namespace spirit { 26 27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 28 29 /////////////////////////////////////////////////////////////////////////// 30 // 31 // subrules_scanner class 32 // 33 /////////////////////////////////////////////////////////////////////////// 34 template <typename ScannerT, typename ListT> 35 struct subrules_scanner : public ScannerT 36 { 37 typedef ScannerT scanner_t; 38 typedef ListT list_t; 39 typedef subrules_scanner<ScannerT, ListT> self_t; 40 subrules_scannerboost::spirit::subrules_scanner41 subrules_scanner(ScannerT const& scan, ListT const& list_) 42 : ScannerT(scan), list(list_) {} 43 44 template <typename PoliciesT> 45 struct rebind_policies 46 { 47 typedef typename rebind_scanner_policies<ScannerT, PoliciesT>::type 48 rebind_scanner; 49 typedef subrules_scanner<rebind_scanner, ListT> type; 50 }; 51 52 template <typename PoliciesT> 53 subrules_scanner< 54 typename rebind_scanner_policies<ScannerT, PoliciesT>::type, 55 ListT> change_policiesboost::spirit::subrules_scanner56 change_policies(PoliciesT const& policies) const 57 { 58 typedef subrules_scanner< 59 BOOST_DEDUCED_TYPENAME 60 rebind_scanner_policies<ScannerT, PoliciesT>::type, 61 ListT> 62 subrules_scanner_t; 63 64 return subrules_scanner_t( 65 ScannerT::change_policies(policies), 66 list); 67 } 68 69 template <typename IteratorT> 70 struct rebind_iterator 71 { 72 typedef typename rebind_scanner_iterator<ScannerT, IteratorT>::type 73 rebind_scanner; 74 typedef subrules_scanner<rebind_scanner, ListT> type; 75 }; 76 77 template <typename IteratorT> 78 subrules_scanner< 79 typename rebind_scanner_iterator<ScannerT, IteratorT>::type, 80 ListT> change_iteratorboost::spirit::subrules_scanner81 change_iterator(IteratorT const& first, IteratorT const &last) const 82 { 83 typedef subrules_scanner< 84 BOOST_DEDUCED_TYPENAME 85 rebind_scanner_iterator<ScannerT, IteratorT>::type, 86 ListT> 87 subrules_scanner_t; 88 89 return subrules_scanner_t( 90 ScannerT::change_iterator(first, last), 91 list); 92 } 93 94 ListT const& list; 95 }; 96 97 /////////////////////////////////////////////////////////////////////////// 98 // 99 // subrule_scanner type computer class 100 // 101 // This computer ensures that the scanner will not be recursively 102 // instantiated if it's not needed. 103 // 104 /////////////////////////////////////////////////////////////////////////// 105 template <typename ScannerT, typename ListT> 106 struct subrules_scanner_finder 107 { 108 typedef subrules_scanner<ScannerT, ListT> type; 109 }; 110 111 template <typename ScannerT, typename ListT> 112 struct subrules_scanner_finder<subrules_scanner<ScannerT, ListT>, ListT> 113 { 114 typedef subrules_scanner<ScannerT, ListT> type; 115 }; 116 117 /////////////////////////////////////////////////////////////////////////// 118 // 119 // subrule_list class 120 // 121 /////////////////////////////////////////////////////////////////////////// 122 template <typename FirstT, typename RestT> 123 struct subrule_list : public parser<subrule_list<FirstT, RestT> > 124 { 125 typedef subrule_list<FirstT, RestT> self_t; 126 typedef FirstT first_t; 127 typedef RestT rest_t; 128 subrule_listboost::spirit::subrule_list129 subrule_list(FirstT const& first_, RestT const& rest_) 130 : first(first_), rest(rest_) {} 131 132 template <typename ScannerT> 133 struct result 134 { 135 typedef typename parser_result<FirstT, ScannerT>::type type; 136 }; 137 138 template <typename ScannerT> 139 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule_list140 parse(ScannerT const& scan) const 141 { 142 typedef typename subrules_scanner_finder<ScannerT, self_t>::type 143 subrules_scanner_t; 144 subrules_scanner_t g_arg(scan, *this); 145 return first.start.parse(g_arg); 146 } 147 148 template <int ID, typename DefT, typename ContextT> 149 subrule_list< 150 FirstT, 151 subrule_list< 152 subrule_parser<ID, DefT, ContextT>, 153 RestT> > operator ,boost::spirit::subrule_list154 operator,(subrule_parser<ID, DefT, ContextT> const& rhs_) 155 { 156 return subrule_list< 157 FirstT, 158 subrule_list< 159 subrule_parser<ID, DefT, ContextT>, 160 RestT> >( 161 first, 162 subrule_list< 163 subrule_parser<ID, DefT, ContextT>, 164 RestT>(rhs_, rest)); 165 } 166 167 FirstT first; 168 RestT rest; 169 }; 170 171 /////////////////////////////////////////////////////////////////////////// 172 // 173 // subrule_parser class 174 // 175 /////////////////////////////////////////////////////////////////////////// 176 template <int ID, typename DefT, typename ContextT> 177 struct subrule_parser 178 : public parser<subrule_parser<ID, DefT, ContextT> > 179 { 180 typedef subrule_parser<ID, DefT, ContextT> self_t; 181 typedef subrule<ID, ContextT> subrule_t; 182 typedef DefT def_t; 183 184 BOOST_STATIC_CONSTANT(int, id = ID); 185 186 template <typename ScannerT> 187 struct result 188 { 189 typedef typename 190 impl::get_subrule_parser_result< 191 DefT, ScannerT, typename subrule_t::attr_t>::type type; 192 }; 193 subrule_parserboost::spirit::subrule_parser194 subrule_parser(subrule_t const& start_, DefT const& rhs_) 195 : rhs(rhs_), start(start_) {} 196 197 template <typename ScannerT> 198 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule_parser199 parse(ScannerT const& scan) const 200 { 201 // This will only be called when parsing single subrules. 202 typedef subrule_list<self_t, nil_t> list_t; 203 typedef subrules_scanner<ScannerT, list_t> scanner_t; 204 205 list_t list(*this, nil_t()); 206 scanner_t g_arg(scan, list); 207 return start.parse(g_arg); 208 } 209 210 template <int ID2, typename DefT2, typename ContextT2> 211 inline subrule_list< 212 self_t, 213 subrule_list< 214 subrule_parser<ID2, DefT2, ContextT2>, 215 nil_t> > operator ,boost::spirit::subrule_parser216 operator,(subrule_parser<ID2, DefT2, ContextT2> const& rhs) const 217 { 218 return subrule_list< 219 self_t, 220 subrule_list< 221 subrule_parser<ID2, DefT2, ContextT2>, 222 nil_t> >( 223 *this, 224 subrule_list< 225 subrule_parser<ID2, DefT2, ContextT2>, nil_t>( 226 rhs, nil_t())); 227 } 228 229 typename DefT::embed_t rhs; 230 subrule_t const& start; 231 }; 232 233 /////////////////////////////////////////////////////////////////////////// 234 // 235 // subrule class 236 // 237 /////////////////////////////////////////////////////////////////////////// 238 template <int ID, typename ContextT> 239 struct subrule 240 : public parser<subrule<ID, ContextT> > 241 , public ContextT::base_t 242 , public context_aux<ContextT, subrule<ID, ContextT> > 243 { 244 typedef subrule<ID, ContextT> self_t; 245 typedef subrule<ID, ContextT> const& embed_t; 246 247 typedef typename ContextT::context_linker_t context_t; 248 typedef typename context_t::attr_t attr_t; 249 250 BOOST_STATIC_CONSTANT(int, id = ID); 251 252 template <typename ScannerT> 253 struct result 254 { 255 typedef typename 256 impl::get_subrule_result<ID, ScannerT, attr_t>::type type; 257 }; 258 259 template <typename ScannerT> 260 typename parser_result<self_t, ScannerT>::type parse_mainboost::spirit::subrule261 parse_main(ScannerT const& scan) const 262 { 263 typedef typename parser_result<self_t, ScannerT>::type result_t; 264 result_t result_; 265 impl::parse_subrule<result_t, ScannerT, ID>:: 266 do_(result_, scan); 267 return result_; 268 } 269 270 template <typename ScannerT> 271 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule272 parse(ScannerT const& scan) const 273 { 274 typedef typename parser_result<self_t, ScannerT>::type result_t; 275 typedef parser_scanner_linker<ScannerT> scanner_t; 276 BOOST_SPIRIT_CONTEXT_PARSE( 277 scan, *this, scanner_t, context_t, result_t); 278 } 279 280 template <typename DefT> 281 subrule_parser<ID, DefT, ContextT> operator =boost::spirit::subrule282 operator=(parser<DefT> const& rhs) const 283 { 284 return subrule_parser<ID, DefT, ContextT>(*this, rhs.derived()); 285 } 286 287 private: 288 289 // assignment of subrules is not allowed. Use subrules 290 // with identical IDs if you want to have aliases. 291 292 subrule& operator=(subrule const&); 293 294 template <int ID2, typename ContextT2> 295 subrule& operator=(subrule<ID2, ContextT2> const&); 296 }; 297 298 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 299 300 }} // namespace BOOST_SPIRIT_CLASSIC_NS 301 302 #endif 303 304