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