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