304 lines
10 KiB
Plaintext
304 lines
10 KiB
Plaintext
/*=============================================================================
|
|
Copyright (c) 2002-2003 Joel de Guzman
|
|
Copyright (c) 2002-2003 Hartmut Kaiser
|
|
http://spirit.sourceforge.net/
|
|
|
|
Distributed under 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_HPP)
|
|
#define BOOST_SPIRIT_SUBRULE_HPP
|
|
|
|
#include <boost/config.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/mpl/if.hpp>
|
|
#include <boost/mpl/bool.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
|
|
#include <boost/spirit/home/classic/namespace.hpp>
|
|
#include <boost/spirit/home/classic/core/parser.hpp>
|
|
#include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp>
|
|
|
|
#include <boost/spirit/home/classic/core/non_terminal/subrule_fwd.hpp>
|
|
#include <boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp>
|
|
|
|
namespace boost { namespace spirit {
|
|
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// subrules_scanner class
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename ScannerT, typename ListT>
|
|
struct subrules_scanner : public ScannerT
|
|
{
|
|
typedef ScannerT scanner_t;
|
|
typedef ListT list_t;
|
|
typedef subrules_scanner<ScannerT, ListT> self_t;
|
|
|
|
subrules_scanner(ScannerT const& scan, ListT const& list_)
|
|
: ScannerT(scan), list(list_) {}
|
|
|
|
template <typename PoliciesT>
|
|
struct rebind_policies
|
|
{
|
|
typedef typename rebind_scanner_policies<ScannerT, PoliciesT>::type
|
|
rebind_scanner;
|
|
typedef subrules_scanner<rebind_scanner, ListT> type;
|
|
};
|
|
|
|
template <typename PoliciesT>
|
|
subrules_scanner<
|
|
typename rebind_scanner_policies<ScannerT, PoliciesT>::type,
|
|
ListT>
|
|
change_policies(PoliciesT const& policies) const
|
|
{
|
|
typedef subrules_scanner<
|
|
BOOST_DEDUCED_TYPENAME
|
|
rebind_scanner_policies<ScannerT, PoliciesT>::type,
|
|
ListT>
|
|
subrules_scanner_t;
|
|
|
|
return subrules_scanner_t(
|
|
ScannerT::change_policies(policies),
|
|
list);
|
|
}
|
|
|
|
template <typename IteratorT>
|
|
struct rebind_iterator
|
|
{
|
|
typedef typename rebind_scanner_iterator<ScannerT, IteratorT>::type
|
|
rebind_scanner;
|
|
typedef subrules_scanner<rebind_scanner, ListT> type;
|
|
};
|
|
|
|
template <typename IteratorT>
|
|
subrules_scanner<
|
|
typename rebind_scanner_iterator<ScannerT, IteratorT>::type,
|
|
ListT>
|
|
change_iterator(IteratorT const& first, IteratorT const &last) const
|
|
{
|
|
typedef subrules_scanner<
|
|
BOOST_DEDUCED_TYPENAME
|
|
rebind_scanner_iterator<ScannerT, IteratorT>::type,
|
|
ListT>
|
|
subrules_scanner_t;
|
|
|
|
return subrules_scanner_t(
|
|
ScannerT::change_iterator(first, last),
|
|
list);
|
|
}
|
|
|
|
ListT const& list;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// subrule_scanner type computer class
|
|
//
|
|
// This computer ensures that the scanner will not be recursively
|
|
// instantiated if it's not needed.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename ScannerT, typename ListT>
|
|
struct subrules_scanner_finder
|
|
{
|
|
typedef subrules_scanner<ScannerT, ListT> type;
|
|
};
|
|
|
|
template <typename ScannerT, typename ListT>
|
|
struct subrules_scanner_finder<subrules_scanner<ScannerT, ListT>, ListT>
|
|
{
|
|
typedef subrules_scanner<ScannerT, ListT> type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// subrule_list class
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename FirstT, typename RestT>
|
|
struct subrule_list : public parser<subrule_list<FirstT, RestT> >
|
|
{
|
|
typedef subrule_list<FirstT, RestT> self_t;
|
|
typedef FirstT first_t;
|
|
typedef RestT rest_t;
|
|
|
|
subrule_list(FirstT const& first_, RestT const& rest_)
|
|
: first(first_), rest(rest_) {}
|
|
|
|
template <typename ScannerT>
|
|
struct result
|
|
{
|
|
typedef typename parser_result<FirstT, ScannerT>::type type;
|
|
};
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
typedef typename subrules_scanner_finder<ScannerT, self_t>::type
|
|
subrules_scanner_t;
|
|
subrules_scanner_t g_arg(scan, *this);
|
|
return first.start.parse(g_arg);
|
|
}
|
|
|
|
template <int ID, typename DefT, typename ContextT>
|
|
subrule_list<
|
|
FirstT,
|
|
subrule_list<
|
|
subrule_parser<ID, DefT, ContextT>,
|
|
RestT> >
|
|
operator,(subrule_parser<ID, DefT, ContextT> const& rhs_)
|
|
{
|
|
return subrule_list<
|
|
FirstT,
|
|
subrule_list<
|
|
subrule_parser<ID, DefT, ContextT>,
|
|
RestT> >(
|
|
first,
|
|
subrule_list<
|
|
subrule_parser<ID, DefT, ContextT>,
|
|
RestT>(rhs_, rest));
|
|
}
|
|
|
|
FirstT first;
|
|
RestT rest;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// subrule_parser class
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <int ID, typename DefT, typename ContextT>
|
|
struct subrule_parser
|
|
: public parser<subrule_parser<ID, DefT, ContextT> >
|
|
{
|
|
typedef subrule_parser<ID, DefT, ContextT> self_t;
|
|
typedef subrule<ID, ContextT> subrule_t;
|
|
typedef DefT def_t;
|
|
|
|
BOOST_STATIC_CONSTANT(int, id = ID);
|
|
|
|
template <typename ScannerT>
|
|
struct result
|
|
{
|
|
typedef typename
|
|
impl::get_subrule_parser_result<
|
|
DefT, ScannerT, typename subrule_t::attr_t>::type type;
|
|
};
|
|
|
|
subrule_parser(subrule_t const& start_, DefT const& rhs_)
|
|
: rhs(rhs_), start(start_) {}
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
// This will only be called when parsing single subrules.
|
|
typedef subrule_list<self_t, nil_t> list_t;
|
|
typedef subrules_scanner<ScannerT, list_t> scanner_t;
|
|
|
|
list_t list(*this, nil_t());
|
|
scanner_t g_arg(scan, list);
|
|
return start.parse(g_arg);
|
|
}
|
|
|
|
template <int ID2, typename DefT2, typename ContextT2>
|
|
inline subrule_list<
|
|
self_t,
|
|
subrule_list<
|
|
subrule_parser<ID2, DefT2, ContextT2>,
|
|
nil_t> >
|
|
operator,(subrule_parser<ID2, DefT2, ContextT2> const& rhs) const
|
|
{
|
|
return subrule_list<
|
|
self_t,
|
|
subrule_list<
|
|
subrule_parser<ID2, DefT2, ContextT2>,
|
|
nil_t> >(
|
|
*this,
|
|
subrule_list<
|
|
subrule_parser<ID2, DefT2, ContextT2>, nil_t>(
|
|
rhs, nil_t()));
|
|
}
|
|
|
|
typename DefT::embed_t rhs;
|
|
subrule_t const& start;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// subrule class
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <int ID, typename ContextT>
|
|
struct subrule
|
|
: public parser<subrule<ID, ContextT> >
|
|
, public ContextT::base_t
|
|
, public context_aux<ContextT, subrule<ID, ContextT> >
|
|
{
|
|
typedef subrule<ID, ContextT> self_t;
|
|
typedef subrule<ID, ContextT> const& embed_t;
|
|
|
|
typedef typename ContextT::context_linker_t context_t;
|
|
typedef typename context_t::attr_t attr_t;
|
|
|
|
BOOST_STATIC_CONSTANT(int, id = ID);
|
|
|
|
template <typename ScannerT>
|
|
struct result
|
|
{
|
|
typedef typename
|
|
impl::get_subrule_result<ID, ScannerT, attr_t>::type type;
|
|
};
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse_main(ScannerT const& scan) const
|
|
{
|
|
typedef typename parser_result<self_t, ScannerT>::type result_t;
|
|
result_t result_;
|
|
impl::parse_subrule<result_t, ScannerT, ID>::
|
|
do_(result_, scan);
|
|
return result_;
|
|
}
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
typedef typename parser_result<self_t, ScannerT>::type result_t;
|
|
typedef parser_scanner_linker<ScannerT> scanner_t;
|
|
BOOST_SPIRIT_CONTEXT_PARSE(
|
|
scan, *this, scanner_t, context_t, result_t);
|
|
}
|
|
|
|
template <typename DefT>
|
|
subrule_parser<ID, DefT, ContextT>
|
|
operator=(parser<DefT> const& rhs) const
|
|
{
|
|
return subrule_parser<ID, DefT, ContextT>(*this, rhs.derived());
|
|
}
|
|
|
|
private:
|
|
|
|
// assignment of subrules is not allowed. Use subrules
|
|
// with identical IDs if you want to have aliases.
|
|
|
|
subrule& operator=(subrule const&);
|
|
|
|
template <int ID2, typename ContextT2>
|
|
subrule& operator=(subrule<ID2, ContextT2> const&);
|
|
};
|
|
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
|
|
|
}} // namespace BOOST_SPIRIT_CLASSIC_NS
|
|
|
|
#endif
|
|
|