1 /*=============================================================================
2     Copyright (c) 2002-2003 Joel de Guzman
3     Copyright (c) 2002-2003 Hartmut Kaiser
4     http://spirit.sourceforge.net/
5 
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
11 
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>
17 
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>
21 
22 #include <boost/spirit/home/classic/core/non_terminal/subrule_fwd.hpp>
23 #include <boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp>
24 
25 namespace boost { namespace spirit {
26 
27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
28 
29     ///////////////////////////////////////////////////////////////////////////
30     //
31     //  subrules_scanner class
32     //
33     ///////////////////////////////////////////////////////////////////////////
34     template <typename ScannerT, typename ListT>
35     struct subrules_scanner : public ScannerT
36     {
37         typedef ScannerT                            scanner_t;
38         typedef ListT                               list_t;
39         typedef subrules_scanner<ScannerT, ListT>   self_t;
40 
subrules_scannerboost::spirit::subrules_scanner41         subrules_scanner(ScannerT const& scan, ListT const& list_)
42         : ScannerT(scan), list(list_) {}
43 
44         template <typename PoliciesT>
45         struct rebind_policies
46         {
47             typedef typename rebind_scanner_policies<ScannerT, PoliciesT>::type
48                 rebind_scanner;
49             typedef subrules_scanner<rebind_scanner, ListT> type;
50         };
51 
52         template <typename PoliciesT>
53         subrules_scanner<
54             typename rebind_scanner_policies<ScannerT, PoliciesT>::type,
55             ListT>
change_policiesboost::spirit::subrules_scanner56         change_policies(PoliciesT const& policies) const
57         {
58             typedef subrules_scanner<
59                 BOOST_DEDUCED_TYPENAME
60                     rebind_scanner_policies<ScannerT, PoliciesT>::type,
61                 ListT>
62             subrules_scanner_t;
63 
64             return subrules_scanner_t(
65                     ScannerT::change_policies(policies),
66                     list);
67         }
68 
69         template <typename IteratorT>
70         struct rebind_iterator
71         {
72             typedef typename rebind_scanner_iterator<ScannerT, IteratorT>::type
73                 rebind_scanner;
74             typedef subrules_scanner<rebind_scanner, ListT> type;
75         };
76 
77         template <typename IteratorT>
78         subrules_scanner<
79             typename rebind_scanner_iterator<ScannerT, IteratorT>::type,
80             ListT>
change_iteratorboost::spirit::subrules_scanner81         change_iterator(IteratorT const& first, IteratorT const &last) const
82         {
83             typedef subrules_scanner<
84                 BOOST_DEDUCED_TYPENAME
85                     rebind_scanner_iterator<ScannerT, IteratorT>::type,
86                 ListT>
87             subrules_scanner_t;
88 
89             return subrules_scanner_t(
90                     ScannerT::change_iterator(first, last),
91                     list);
92         }
93 
94         ListT const& list;
95     };
96 
97     ///////////////////////////////////////////////////////////////////////////
98     //
99     //  subrule_scanner type computer class
100     //
101     //      This computer ensures that the scanner will not be recursively
102     //      instantiated if it's not needed.
103     //
104     ///////////////////////////////////////////////////////////////////////////
105     template <typename ScannerT, typename ListT>
106     struct subrules_scanner_finder
107     {
108           typedef subrules_scanner<ScannerT, ListT> type;
109     };
110 
111     template <typename ScannerT, typename ListT>
112     struct subrules_scanner_finder<subrules_scanner<ScannerT, ListT>, ListT>
113     {
114           typedef subrules_scanner<ScannerT, ListT> type;
115     };
116 
117     ///////////////////////////////////////////////////////////////////////////
118     //
119     //  subrule_list class
120     //
121     ///////////////////////////////////////////////////////////////////////////
122     template <typename FirstT, typename RestT>
123     struct subrule_list : public parser<subrule_list<FirstT, RestT> >
124     {
125         typedef subrule_list<FirstT, RestT> self_t;
126         typedef FirstT                      first_t;
127         typedef RestT                       rest_t;
128 
subrule_listboost::spirit::subrule_list129         subrule_list(FirstT const& first_, RestT const& rest_)
130         : first(first_), rest(rest_) {}
131 
132         template <typename ScannerT>
133         struct result
134         {
135             typedef typename parser_result<FirstT, ScannerT>::type type;
136         };
137 
138         template <typename ScannerT>
139         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::subrule_list140         parse(ScannerT const& scan) const
141         {
142             typedef typename subrules_scanner_finder<ScannerT, self_t>::type
143             subrules_scanner_t;
144             subrules_scanner_t g_arg(scan, *this);
145             return first.start.parse(g_arg);
146         }
147 
148         template <int ID, typename DefT, typename ContextT>
149         subrule_list<
150             FirstT,
151             subrule_list<
152                 subrule_parser<ID, DefT, ContextT>,
153                 RestT> >
operator ,boost::spirit::subrule_list154         operator,(subrule_parser<ID, DefT, ContextT> const& rhs_)
155         {
156             return subrule_list<
157                 FirstT,
158                 subrule_list<
159                     subrule_parser<ID, DefT, ContextT>,
160                     RestT> >(
161                         first,
162                         subrule_list<
163                             subrule_parser<ID, DefT, ContextT>,
164                             RestT>(rhs_, rest));
165         }
166 
167         FirstT first;
168         RestT rest;
169     };
170 
171     ///////////////////////////////////////////////////////////////////////////
172     //
173     //  subrule_parser class
174     //
175     ///////////////////////////////////////////////////////////////////////////
176     template <int ID, typename DefT, typename ContextT>
177     struct subrule_parser
178     : public parser<subrule_parser<ID, DefT, ContextT> >
179     {
180         typedef subrule_parser<ID, DefT, ContextT> self_t;
181         typedef subrule<ID, ContextT> subrule_t;
182         typedef DefT def_t;
183 
184         BOOST_STATIC_CONSTANT(int, id = ID);
185 
186         template <typename ScannerT>
187         struct result
188         {
189             typedef typename
190                 impl::get_subrule_parser_result<
191                     DefT, ScannerT, typename subrule_t::attr_t>::type type;
192         };
193 
subrule_parserboost::spirit::subrule_parser194         subrule_parser(subrule_t const& start_, DefT const& rhs_)
195         : rhs(rhs_), start(start_) {}
196 
197         template <typename ScannerT>
198         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::subrule_parser199         parse(ScannerT const& scan) const
200         {
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;
204 
205             list_t    list(*this, nil_t());
206             scanner_t g_arg(scan, list);
207             return start.parse(g_arg);
208         }
209 
210         template <int ID2, typename DefT2, typename ContextT2>
211         inline subrule_list<
212             self_t,
213             subrule_list<
214                 subrule_parser<ID2, DefT2, ContextT2>,
215                 nil_t> >
operator ,boost::spirit::subrule_parser216         operator,(subrule_parser<ID2, DefT2, ContextT2> const& rhs) const
217         {
218             return subrule_list<
219                 self_t,
220                 subrule_list<
221                     subrule_parser<ID2, DefT2, ContextT2>,
222                     nil_t> >(
223                         *this,
224                         subrule_list<
225                             subrule_parser<ID2, DefT2, ContextT2>, nil_t>(
226                                 rhs, nil_t()));
227         }
228 
229         typename DefT::embed_t rhs;
230         subrule_t const& start;
231     };
232 
233     ///////////////////////////////////////////////////////////////////////////
234     //
235     //  subrule class
236     //
237     ///////////////////////////////////////////////////////////////////////////
238     template <int ID, typename ContextT>
239     struct subrule
240         : public parser<subrule<ID, ContextT> >
241         , public ContextT::base_t
242         , public context_aux<ContextT, subrule<ID, ContextT> >
243     {
244         typedef subrule<ID, ContextT> self_t;
245         typedef subrule<ID, ContextT> const&  embed_t;
246 
247         typedef typename ContextT::context_linker_t context_t;
248         typedef typename context_t::attr_t attr_t;
249 
250         BOOST_STATIC_CONSTANT(int, id = ID);
251 
252         template <typename ScannerT>
253         struct result
254         {
255             typedef typename
256                 impl::get_subrule_result<ID, ScannerT, attr_t>::type type;
257         };
258 
259         template <typename ScannerT>
260         typename parser_result<self_t, ScannerT>::type
parse_mainboost::spirit::subrule261         parse_main(ScannerT const& scan) const
262         {
263             typedef typename parser_result<self_t, ScannerT>::type result_t;
264             result_t result_;
265             impl::parse_subrule<result_t, ScannerT, ID>::
266                 do_(result_, scan);
267             return result_;
268         }
269 
270         template <typename ScannerT>
271         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::subrule272         parse(ScannerT const& scan) const
273         {
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);
278         }
279 
280         template <typename DefT>
281         subrule_parser<ID, DefT, ContextT>
operator =boost::spirit::subrule282         operator=(parser<DefT> const& rhs) const
283         {
284             return subrule_parser<ID, DefT, ContextT>(*this, rhs.derived());
285         }
286 
287     private:
288 
289         //  assignment of subrules is not allowed. Use subrules
290         //  with identical IDs if you want to have aliases.
291 
292         subrule& operator=(subrule const&);
293 
294         template <int ID2, typename ContextT2>
295         subrule& operator=(subrule<ID2, ContextT2> const&);
296     };
297 
298 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
299 
300 }} // namespace BOOST_SPIRIT_CLASSIC_NS
301 
302 #endif
303 
304