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