/*============================================================================= | |
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 |