Initial Commit
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
/*=============================================================================
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user