1 /*=============================================================================
2 Copyright (c) 2002-2003 Joel de Guzman
3 Copyright (c) 2002-2003 Hartmut Kaiser
4 http://spirit.sourceforge.net/
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_SUBRULE_HPP)
10 #define BOOST_SPIRIT_SUBRULE_HPP
12 #include <boost/config.hpp>
13 #include <boost/static_assert.hpp>
14 #include <boost/mpl/if.hpp>
15 #include <boost/mpl/bool.hpp>
16 #include <boost/type_traits/is_same.hpp>
18 #include <boost/spirit/home/classic/namespace.hpp>
19 #include <boost/spirit/home/classic/core/parser.hpp>
20 #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp>
22 #include <boost/spirit/home/classic/core/non_terminal/subrule_fwd.hpp>
23 #include <boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp>
25 namespace boost { namespace spirit {
27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
29 ///////////////////////////////////////////////////////////////////////////
31 // subrules_scanner class
33 ///////////////////////////////////////////////////////////////////////////
34 template <typename ScannerT, typename ListT>
35 struct subrules_scanner : public ScannerT
37 typedef ScannerT scanner_t;
39 typedef subrules_scanner<ScannerT, ListT> self_t;
41 subrules_scanner(ScannerT const& scan, ListT const& list_)
42 : ScannerT(scan), list(list_) {}
44 template <typename PoliciesT>
45 struct rebind_policies
47 typedef typename rebind_scanner_policies<ScannerT, PoliciesT>::type
49 typedef subrules_scanner<rebind_scanner, ListT> type;
52 template <typename PoliciesT>
54 typename rebind_scanner_policies<ScannerT, PoliciesT>::type,
56 change_policies(PoliciesT const& policies) const
58 typedef subrules_scanner<
59 BOOST_DEDUCED_TYPENAME
60 rebind_scanner_policies<ScannerT, PoliciesT>::type,
64 return subrules_scanner_t(
65 ScannerT::change_policies(policies),
69 template <typename IteratorT>
70 struct rebind_iterator
72 typedef typename rebind_scanner_iterator<ScannerT, IteratorT>::type
74 typedef subrules_scanner<rebind_scanner, ListT> type;
77 template <typename IteratorT>
79 typename rebind_scanner_iterator<ScannerT, IteratorT>::type,
81 change_iterator(IteratorT const& first, IteratorT const &last) const
83 typedef subrules_scanner<
84 BOOST_DEDUCED_TYPENAME
85 rebind_scanner_iterator<ScannerT, IteratorT>::type,
89 return subrules_scanner_t(
90 ScannerT::change_iterator(first, last),
97 ///////////////////////////////////////////////////////////////////////////
99 // subrule_scanner type computer class
101 // This computer ensures that the scanner will not be recursively
102 // instantiated if it's not needed.
104 ///////////////////////////////////////////////////////////////////////////
105 template <typename ScannerT, typename ListT>
106 struct subrules_scanner_finder
108 typedef subrules_scanner<ScannerT, ListT> type;
111 template <typename ScannerT, typename ListT>
112 struct subrules_scanner_finder<subrules_scanner<ScannerT, ListT>, ListT>
114 typedef subrules_scanner<ScannerT, ListT> type;
117 ///////////////////////////////////////////////////////////////////////////
119 // subrule_list class
121 ///////////////////////////////////////////////////////////////////////////
122 template <typename FirstT, typename RestT>
123 struct subrule_list : public parser<subrule_list<FirstT, RestT> >
125 typedef subrule_list<FirstT, RestT> self_t;
126 typedef FirstT first_t;
127 typedef RestT rest_t;
129 subrule_list(FirstT const& first_, RestT const& rest_)
130 : first(first_), rest(rest_) {}
132 template <typename ScannerT>
135 typedef typename parser_result<FirstT, ScannerT>::type type;
138 template <typename ScannerT>
139 typename parser_result<self_t, ScannerT>::type
140 parse(ScannerT const& scan) const
142 typedef typename subrules_scanner_finder<ScannerT, self_t>::type
144 subrules_scanner_t g_arg(scan, *this);
145 return first.start.parse(g_arg);
148 template <int ID, typename DefT, typename ContextT>
152 subrule_parser<ID, DefT, ContextT>,
154 operator,(subrule_parser<ID, DefT, ContextT> const& rhs_)
159 subrule_parser<ID, DefT, ContextT>,
163 subrule_parser<ID, DefT, ContextT>,
171 ///////////////////////////////////////////////////////////////////////////
173 // subrule_parser class
175 ///////////////////////////////////////////////////////////////////////////
176 template <int ID, typename DefT, typename ContextT>
177 struct subrule_parser
178 : public parser<subrule_parser<ID, DefT, ContextT> >
180 typedef subrule_parser<ID, DefT, ContextT> self_t;
181 typedef subrule<ID, ContextT> subrule_t;
184 BOOST_STATIC_CONSTANT(int, id = ID);
186 template <typename ScannerT>
190 impl::get_subrule_parser_result<
191 DefT, ScannerT, typename subrule_t::attr_t>::type type;
194 subrule_parser(subrule_t const& start_, DefT const& rhs_)
195 : rhs(rhs_), start(start_) {}
197 template <typename ScannerT>
198 typename parser_result<self_t, ScannerT>::type
199 parse(ScannerT const& scan) const
201 // This will only be called when parsing single subrules.
202 typedef subrule_list<self_t, nil_t> list_t;
203 typedef subrules_scanner<ScannerT, list_t> scanner_t;
205 list_t list(*this, nil_t());
206 scanner_t g_arg(scan, list);
207 return start.parse(g_arg);
210 template <int ID2, typename DefT2, typename ContextT2>
214 subrule_parser<ID2, DefT2, ContextT2>,
216 operator,(subrule_parser<ID2, DefT2, ContextT2> const& rhs) const
221 subrule_parser<ID2, DefT2, ContextT2>,
225 subrule_parser<ID2, DefT2, ContextT2>, nil_t>(
229 typename DefT::embed_t rhs;
230 subrule_t const& start;
233 ///////////////////////////////////////////////////////////////////////////
237 ///////////////////////////////////////////////////////////////////////////
238 template <int ID, typename ContextT>
240 : public parser<subrule<ID, ContextT> >
241 , public ContextT::base_t
242 , public context_aux<ContextT, subrule<ID, ContextT> >
244 typedef subrule<ID, ContextT> self_t;
245 typedef subrule<ID, ContextT> const& embed_t;
247 typedef typename ContextT::context_linker_t context_t;
248 typedef typename context_t::attr_t attr_t;
250 BOOST_STATIC_CONSTANT(int, id = ID);
252 template <typename ScannerT>
256 impl::get_subrule_result<ID, ScannerT, attr_t>::type type;
259 template <typename ScannerT>
260 typename parser_result<self_t, ScannerT>::type
261 parse_main(ScannerT const& scan) const
263 typedef typename parser_result<self_t, ScannerT>::type result_t;
265 impl::parse_subrule<result_t, ScannerT, ID>::
270 template <typename ScannerT>
271 typename parser_result<self_t, ScannerT>::type
272 parse(ScannerT const& scan) const
274 typedef typename parser_result<self_t, ScannerT>::type result_t;
275 typedef parser_scanner_linker<ScannerT> scanner_t;
276 BOOST_SPIRIT_CONTEXT_PARSE(
277 scan, *this, scanner_t, context_t, result_t);
280 template <typename DefT>
281 subrule_parser<ID, DefT, ContextT>
282 operator=(parser<DefT> const& rhs) const
284 return subrule_parser<ID, DefT, ContextT>(*this, rhs.derived());
289 // assignment of subrules is not allowed. Use subrules
290 // with identical IDs if you want to have aliases.
292 subrule& operator=(subrule const&);
294 template <int ID2, typename ContextT2>
295 subrule& operator=(subrule<ID2, ContextT2> const&);
298 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
300 }} // namespace BOOST_SPIRIT_CLASSIC_NS