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