1/*============================================================================= 2 Copyright (c) 1998-2003 Joel de Guzman 3 http://spirit.sourceforge.net/ 4 5 Use, modification and distribution is subject to the Boost Software 6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 http://www.boost.org/LICENSE_1_0.txt) 8=============================================================================*/ 9#if !defined(BOOST_SPIRIT_RULE_IPP) 10#define BOOST_SPIRIT_RULE_IPP 11 12#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 13#include <boost/preprocessor/repeat.hpp> 14#include <boost/preprocessor/repeat_from_to.hpp> 15#include <boost/preprocessor/enum_params.hpp> 16#include <boost/preprocessor/enum_params_with_defaults.hpp> 17#include <boost/preprocessor/facilities/intercept.hpp> 18#include <boost/preprocessor/inc.hpp> 19#include <boost/preprocessor/cat.hpp> 20#endif 21 22#include <boost/spirit/home/classic/core/parser.hpp> 23#include <boost/spirit/home/classic/core/scanner/scanner.hpp> 24#include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp> 25#include <boost/spirit/home/classic/core/non_terminal/parser_id.hpp> 26#include <boost/type_traits/is_base_and_derived.hpp> 27#include <boost/mpl/if.hpp> 28 29/////////////////////////////////////////////////////////////////////////////// 30namespace boost { namespace spirit { 31 32BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 33 34#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 35 36 template < 37 BOOST_PP_ENUM_BINARY_PARAMS( 38 BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, 39 typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT 40 ) 41 > 42 struct scanner_list; 43 44#endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 45 46 /////////////////////////////////////////////////////////////////////////// 47 namespace impl 48 { 49 template <typename BaseT, typename DefaultT 50 , typename T0, typename T1, typename T2> 51 struct get_param 52 { 53 typedef typename mpl::if_< 54 is_base_and_derived<BaseT, T0> 55 , T0 56 , typename mpl::if_< 57 is_base_and_derived<BaseT, T1> 58 , T1 59 , typename mpl::if_< 60 is_base_and_derived<BaseT, T2> 61 , T2 62 , DefaultT 63 >::type 64 >::type 65 >::type type; 66 }; 67 68 template <typename T0, typename T1, typename T2> 69 struct get_context 70 { 71 typedef typename get_param< 72 parser_context_base, parser_context<>, T0, T1, T2>::type 73 type; 74 }; 75 76 template <typename T0, typename T1, typename T2> 77 struct get_tag 78 { 79 typedef typename get_param< 80 parser_tag_base, parser_address_tag, T0, T1, T2>::type 81 type; 82 }; 83 84 template <typename T0, typename T1, typename T2> 85 struct get_scanner 86 { 87 typedef typename get_param< 88 scanner_base, scanner<>, T0, T1, T2>::type 89 type; 90 }; 91 92 /////////////////////////////////////////////////////////////////////// 93 // 94 // rule_base class 95 // 96 // The rule_base class implements the basic plumbing for rules 97 // minus the storage mechanism. It is up to the derived class 98 // to actually store the definition somewhere. The rule_base 99 // class assumes that the derived class provides a get() function 100 // that will return a pointer to a parser. The get() function 101 // may return NULL. See rule below for details. 102 // 103 // <<< For framework use only. Not for public consumption. >>> 104 // 105 /////////////////////////////////////////////////////////////////////// 106 template < 107 typename DerivedT // derived class 108 , typename EmbedT // how derived class is embedded 109 , typename T0 = nil_t // see rule class 110 , typename T1 = nil_t // see rule class 111 , typename T2 = nil_t // see rule class 112 > 113 class rule_base; // forward declaration 114 115 class rule_base_access 116 { 117#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) 118 public: // YUCK! 119#else 120 template < 121 typename DerivedT 122 , typename EmbedT 123 , typename T0 124 , typename T1 125 , typename T2 126 > 127 friend class rule_base; 128#endif 129 template <typename RuleT> 130 static typename RuleT::abstract_parser_t* 131 get(RuleT const& r) 132 { 133 return r.get(); 134 } 135 }; 136 137 template < 138 typename DerivedT // derived class 139 , typename EmbedT // how derived class is embedded 140 , typename T0 // see rule class 141 , typename T1 // see rule class 142 , typename T2 // see rule class 143 > 144 class rule_base 145 : public parser<DerivedT> 146 , public impl::get_context<T0, T1, T2>::type::base_t 147 , public context_aux< 148 typename impl::get_context<T0, T1, T2>::type, DerivedT> 149 , public impl::get_tag<T0, T1, T2>::type 150 { 151 public: 152 153 typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t; 154 typedef typename impl::get_context<T0, T1, T2>::type context_t; 155 typedef typename impl::get_tag<T0, T1, T2>::type tag_t; 156 157 typedef EmbedT embed_t; 158 typedef typename context_t::context_linker_t linked_context_t; 159 typedef typename linked_context_t::attr_t attr_t; 160 161 template <typename ScannerT> 162 struct result 163 { 164 typedef typename match_result<ScannerT, attr_t>::type type; 165 }; 166 167 template <typename ScannerT> 168 typename parser_result<DerivedT, ScannerT>::type 169 parse(ScannerT const& scan) const 170 { 171 typedef parser_scanner_linker<ScannerT> linked_scanner_t; 172 typedef typename parser_result<DerivedT, ScannerT>::type result_t; 173 BOOST_SPIRIT_CONTEXT_PARSE( 174 scan, *this, linked_scanner_t, linked_context_t, result_t); 175 } 176 177 template <typename ScannerT> 178 typename parser_result<DerivedT, ScannerT>::type 179 parse_main(ScannerT const& scan) const 180 { 181 typename parser_result<DerivedT, ScannerT>::type hit; 182 183 // MWCW 8.3 needs this cast to be done through a pointer, 184 // not a reference. Otherwise, it will silently construct 185 // a temporary, causing an infinite runtime recursion. 186 DerivedT const* derived_this = static_cast<DerivedT const*>(this); 187 188 if (rule_base_access::get(*derived_this)) 189 { 190 typename ScannerT::iterator_t s(scan.first); 191 hit = rule_base_access::get(*derived_this) 192 ->do_parse_virtual(scan); 193 scan.group_match(hit, this->id(), s, scan.first); 194 } 195 else 196 { 197 hit = scan.no_match(); 198 } 199 return hit; 200 } 201 }; 202 203 /////////////////////////////////////////////////////////////////////// 204 // 205 // abstract_parser class 206 // 207 /////////////////////////////////////////////////////////////////////// 208 template <typename ScannerT, typename AttrT> 209 struct abstract_parser 210 { 211 abstract_parser() {} 212 virtual ~abstract_parser() {} 213 214 virtual typename match_result<ScannerT, AttrT>::type 215 do_parse_virtual(ScannerT const& scan) const = 0; 216 217 virtual abstract_parser* 218 clone() const = 0; 219 }; 220 221 /////////////////////////////////////////////////////////////////////// 222 // 223 // concrete_parser class 224 // 225 /////////////////////////////////////////////////////////////////////// 226#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 227#pragma warning(push) 228#pragma warning(disable:4512) //assignment operator could not be generated 229#endif 230 231 template <typename ParserT, typename ScannerT, typename AttrT> 232 struct concrete_parser : abstract_parser<ScannerT, AttrT> 233 { 234 concrete_parser(ParserT const& p_) : p(p_) {} 235 ~concrete_parser() BOOST_OVERRIDE {} 236 237 typename match_result<ScannerT, AttrT>::type 238 do_parse_virtual(ScannerT const& scan) const BOOST_OVERRIDE 239 { 240 return p.parse(scan); 241 } 242 243 abstract_parser<ScannerT, AttrT>* 244 clone() const BOOST_OVERRIDE 245 { 246 return new concrete_parser(p); 247 } 248 249 typename ParserT::embed_t p; 250 }; 251 252#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 253#pragma warning(pop) 254#endif 255 256#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 257 258 /////////////////////////////////////////////////////////////////////// 259 // 260 // This generates partial specializations for the class 261 // 262 // abstract_parser 263 // 264 // with an increasing number of different ScannerT template parameters 265 // and corresponding do_parse_virtual function declarations for each 266 // of the different required scanner types: 267 // 268 // template <typename ScannerT0, ..., typename AttrT> 269 // struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT> 270 // { 271 // abstract_parser() {} 272 // virtual ~abstract_parser() {} 273 // 274 // virtual typename match_result<ScannerT0, AttrT>::type 275 // do_parse_virtual(ScannerT0 const &scan) const = 0; 276 // 277 // virtual abstract_parser* 278 // clone() const = 0; 279 // 280 // ... 281 // }; 282 // 283 /////////////////////////////////////////////////////////////////////// 284 #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _) \ 285 virtual typename match_result< \ 286 BOOST_PP_CAT(ScannerT, N), AttrT \ 287 >::type \ 288 do_parse_virtual( \ 289 BOOST_PP_CAT(ScannerT, N) const& scan) const = 0; \ 290 291 #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _) \ 292 template < \ 293 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ 294 typename AttrT \ 295 > \ 296 struct abstract_parser< \ 297 scanner_list< \ 298 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ 299 >, \ 300 AttrT \ 301 > \ 302 { \ 303 abstract_parser() {} \ 304 virtual ~abstract_parser() {} \ 305 \ 306 BOOST_PP_REPEAT_ ## z( \ 307 BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _) \ 308 \ 309 virtual abstract_parser* \ 310 clone() const = 0; \ 311 }; \ 312 313 BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, 314 BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _) 315 316 #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A 317 #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS 318 /////////////////////////////////////////////////////////////////////// 319 320 /////////////////////////////////////////////////////////////////////// 321 // 322 // This generates partial specializations for the class 323 // 324 // concrete_parser 325 // 326 // with an increasing number of different ScannerT template parameters 327 // and corresponding do_parse_virtual function declarations for each 328 // of the different required scanner types: 329 // 330 // template < 331 // typename ParserT, typename ScannerT0, ..., typename AttrT 332 // > 333 // struct concrete_parser< 334 // ParserT, scanner_list<ScannerT0, ...>, AttrT 335 // > 336 // : public abstract_parser<scanner_list<ScannerT0, ...>, AttrT> 337 // { 338 // concrete_parser(ParserT const& p_) : p(p_) {} 339 // virtual ~concrete_parser() {} 340 // 341 // virtual typename match_result<ScannerT0, AttrT>::type 342 // do_parse_virtual(ScannerT0 const &scan) const 343 // { return p.parse(scan); } 344 // 345 // virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>* 346 // clone() const 347 // { 348 // return new concrete_parser(p); 349 // } 350 // 351 // ... 352 // 353 // typename ParserT::embed_t p; 354 // }; 355 // 356 /////////////////////////////////////////////////////////////////////// 357 #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _) \ 358 virtual typename match_result< \ 359 BOOST_PP_CAT(ScannerT, N), AttrT \ 360 >::type \ 361 do_parse_virtual( \ 362 BOOST_PP_CAT(ScannerT, N) const& scan) const \ 363 { return p.parse(scan); } \ 364 365 #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _) \ 366 template < \ 367 typename ParserT, \ 368 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ 369 typename AttrT \ 370 > \ 371 struct concrete_parser< \ 372 ParserT, \ 373 scanner_list< \ 374 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ 375 >, \ 376 AttrT \ 377 > \ 378 : abstract_parser< \ 379 scanner_list< \ 380 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ 381 >, \ 382 AttrT \ 383 > \ 384 { \ 385 concrete_parser(ParserT const& p_) : p(p_) {} \ 386 virtual ~concrete_parser() {} \ 387 \ 388 BOOST_PP_REPEAT_ ## z( \ 389 BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _) \ 390 \ 391 virtual abstract_parser< \ 392 scanner_list< \ 393 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ 394 >, \ 395 AttrT \ 396 >* \ 397 clone() const \ 398 { \ 399 return new concrete_parser(p); \ 400 } \ 401 \ 402 typename ParserT::embed_t p; \ 403 }; \ 404 405 BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, 406 BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _) 407 408 #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS 409 #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C 410 /////////////////////////////////////////////////////////////////////// 411 412#endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 413 414 } // namespace impl 415 416BOOST_SPIRIT_CLASSIC_NAMESPACE_END 417 418}} // namespace boost::spirit 419 420#endif 421