/*============================================================================= Copyright (c) 1998-2003 Joel de Guzman http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(BOOST_SPIRIT_RULE_IPP) #define BOOST_SPIRIT_RULE_IPP #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 #include #include #include #include #include #include #include #endif #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 template < BOOST_PP_ENUM_BINARY_PARAMS( BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT ) > struct scanner_list; #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 /////////////////////////////////////////////////////////////////////////// namespace impl { template struct get_param { typedef typename mpl::if_< is_base_and_derived , T0 , typename mpl::if_< is_base_and_derived , T1 , typename mpl::if_< is_base_and_derived , T2 , DefaultT >::type >::type >::type type; }; template struct get_context { typedef typename get_param< parser_context_base, parser_context<>, T0, T1, T2>::type type; }; template struct get_tag { typedef typename get_param< parser_tag_base, parser_address_tag, T0, T1, T2>::type type; }; template struct get_scanner { typedef typename get_param< scanner_base, scanner<>, T0, T1, T2>::type type; }; /////////////////////////////////////////////////////////////////////// // // rule_base class // // The rule_base class implements the basic plumbing for rules // minus the storage mechanism. It is up to the derived class // to actually store the definition somewhere. The rule_base // class assumes that the derived class provides a get() function // that will return a pointer to a parser. The get() function // may return NULL. See rule below for details. // // <<< For framework use only. Not for public consumption. >>> // /////////////////////////////////////////////////////////////////////// template < typename DerivedT // derived class , typename EmbedT // how derived class is embedded , typename T0 = nil_t // see rule class , typename T1 = nil_t // see rule class , typename T2 = nil_t // see rule class > class rule_base; // forward declaration class rule_base_access { #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) public: // YUCK! #else template < typename DerivedT , typename EmbedT , typename T0 , typename T1 , typename T2 > friend class rule_base; #endif template static typename RuleT::abstract_parser_t* get(RuleT const& r) { return r.get(); } }; template < typename DerivedT // derived class , typename EmbedT // how derived class is embedded , typename T0 // see rule class , typename T1 // see rule class , typename T2 // see rule class > class rule_base : public parser , public impl::get_context::type::base_t , public context_aux< typename impl::get_context::type, DerivedT> , public impl::get_tag::type { public: typedef typename impl::get_scanner::type scanner_t; typedef typename impl::get_context::type context_t; typedef typename impl::get_tag::type tag_t; typedef EmbedT embed_t; typedef typename context_t::context_linker_t linked_context_t; typedef typename linked_context_t::attr_t attr_t; template struct result { typedef typename match_result::type type; }; template typename parser_result::type parse(ScannerT const& scan) const { typedef parser_scanner_linker linked_scanner_t; typedef typename parser_result::type result_t; BOOST_SPIRIT_CONTEXT_PARSE( scan, *this, linked_scanner_t, linked_context_t, result_t); } template typename parser_result::type parse_main(ScannerT const& scan) const { typename parser_result::type hit; // MWCW 8.3 needs this cast to be done through a pointer, // not a reference. Otherwise, it will silently construct // a temporary, causing an infinite runtime recursion. DerivedT const* derived_this = static_cast(this); if (rule_base_access::get(*derived_this)) { typename ScannerT::iterator_t s(scan.first); hit = rule_base_access::get(*derived_this) ->do_parse_virtual(scan); scan.group_match(hit, this->id(), s, scan.first); } else { hit = scan.no_match(); } return hit; } }; /////////////////////////////////////////////////////////////////////// // // abstract_parser class // /////////////////////////////////////////////////////////////////////// template struct abstract_parser { abstract_parser() {} virtual ~abstract_parser() {} virtual typename match_result::type do_parse_virtual(ScannerT const& scan) const = 0; virtual abstract_parser* clone() const = 0; }; /////////////////////////////////////////////////////////////////////// // // concrete_parser class // /////////////////////////////////////////////////////////////////////// #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(push) #pragma warning(disable:4512) //assignment operator could not be generated #endif template struct concrete_parser : abstract_parser { concrete_parser(ParserT const& p_) : p(p_) {} virtual ~concrete_parser() {} virtual typename match_result::type do_parse_virtual(ScannerT const& scan) const { return p.parse(scan); } virtual abstract_parser* clone() const { return new concrete_parser(p); } typename ParserT::embed_t p; }; #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(pop) #endif #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 /////////////////////////////////////////////////////////////////////// // // This generates partial specializations for the class // // abstract_parser // // with an increasing number of different ScannerT template parameters // and corresponding do_parse_virtual function declarations for each // of the different required scanner types: // // template // struct abstract_parser, AttrT> // { // abstract_parser() {} // virtual ~abstract_parser() {} // // virtual typename match_result::type // do_parse_virtual(ScannerT0 const &scan) const = 0; // // virtual abstract_parser* // clone() const = 0; // // ... // }; // /////////////////////////////////////////////////////////////////////// #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _) \ virtual typename match_result< \ BOOST_PP_CAT(ScannerT, N), AttrT \ >::type \ do_parse_virtual( \ BOOST_PP_CAT(ScannerT, N) const& scan) const = 0; \ #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _) \ template < \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ typename AttrT \ > \ struct abstract_parser< \ scanner_list< \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ >, \ AttrT \ > \ { \ abstract_parser() {} \ virtual ~abstract_parser() {} \ \ BOOST_PP_REPEAT_ ## z( \ BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _) \ \ virtual abstract_parser* \ clone() const = 0; \ }; \ BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _) #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // This generates partial specializations for the class // // concrete_parser // // with an increasing number of different ScannerT template parameters // and corresponding do_parse_virtual function declarations for each // of the different required scanner types: // // template < // typename ParserT, typename ScannerT0, ..., typename AttrT // > // struct concrete_parser< // ParserT, scanner_list, AttrT // > // : public abstract_parser, AttrT> // { // concrete_parser(ParserT const& p_) : p(p_) {} // virtual ~concrete_parser() {} // // virtual typename match_result::type // do_parse_virtual(ScannerT0 const &scan) const // { return p.parse(scan); } // // virtual abstract_parser, AttrT>* // clone() const // { // return new concrete_parser(p); // } // // ... // // typename ParserT::embed_t p; // }; // /////////////////////////////////////////////////////////////////////// #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _) \ virtual typename match_result< \ BOOST_PP_CAT(ScannerT, N), AttrT \ >::type \ do_parse_virtual( \ BOOST_PP_CAT(ScannerT, N) const& scan) const \ { return p.parse(scan); } \ #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _) \ template < \ typename ParserT, \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ typename AttrT \ > \ struct concrete_parser< \ ParserT, \ scanner_list< \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ >, \ AttrT \ > \ : abstract_parser< \ scanner_list< \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ >, \ AttrT \ > \ { \ concrete_parser(ParserT const& p_) : p(p_) {} \ virtual ~concrete_parser() {} \ \ BOOST_PP_REPEAT_ ## z( \ BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _) \ \ virtual abstract_parser< \ scanner_list< \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ >, \ AttrT \ >* \ clone() const \ { \ return new concrete_parser(p); \ } \ \ typename ParserT::embed_t p; \ }; \ BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _) #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C /////////////////////////////////////////////////////////////////////// #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 } // namespace impl BOOST_SPIRIT_CLASSIC_NAMESPACE_END }} // namespace boost::spirit #endif