]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | http://spirit.sourceforge.net/ | |
4 | ||
5 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | =============================================================================*/ | |
8 | #ifndef BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM | |
9 | #define BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM | |
10 | ||
11 | #if defined(_MSC_VER) | |
12 | #pragma once | |
13 | #endif | |
14 | ||
15 | #include <boost/spirit/include/phoenix_core.hpp> | |
16 | #include <boost/proto/proto.hpp> | |
17 | #include <boost/spirit/home/support/detail/make_cons.hpp> | |
18 | #include <boost/spirit/home/support/modify.hpp> | |
19 | ||
20 | namespace boost { namespace spirit | |
21 | { | |
22 | // There is no real "component" class. Each domain is responsible | |
23 | // for creating its own components. You need to specialize this for | |
24 | // each component in your domain. Use this as a guide. | |
25 | ||
26 | template <typename Domain, typename Tag, typename Enable = void> | |
27 | struct make_component | |
28 | { | |
29 | template <typename Sig> | |
30 | struct result; | |
31 | ||
32 | template <typename This, typename Elements, typename Modifiers> | |
33 | struct result<This(Elements, Modifiers)>; | |
34 | ||
35 | template <typename Elements, typename Modifiers> | |
36 | typename result<make_component(Elements, Modifiers)>::type | |
37 | operator()(Elements const& elements, Modifiers const& modifiers) const; | |
38 | }; | |
39 | ||
40 | namespace tag | |
41 | { | |
42 | // Normally, we use proto tags as-is to distinguish operators. | |
43 | // The special case is proto::tag::subscript. Spirit uses this | |
44 | // as either sementic actions or directives. To distinguish between | |
45 | // the two, we use these special tags below. | |
46 | ||
47 | struct directive; | |
48 | struct action; | |
49 | } | |
50 | ||
51 | template <typename Domain, typename T, typename Enable = void> | |
52 | struct flatten_tree; | |
53 | }} | |
54 | ||
55 | namespace boost { namespace spirit { namespace detail | |
56 | { | |
57 | template <typename Expr, typename State, typename Data, typename Domain> | |
58 | struct make_terminal_impl | |
59 | : proto::transform_impl<Expr, State, Data> | |
60 | { | |
61 | typedef typename | |
62 | proto::result_of::value<Expr>::type | |
63 | value; | |
64 | ||
65 | typedef typename result_of::make_cons<value>::type elements; | |
66 | ||
67 | typedef | |
68 | make_component<Domain, proto::tag::terminal> | |
69 | make_component_; | |
70 | ||
71 | typedef typename | |
72 | make_component_::template | |
73 | result<make_component_(elements, Data)>::type | |
74 | result_type; | |
75 | ||
76 | result_type operator()( | |
77 | typename make_terminal_impl::expr_param expr | |
78 | , typename make_terminal_impl::state_param /*state*/ | |
79 | , typename make_terminal_impl::data_param data | |
80 | ) const | |
81 | { | |
82 | return typename make_terminal_impl::make_component_()( | |
83 | detail::make_cons(proto::value(expr)) | |
84 | , data | |
85 | ); | |
86 | } | |
87 | }; | |
88 | ||
89 | template <typename Expr, typename State, typename Data, typename Domain> | |
90 | struct make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
91 | : proto::transform_impl<phoenix::actor<Expr>, State, Data> | |
92 | { | |
93 | typedef phoenix::actor<Expr> value; | |
94 | typedef typename result_of::make_cons<value>::type elements; | |
95 | typedef make_component<Domain, proto::tag::terminal> make_component_; | |
96 | ||
97 | typedef typename | |
98 | make_component_::template | |
99 | result<make_component_(elements, Data)>::type | |
100 | result_type; | |
101 | ||
102 | result_type operator()( | |
103 | typename make_terminal_impl::expr_param expr | |
104 | , typename make_terminal_impl::state_param /*state*/ | |
105 | , typename make_terminal_impl::data_param data | |
106 | ) const | |
107 | { | |
108 | return typename make_terminal_impl::make_component_()( | |
109 | detail::make_cons(expr) | |
110 | , data | |
111 | ); | |
112 | } | |
113 | }; | |
114 | ||
115 | template <typename Expr, typename State, typename Data, typename Domain> | |
116 | struct make_terminal_impl<phoenix::actor<Expr> &, State, Data, Domain> | |
117 | : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
118 | {}; | |
119 | ||
120 | template <typename Expr, typename State, typename Data, typename Domain> | |
121 | struct make_terminal_impl<phoenix::actor<Expr> const &, State, Data, Domain> | |
122 | : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
123 | {}; | |
124 | ||
125 | template <typename Domain> | |
126 | struct make_terminal : proto::transform<make_terminal<Domain> > | |
127 | { | |
128 | template<typename Expr, typename State, typename Data> | |
129 | struct impl : make_terminal_impl<Expr, State, Data, Domain> {}; | |
130 | }; | |
131 | ||
132 | template <typename Domain, typename Tag, typename Grammar> | |
133 | struct make_unary : proto::transform<make_unary<Domain, Tag, Grammar> > | |
134 | { | |
135 | template<typename Expr, typename State, typename Data> | |
136 | struct impl : proto::transform_impl<Expr, State, Data> | |
137 | { | |
138 | typedef typename | |
139 | proto::result_of::child_c<Expr, 0>::type | |
140 | child; | |
141 | ||
142 | typedef typename Grammar:: | |
143 | template result<Grammar(child, State, Data)>::type | |
144 | child_component; | |
145 | ||
146 | typedef typename | |
147 | result_of::make_cons<child_component>::type | |
148 | elements; | |
149 | ||
150 | typedef make_component<Domain, Tag> make_component_; | |
151 | ||
152 | typedef typename | |
153 | make_component_::template | |
154 | result<make_component_(elements, Data)>::type | |
155 | result_type; | |
156 | ||
157 | result_type operator()( | |
158 | typename impl::expr_param expr | |
159 | , typename impl::state_param state | |
160 | , typename impl::data_param data | |
161 | ) const | |
162 | { | |
163 | return typename impl::make_component_()( | |
164 | detail::make_cons( | |
165 | Grammar()(proto::child(expr), state, data)) | |
166 | , data | |
167 | ); | |
168 | } | |
169 | }; | |
170 | }; | |
171 | ||
172 | // un-flattened version | |
173 | template <typename Domain, typename Tag, typename Grammar, | |
174 | bool flatten = flatten_tree<Domain, Tag>::value> | |
175 | struct make_binary | |
176 | { | |
177 | template<typename Expr, typename State, typename Data> | |
178 | struct impl : proto::transform_impl<Expr, State, Data> | |
179 | { | |
180 | typedef typename Grammar:: | |
181 | template result<Grammar( | |
182 | typename proto::result_of::child_c<Expr, 0>::type | |
183 | , State, Data)>::type | |
184 | lhs_component; | |
185 | ||
186 | typedef typename Grammar:: | |
187 | template result<Grammar( | |
188 | typename proto::result_of::child_c<Expr, 1>::type | |
189 | , State, Data)>::type | |
190 | rhs_component; | |
191 | ||
192 | typedef typename | |
193 | result_of::make_cons< | |
194 | lhs_component | |
195 | , typename result_of::make_cons<rhs_component>::type | |
196 | >::type | |
197 | elements_type; | |
198 | ||
199 | typedef make_component<Domain, Tag> make_component_; | |
200 | ||
201 | typedef typename | |
202 | make_component_::template | |
203 | result<make_component_(elements_type, Data)>::type | |
204 | result_type; | |
205 | ||
206 | result_type operator()( | |
207 | typename impl::expr_param expr | |
208 | , typename impl::state_param state | |
209 | , typename impl::data_param data | |
210 | ) const | |
211 | { | |
212 | elements_type elements = | |
213 | detail::make_cons( | |
214 | Grammar()( | |
215 | proto::child_c<0>(expr), state, data) // LHS | |
216 | , detail::make_cons( | |
217 | Grammar()( | |
218 | proto::child_c<1>(expr), state, data) // RHS | |
219 | ) | |
220 | ); | |
221 | ||
222 | return make_component_()(elements, data); | |
223 | } | |
224 | }; | |
225 | }; | |
226 | ||
227 | template <typename Grammar> | |
228 | struct make_binary_helper : proto::transform<make_binary_helper<Grammar> > | |
229 | { | |
230 | template<typename Expr, typename State, typename Data> | |
231 | struct impl : proto::transform_impl<Expr, State, Data> | |
232 | { | |
233 | typedef typename Grammar:: | |
234 | template result<Grammar(Expr, State, Data)>::type | |
235 | lhs; | |
236 | ||
237 | typedef typename result_of::make_cons<lhs, State>::type result_type; | |
238 | ||
239 | result_type operator()( | |
240 | typename impl::expr_param expr | |
241 | , typename impl::state_param state | |
242 | , typename impl::data_param data | |
243 | ) const | |
244 | { | |
245 | return detail::make_cons(Grammar()(expr, state, data), state); | |
246 | } | |
247 | }; | |
248 | }; | |
249 | ||
250 | // Flattened version | |
251 | template <typename Domain, typename Tag, typename Grammar> | |
252 | struct make_binary<Domain, Tag, Grammar, true> | |
253 | : proto::transform<make_binary<Domain, Tag, Grammar> > | |
254 | { | |
255 | template<typename Expr, typename State, typename Data> | |
256 | struct impl : proto::transform_impl<Expr, State, Data> | |
257 | { | |
258 | typedef typename | |
259 | proto::reverse_fold_tree< | |
260 | proto::_ | |
261 | , proto::make<fusion::nil_> | |
262 | , make_binary_helper<Grammar> | |
263 | >::template impl<Expr, State, Data> | |
264 | reverse_fold_tree; | |
265 | ||
266 | typedef typename reverse_fold_tree::result_type elements; | |
267 | typedef make_component<Domain, Tag> make_component_; | |
268 | ||
269 | typedef typename | |
270 | make_component_::template | |
271 | result<make_component_(elements, Data)>::type | |
272 | result_type; | |
273 | ||
274 | result_type operator()( | |
275 | typename impl::expr_param expr | |
276 | , typename impl::state_param state | |
277 | , typename impl::data_param data | |
278 | ) const | |
279 | { | |
280 | return make_component_()( | |
281 | reverse_fold_tree()(expr, state, data), data); | |
282 | } | |
283 | }; | |
284 | }; | |
285 | ||
286 | template <typename Domain, typename Grammar> | |
287 | struct make_directive : proto::transform<make_directive<Domain, Grammar> > | |
288 | { | |
289 | template<typename Expr, typename State, typename Data> | |
290 | struct impl : proto::transform_impl<Expr, State, Data> | |
291 | { | |
292 | typedef typename | |
293 | proto::result_of::child_c<Expr, 0>::type | |
294 | lhs; | |
295 | ||
296 | typedef typename | |
297 | proto::result_of::value<lhs>::type | |
298 | tag_type; | |
299 | ||
300 | typedef typename modify<Domain>:: | |
301 | template result<modify<Domain>(tag_type, Data)>::type | |
302 | modifier_type; | |
303 | ||
304 | typedef typename Grammar:: | |
305 | template result<Grammar( | |
306 | typename proto::result_of::child_c<Expr, 1>::type | |
307 | , State | |
308 | , modifier_type | |
309 | )>::type | |
310 | rhs_component; | |
311 | ||
312 | typedef typename | |
313 | result_of::make_cons< | |
314 | tag_type | |
315 | , typename result_of::make_cons<rhs_component>::type | |
316 | >::type | |
317 | elements_type; | |
318 | ||
319 | typedef make_component<Domain, tag::directive> make_component_; | |
320 | ||
321 | typedef typename | |
322 | make_component_::template | |
323 | result<make_component_(elements_type, Data)>::type | |
324 | result_type; | |
325 | ||
326 | result_type operator()( | |
327 | typename impl::expr_param expr | |
328 | , typename impl::state_param state | |
329 | , typename impl::data_param data | |
330 | ) const | |
331 | { | |
332 | tag_type tag = proto::value(proto::child_c<0>(expr)); | |
333 | typename remove_reference<modifier_type>::type | |
334 | modifier = modify<Domain>()(tag, data); | |
335 | ||
336 | elements_type elements = | |
337 | detail::make_cons( | |
338 | tag // LHS | |
339 | , detail::make_cons( | |
340 | Grammar()( | |
341 | proto::child_c<1>(expr) // RHS | |
342 | , state, modifier) | |
343 | ) | |
344 | ); | |
345 | ||
346 | return make_component_()(elements, data); | |
347 | } | |
348 | }; | |
349 | }; | |
350 | ||
351 | template <typename Domain, typename Grammar> | |
352 | struct make_action : proto::transform<make_action<Domain, Grammar> > | |
353 | { | |
354 | template<typename Expr, typename State, typename Data> | |
355 | struct impl : proto::transform_impl<Expr, State, Data> | |
356 | { | |
357 | typedef typename Grammar:: | |
358 | template result<Grammar( | |
359 | typename proto::result_of::child_c<Expr, 0>::type | |
360 | , State | |
361 | , Data | |
362 | )>::type | |
363 | lhs_component; | |
364 | ||
365 | typedef | |
366 | typename mpl::eval_if_c< | |
367 | phoenix::is_actor< | |
368 | typename proto::result_of::child_c<Expr, 1>::type | |
369 | >::type::value | |
370 | , proto::result_of::child_c<Expr, 1> | |
371 | , proto::result_of::value< | |
372 | typename proto::result_of::child_c<Expr, 1>::type | |
373 | > | |
374 | >::type | |
375 | rhs_component; | |
376 | ||
377 | typedef typename | |
378 | result_of::make_cons< | |
379 | lhs_component | |
380 | , typename result_of::make_cons<rhs_component>::type | |
381 | >::type | |
382 | elements_type; | |
383 | ||
384 | typedef make_component<Domain, tag::action> make_component_; | |
385 | ||
386 | typedef typename | |
387 | make_component_::template | |
388 | result<make_component_(elements_type, Data)>::type | |
389 | result_type; | |
390 | ||
391 | result_type operator()( | |
392 | typename impl::expr_param expr | |
393 | , typename impl::state_param state | |
394 | , typename impl::data_param data | |
395 | ) const | |
396 | { | |
397 | return | |
398 | (*this)( | |
399 | expr | |
400 | , state | |
401 | , data | |
402 | , typename phoenix::is_actor< | |
403 | typename proto::result_of::child_c<Expr, 1>::type | |
404 | >::type() | |
405 | ); | |
406 | } | |
407 | ||
408 | result_type operator()( | |
409 | typename impl::expr_param expr | |
410 | , typename impl::state_param state | |
411 | , typename impl::data_param data | |
412 | , mpl::false_ | |
413 | ) const | |
414 | { | |
415 | elements_type elements = | |
416 | detail::make_cons( | |
417 | Grammar()( | |
418 | proto::child_c<0>(expr), state, data) // LHS | |
419 | , detail::make_cons( | |
420 | proto::value(proto::child_c<1>(expr))) // RHS | |
421 | ); | |
422 | ||
423 | return make_component_()(elements, data); | |
424 | } | |
425 | ||
426 | result_type operator()( | |
427 | typename impl::expr_param expr | |
428 | , typename impl::state_param state | |
429 | , typename impl::data_param data | |
430 | , mpl::true_ | |
431 | ) const | |
432 | { | |
433 | elements_type elements = | |
434 | detail::make_cons( | |
435 | Grammar()( | |
436 | proto::child_c<0>(expr), state, data) // LHS | |
437 | , detail::make_cons( | |
438 | proto::child_c<1>(expr)) // RHS | |
439 | ); | |
440 | ||
441 | return make_component_()(elements, data); | |
442 | } | |
443 | }; | |
444 | }; | |
445 | }}} | |
446 | ||
447 | #endif |