]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
41 | 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> | |
56 | 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> | |
81 | 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 | ||
129 | 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 | |
140 | 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> > | |
154 | 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 | ||
194 | 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 | |
199 | 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> > | |
216 | 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 | |
261 | 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 | |
272 | 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> | |
282 | 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 |