143 lines
4.5 KiB
Plaintext
143 lines
4.5 KiB
Plaintext
|
/*=============================================================================
|
||
|
Copyright (c) 2002-2003 Joel de Guzman
|
||
|
Copyright (c) 2002-2003 Hartmut Kaiser
|
||
|
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_SUBRULE_IPP)
|
||
|
#define BOOST_SPIRIT_SUBRULE_IPP
|
||
|
|
||
|
#include <boost/mpl/if.hpp>
|
||
|
|
||
|
namespace boost { namespace spirit {
|
||
|
|
||
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
||
|
|
||
|
template <typename FirstT, typename RestT>
|
||
|
struct subrule_list;
|
||
|
|
||
|
template <int ID, typename DefT, typename ContextT>
|
||
|
struct subrule_parser;
|
||
|
|
||
|
namespace impl {
|
||
|
|
||
|
|
||
|
template <int N, typename ListT>
|
||
|
struct get_subrule
|
||
|
{
|
||
|
// First case. ListT is non-empty but the list's
|
||
|
// first item does not have the ID we are looking for.
|
||
|
|
||
|
typedef typename get_subrule<N, typename ListT::rest_t>::type type;
|
||
|
};
|
||
|
|
||
|
template <int ID, typename DefT, typename ContextT, typename RestT>
|
||
|
struct get_subrule<
|
||
|
ID,
|
||
|
subrule_list<
|
||
|
subrule_parser<ID, DefT, ContextT>,
|
||
|
RestT> >
|
||
|
{
|
||
|
// Second case. ListT is non-empty and the list's
|
||
|
// first item has the ID we are looking for.
|
||
|
|
||
|
typedef DefT type;
|
||
|
};
|
||
|
|
||
|
template <int ID>
|
||
|
struct get_subrule<ID, nil_t>
|
||
|
{
|
||
|
// Third case. ListT is empty
|
||
|
typedef nil_t type;
|
||
|
};
|
||
|
|
||
|
|
||
|
template <typename T1, typename T2>
|
||
|
struct get_result_t {
|
||
|
|
||
|
// If the result type dictated by the context is nil_t (no closures
|
||
|
// present), then the whole subrule_parser return type is equal to
|
||
|
// the return type of the right hand side of this subrule_parser,
|
||
|
// otherwise it is equal to the dictated return value.
|
||
|
|
||
|
typedef typename mpl::if_<
|
||
|
boost::is_same<T1, nil_t>, T2, T1
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
template <int ID, typename ScannerT, typename ContextResultT>
|
||
|
struct get_subrule_result
|
||
|
{
|
||
|
typedef typename
|
||
|
impl::get_subrule<ID, typename ScannerT::list_t>::type
|
||
|
parser_t;
|
||
|
|
||
|
typedef typename parser_result<parser_t, ScannerT>::type
|
||
|
def_result_t;
|
||
|
|
||
|
typedef typename match_result<ScannerT, ContextResultT>::type
|
||
|
context_result_t;
|
||
|
|
||
|
typedef typename get_result_t<context_result_t, def_result_t>::type
|
||
|
type;
|
||
|
};
|
||
|
|
||
|
template <typename DefT, typename ScannerT, typename ContextResultT>
|
||
|
struct get_subrule_parser_result
|
||
|
{
|
||
|
typedef typename parser_result<DefT, ScannerT>::type
|
||
|
def_result_t;
|
||
|
|
||
|
typedef typename match_result<ScannerT, ContextResultT>::type
|
||
|
context_result_t;
|
||
|
|
||
|
typedef typename get_result_t<context_result_t, def_result_t>::type
|
||
|
type;
|
||
|
};
|
||
|
|
||
|
template <typename SubruleT, int ID>
|
||
|
struct same_subrule_id
|
||
|
{
|
||
|
BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID));
|
||
|
};
|
||
|
|
||
|
template <typename RT, typename ScannerT, int ID>
|
||
|
struct parse_subrule
|
||
|
{
|
||
|
template <typename ListT>
|
||
|
static void
|
||
|
do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_)
|
||
|
{
|
||
|
r = list.first.rhs.parse(scan);
|
||
|
}
|
||
|
|
||
|
template <typename ListT>
|
||
|
static void
|
||
|
do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::false_)
|
||
|
{
|
||
|
typedef typename ListT::rest_t::first_t subrule_t;
|
||
|
mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
|
||
|
do_parse(r, scan, list.rest, same_id);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
do_(RT& r, ScannerT const& scan)
|
||
|
{
|
||
|
typedef typename ScannerT::list_t::first_t subrule_t;
|
||
|
mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
|
||
|
do_parse(r, scan, scan.list, same_id);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
||
|
|
||
|
}} // namespace boost::spirit::impl
|
||
|
|
||
|
#endif
|
||
|
|