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