| /*============================================================================= |
| 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 <boost/preprocessor/repeat.hpp> |
| #include <boost/preprocessor/repeat_from_to.hpp> |
| #include <boost/preprocessor/enum_params.hpp> |
| #include <boost/preprocessor/enum_params_with_defaults.hpp> |
| #include <boost/preprocessor/facilities/intercept.hpp> |
| #include <boost/preprocessor/inc.hpp> |
| #include <boost/preprocessor/cat.hpp> |
| #endif |
| |
| #include <boost/spirit/home/classic/core/parser.hpp> |
| #include <boost/spirit/home/classic/core/scanner/scanner.hpp> |
| #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp> |
| #include <boost/spirit/home/classic/core/non_terminal/parser_id.hpp> |
| #include <boost/type_traits/is_base_and_derived.hpp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| 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 <typename BaseT, typename DefaultT |
| , typename T0, typename T1, typename T2> |
| struct get_param |
| { |
| typedef typename mpl::if_< |
| is_base_and_derived<BaseT, T0> |
| , T0 |
| , typename mpl::if_< |
| is_base_and_derived<BaseT, T1> |
| , T1 |
| , typename mpl::if_< |
| is_base_and_derived<BaseT, T2> |
| , T2 |
| , DefaultT |
| >::type |
| >::type |
| >::type type; |
| }; |
| |
| template <typename T0, typename T1, typename T2> |
| struct get_context |
| { |
| typedef typename get_param< |
| parser_context_base, parser_context<>, T0, T1, T2>::type |
| type; |
| }; |
| |
| template <typename T0, typename T1, typename T2> |
| struct get_tag |
| { |
| typedef typename get_param< |
| parser_tag_base, parser_address_tag, T0, T1, T2>::type |
| type; |
| }; |
| |
| template <typename T0, typename T1, typename T2> |
| 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 <typename RuleT> |
| 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<DerivedT> |
| , public impl::get_context<T0, T1, T2>::type::base_t |
| , public context_aux< |
| typename impl::get_context<T0, T1, T2>::type, DerivedT> |
| , public impl::get_tag<T0, T1, T2>::type |
| { |
| public: |
| |
| typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t; |
| typedef typename impl::get_context<T0, T1, T2>::type context_t; |
| typedef typename impl::get_tag<T0, T1, T2>::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 <typename ScannerT> |
| struct result |
| { |
| typedef typename match_result<ScannerT, attr_t>::type type; |
| }; |
| |
| template <typename ScannerT> |
| typename parser_result<DerivedT, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| typedef parser_scanner_linker<ScannerT> linked_scanner_t; |
| typedef typename parser_result<DerivedT, ScannerT>::type result_t; |
| BOOST_SPIRIT_CONTEXT_PARSE( |
| scan, *this, linked_scanner_t, linked_context_t, result_t); |
| } |
| |
| template <typename ScannerT> |
| typename parser_result<DerivedT, ScannerT>::type |
| parse_main(ScannerT const& scan) const |
| { |
| typename parser_result<DerivedT, ScannerT>::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<DerivedT const*>(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 <typename ScannerT, typename AttrT> |
| struct abstract_parser |
| { |
| abstract_parser() {} |
| virtual ~abstract_parser() {} |
| |
| virtual typename match_result<ScannerT, AttrT>::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 <typename ParserT, typename ScannerT, typename AttrT> |
| struct concrete_parser : abstract_parser<ScannerT, AttrT> |
| { |
| concrete_parser(ParserT const& p_) : p(p_) {} |
| virtual ~concrete_parser() {} |
| |
| virtual typename match_result<ScannerT, AttrT>::type |
| do_parse_virtual(ScannerT const& scan) const |
| { |
| return p.parse(scan); |
| } |
| |
| virtual abstract_parser<ScannerT, AttrT>* |
| 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 <typename ScannerT0, ..., typename AttrT> |
| // struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT> |
| // { |
| // abstract_parser() {} |
| // virtual ~abstract_parser() {} |
| // |
| // virtual typename match_result<ScannerT0, AttrT>::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<ScannerT0, ...>, AttrT |
| // > |
| // : public abstract_parser<scanner_list<ScannerT0, ...>, AttrT> |
| // { |
| // concrete_parser(ParserT const& p_) : p(p_) {} |
| // virtual ~concrete_parser() {} |
| // |
| // virtual typename match_result<ScannerT0, AttrT>::type |
| // do_parse_virtual(ScannerT0 const &scan) const |
| // { return p.parse(scan); } |
| // |
| // virtual abstract_parser<scanner_list<ScannerT0, ...>, 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 |