📄 rule.ipp
字号:
/*=============================================================================
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/core/parser.hpp>
#include <boost/spirit/core/scanner/scanner.hpp>
#include <boost/spirit/core/non_terminal/parser_context.hpp>
#include <boost/spirit/core/non_terminal/parser_id.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
#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
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -