]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/============================================================================== |
2 | Copyright (C) 2001-2010 Joel de Guzman | |
3 | Copyright (C) 2001-2005 Dan Marsden | |
4 | Copyright (C) 2001-2010 Thomas Heller | |
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 | ||
10 | [section:expression Phoenix Expressions] | |
11 | ||
12 | A Phoenix Expression is a model of the __proto_expr__ Concept. These expressions | |
13 | are wrapped inside an [link phoenix.inside.actor Actor] template. The `actor` provides | |
14 | the function call operator which evaluates the expressions. | |
15 | The `actor` is the domain specific wrapper around Phoenix expressions. | |
16 | ||
17 | By design, Phoenix Expressions do not carry any information on how they will be | |
18 | evaluated later on. They are the data structure on which the `Actions` will work. | |
19 | ||
20 | The library provides a convenience template to define expressions: | |
21 | ||
22 | template <template <typename> Actor, typename Tag, typename A0, ..., typename A1> | |
23 | struct expr_ext | |
24 | : proto::transform<expr_ext<Actor, Tag, A0, ..., A1> > | |
25 | { | |
26 | typedef __unspecified__ base_expr; | |
27 | typedef Actor<base_expr> type; | |
28 | ||
29 | typedef __unspecified__ proto_grammar; | |
30 | ||
31 | static type make(A0 a0, ..., A1 a1); | |
32 | }; | |
33 | ||
34 | template <typename Tag, typename A0, ..., typename A1> | |
35 | struct expr : expr_ext<actor, Tag, A0, ..., A1> {}; | |
36 | ||
37 | [*Notation] | |
38 | [variablelist | |
39 | [[`A0...AN`] [Child node types]] | |
40 | [[`a0...aN`] [Child node objects]] | |
41 | [[`G0...GN`] [__proto__ grammar types]] | |
42 | ] | |
43 | ||
44 | [*Expression Semantics] | |
45 | [table | |
46 | [[Expression] [Semantics]] | |
47 | [[`expr<Tag, A0...AN>::type`] [The type of Expression having tag `Tag` and `A0...AN` children]] | |
48 | [[`expr<Tag, G0...GN>`] [A __proto__ grammar and __proto_pass_through_transform__]] | |
49 | [[`expr<Tag, A0...AN>::make(a0...aN)`] [Returns a Phoenix Expression]] | |
50 | ] | |
51 | ||
52 | [note | |
53 | You might have noticed the template template argument `Actor` used in | |
54 | `expr_ext`. This can be a user supplied custom Actor adding other member | |
55 | functions or objects than the default `actor` template. See | |
56 | [link phoenix.examples.extending_actors Extending Actors] for more details. | |
57 | ] | |
58 | ||
59 | [heading meta_grammar] | |
60 | ||
61 | Defining expressions is only part of the game to make it a valid Phoenix Expression. | |
62 | In order to use the expressions in the Phoenix domain, we need to "register" them | |
63 | to our grammar. | |
64 | ||
65 | The `meta_grammar` is a struct for exactly that purpose. It is an openly extendable __proto__ Grammar: | |
66 | ||
67 | struct meta_grammar | |
68 | : proto::switch_<meta_grammar> | |
69 | { | |
70 | template <typename Tag, typename Dummy> | |
71 | struct case_ | |
72 | : proto::not_<proto::_> | |
73 | {}; | |
74 | }; | |
75 | ||
76 | As you can see, by default the `meta_grammar` matches nothing. With every [link phoenix.modules Module] | |
77 | you include this grammar gets extended by various expressions. | |
78 | ||
79 | [heading Example] | |
80 | ||
81 | Define an expression: | |
82 | ||
83 | template <typename Lhs, typename Rhs> | |
84 | struct plus | |
85 | : expr<proto::tag::plus, Lhs, Rhs> | |
86 | {}; | |
87 | ||
88 | And add it to the grammar: | |
89 | ||
90 | template <> | |
91 | struct meta_grammar::case_<proto::tag::plus> | |
92 | : enable_rule< | |
93 | plus< | |
94 | meta_grammar | |
95 | , meta_grammar | |
96 | > | |
97 | > | |
98 | {}; | |
99 | ||
100 | Define a generator function to make the life of our potential users easier: | |
101 | ||
102 | template <typename Lhs, typename Rhs> | |
103 | typename plus<Lhs, Rhs>::type | |
104 | plus(Lhs const & lhs, Rhs const & rhs) | |
105 | { | |
106 | return expression::plus<Lhs, Rhs>::make(lhs, rhs); | |
107 | } | |
108 | ||
109 | Look if it really works: | |
110 | ||
111 | plus(6, 5)(); | |
112 | ||
113 | returns 11! | |
114 | ||
115 | proto::display_expr(plus(5, 6)); | |
116 | ||
117 | prints: | |
118 | ||
119 | plus( | |
120 | terminal(6) | |
121 | , terminal(5) | |
122 | ) | |
123 | ||
124 | See [@../../example/define_expression.cpp define_expression.cpp] for the full example. | |
125 | ||
126 | [note | |
127 | The example shown here only works because `default_actions` knows how to handle | |
128 | an expression having the `proto::tag::plus` and two children. This is because | |
129 | `default_actions` uses the `proto::_default<meta_grammar>` transform to | |
130 | evaluate operators and functions. Learn more about actions | |
131 | [link phoenix.inside.actions here]. | |
132 | ] | |
133 | ||
134 | [section Boilerplate Macros] | |
135 | ||
136 | When having more and more expressions, you start to realize that this is a very | |
137 | repetetive task. Phoenix provides boilerplate macros that make defining Phoenix | |
138 | Expressions as you have seen in the | |
139 | [link phoenix.inside.expression previous section] look like a piece of cake. | |
140 | ||
141 | ||
142 | [/ | |
143 | These expressions generate the following: | |
144 | * A tag (in the underlying namespace tag) | |
145 | * An expression | |
146 | * an expression type in namespace expression | |
147 | ] | |
148 | ||
149 | [section BOOST_PHOENIX_DEFINE_EXPRESSION] | |
150 | ||
151 | [heading Description] | |
152 | ||
153 | `BOOST_PHOENIX_DEFINE_EXPRESSION` is a macro that can be used to generate all the | |
154 | necessary boilerplate to create Phoenix Expressions | |
155 | ||
156 | [heading Synopsis] | |
157 | ||
158 | BOOST_PHOENIX_DEFINE_EXPRESSION( | |
159 | (namespace_seq)(name) | |
160 | , (child_grammar0) | |
161 | (child_grammar1) | |
162 | ... | |
163 | ) | |
164 | ||
165 | [heading Semantics] | |
166 | ||
167 | The above macro generates the necessary code for an expression `name` in | |
168 | namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many | |
169 | children the expression will have and what `proto::grammar` they match. | |
170 | ||
171 | The macro should be used at global scope. `namespace_seq` shall be the sequence | |
172 | of namespaces under which the following symbols will be defined: | |
173 | ||
174 | namespace tag | |
175 | { | |
176 | struct name; | |
177 | } | |
178 | ||
179 | namespace expression | |
180 | { | |
181 | template <typename A0, typename A1 ... typename AN> | |
182 | struct name | |
183 | : boost::phoenix::expr< | |
184 | tag::name | |
185 | , A0 | |
186 | , A1 | |
187 | ... | |
188 | , AN | |
189 | > | |
190 | } | |
191 | ||
192 | namespace rule | |
193 | { | |
194 | struct name | |
195 | : boost::phoenix::expr< | |
196 | child_grammar0 | |
197 | , child_grammar1 | |
198 | ... | |
199 | , child_grammarN | |
200 | > | |
201 | {}; | |
202 | } | |
203 | ||
204 | namespace functional | |
205 | { | |
206 | struct make_name; // A polymorphic function object that can be called to create the expression node | |
207 | } | |
208 | ||
209 | namespace result_of | |
210 | { | |
211 | template <typename A0, typename A1 ... typename AN> | |
212 | struct make_name; // The result type of the expression node | |
213 | } | |
214 | ||
215 | // convenience polymorphic function to create an expression node | |
216 | template <typename A0, typename A1 ... typename AN> | |
217 | result_of::make_name<A0, A1 ... AN> | |
218 | make_name(A0 const & a0, A1 const & a1 ... AN const & an); | |
219 | ||
220 | This macros also adds a specialization for `meta_grammar::case_<tag::name>` to | |
221 | enable the rule for further use in actions. | |
222 | ||
223 | [heading Header] | |
224 | ||
225 | #include <boost/phoenix/core/expression.hpp> | |
226 | ||
227 | [heading Example] | |
228 | ||
229 | The example from the previous section can be rewritten as: | |
230 | ||
231 | BOOST_PHOENIX_DEFINE_EXPRESSION( | |
232 | (plus) | |
233 | , (meta_grammar) // Lhs | |
234 | (meta_grammar) // Rhs | |
235 | ) | |
236 | ||
237 | template <typename Lhs, typename Rhs> | |
238 | typename plus<Lhs, Rhs>::type | |
239 | plus(Lhs const & lhs, Rhs const & rhs) | |
240 | { | |
241 | return expression::plus<Lhs, Rhs>::make(lhs, rhs); | |
242 | } | |
243 | ||
244 | [endsect] | |
245 | ||
246 | [section BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG] | |
247 | ||
248 | [heading Description] | |
249 | ||
250 | `BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG` is a macro that can be used to generate all the | |
251 | necessary boilerplate to create Phoenix Expressions | |
252 | ||
253 | [heading Synopsis] | |
254 | ||
255 | BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( | |
256 | (namespace_seq)(name) | |
257 | , (child_grammar0) | |
258 | (child_grammar1) | |
259 | ... | |
260 | (child_grammarN) | |
261 | , N | |
262 | ) | |
263 | ||
264 | [heading Semantics] | |
265 | ||
266 | The above macro generates the necessary code for an expression `name` in | |
267 | namespace `namespace_seq`. `N` is the maximum number of variable children. | |
268 | All but the last elements in the grammar sequence are required children of | |
269 | the expression, and the last denotes a variable number of children. The number | |
270 | of children an expression of this kind can hold is therefor `N-1` plus the size of | |
271 | the sequence | |
272 | ||
273 | The macro should be used at global scope. `namespace_seq` shall be the sequence | |
274 | of namespaces under which the following symbols will be defined: | |
275 | ||
276 | namespace tag | |
277 | { | |
278 | struct name; | |
279 | } | |
280 | ||
281 | namespace expression | |
282 | { | |
283 | template <typename A0, typename A1 ... typename AN> | |
284 | struct name | |
285 | : boost::phoenix::expr< | |
286 | tag::name | |
287 | , A0 | |
288 | , A1 | |
289 | ... | |
290 | , AN | |
291 | > | |
292 | {}; | |
293 | } | |
294 | ||
295 | namespace rule | |
296 | { | |
297 | struct name | |
298 | : expression::name< | |
299 | child_grammar0 | |
300 | , child_grammar1 | |
301 | ... | |
302 | , proto::vararg<child_grammarN> | |
303 | > | |
304 | {}; | |
305 | } | |
306 | ||
307 | namespace functional | |
308 | { | |
309 | struct make_name; // A polymorphic function object that can be called to create the expression node | |
310 | } | |
311 | ||
312 | namespace result_of | |
313 | { | |
314 | template <typename A0, typename A1 ... typename AN> | |
315 | struct make_name; // The result type of the expression node | |
316 | } | |
317 | ||
318 | // convenience polymorphic function to create an expression node | |
319 | template <typename A0, typename A1 ... typename AN> | |
320 | result_of::make_name<A0, A1 ... AN> | |
321 | make_name(A0 const & a0, A1 const & a1 ... AN const & an); | |
322 | ||
323 | This macros also adds a specialization for `meta_grammar::case_<tag::name>` to | |
324 | enable the rule for further use in actions. | |
325 | ||
326 | [heading Header] | |
327 | ||
328 | #include <boost/phoenix/core/expression.hpp> | |
329 | ||
330 | [heading Example] | |
331 | ||
332 | BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( | |
333 | (boost)(phoenix)(mem_fun_ptr) | |
334 | , (meta_grammar) // Pointer to Object | |
335 | (meta_grammar) // Member pointer | |
336 | (meta_grammar) // Variable number of arguments | |
337 | , BOOST_PHOENIX_LIMIT | |
338 | ) | |
339 | ||
340 | This defines the member function pointer operator expression as described in | |
341 | [link phoenix.modules.operator operators]. | |
342 | ||
343 | [endsect] | |
344 | ||
345 | [section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT] | |
346 | ||
347 | [heading Description] | |
348 | ||
349 | `BOOST_PHOENIX_DEFINE_EXPRESSION_EXT` is a macro that can be used to generate all the | |
350 | necessary boilerplate to create Phoenix Expressions | |
351 | ||
352 | [heading Synopsis] | |
353 | ||
354 | BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( | |
355 | actor | |
356 | , (namespace_seq)(name) | |
357 | , (child_grammar0) | |
358 | (child_grammar1) | |
359 | ... | |
360 | (child_grammarN) | |
361 | , N | |
362 | ) | |
363 | ||
364 | [heading Semantics] | |
365 | ||
366 | The above macro generates the necessary code for an expression `name` in | |
367 | namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many | |
368 | children the expression will have and what `proto::grammar` they match. | |
369 | ||
370 | The macro should be used at global scope. `namespace_seq` shall be the sequence | |
371 | of namespaces under which the following symbols will be defined: | |
372 | ||
373 | namespace tag | |
374 | { | |
375 | struct name; | |
376 | } | |
377 | ||
378 | namespace expression | |
379 | { | |
380 | template <typename A0, typename A1 ... typename AN> | |
381 | struct name | |
382 | : boost::phoenix::expr_ext< | |
383 | actor | |
384 | , tag::name | |
385 | , A0 | |
386 | , A1 | |
387 | ... | |
388 | , AN | |
389 | > | |
390 | } | |
391 | ||
392 | namespace rule | |
393 | { | |
394 | struct name | |
395 | : boost::phoenix::expr< | |
396 | child_grammar0 | |
397 | , child_grammar1 | |
398 | ... | |
399 | , child_grammarN | |
400 | > | |
401 | {}; | |
402 | } | |
403 | ||
404 | namespace functional | |
405 | { | |
406 | struct make_name; // A polymorphic function object that can be called to create the expression node | |
407 | } | |
408 | ||
409 | namespace result_of | |
410 | { | |
411 | template <typename A0, typename A1 ... typename AN> | |
412 | struct make_name; // The result type of the expression node | |
413 | } | |
414 | ||
415 | // convenience polymorphic function to create an expression node | |
416 | template <typename A0, typename A1 ... typename AN> | |
417 | result_of::make_name<A0, A1 ... AN> | |
418 | make_name(A0 const & a0, A1 const & a1 ... AN const & an); | |
419 | ||
420 | This macros also adds a specialization for `meta_grammar::case_<tag::name>` to | |
421 | enable the rule for further use in actions. | |
422 | ||
423 | [heading Header] | |
424 | ||
425 | #include <boost/phoenix/core/expression.hpp> | |
426 | ||
427 | [heading Example] | |
428 | ||
429 | BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( | |
430 | if_actor | |
431 | , (boost)(phoenix)(if_) | |
432 | , (meta_grammar) // Cond | |
433 | (meta_grammar) // Then | |
434 | ) | |
435 | ||
436 | This defines the if_ expression. The custom actor defines `else_` as a member. | |
437 | ||
438 | [endsect] | |
439 | ||
440 | [section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG] | |
441 | ||
442 | [heading Description] | |
443 | ||
444 | `BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG` is a macro that can be used to generate all the | |
445 | necessary boilerplate to create Phoenix Expressions | |
446 | ||
447 | [heading Synopsis] | |
448 | ||
449 | BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG( | |
450 | actor | |
451 | , (namespace_seq)(name) | |
452 | , (child_grammar0) | |
453 | (child_grammar1) | |
454 | ... | |
455 | (child_grammarN) | |
456 | , N | |
457 | ) | |
458 | ||
459 | [heading Semantics] | |
460 | ||
461 | The above macro generates the necessary code for an expression `name` in | |
462 | namespace `namespace_seq`. `N` is the maximum number of variable children. | |
463 | All but the last elements in the grammar sequence are required children of | |
464 | the expression, and the last denotes a variable number of children. The number | |
465 | of children an expression of this kind can hold is therefor `N-1` plus the size of | |
466 | the sequence | |
467 | ||
468 | The macro should be used at global scope. `namespace_seq` shall be the sequence | |
469 | of namespaces under which the following symbols will be defined: | |
470 | ||
471 | namespace tag | |
472 | { | |
473 | struct name; | |
474 | } | |
475 | ||
476 | namespace expression | |
477 | { | |
478 | template <typename A0, typename A1 ... typename AN> | |
479 | struct name | |
480 | : boost::phoenix::expr_ext< | |
481 | actor | |
482 | , tag::name | |
483 | , A0 | |
484 | , A1 | |
485 | ... | |
486 | , AN | |
487 | > | |
488 | {}; | |
489 | } | |
490 | ||
491 | namespace rule | |
492 | { | |
493 | struct name | |
494 | : expression::name< | |
495 | child_grammar0 | |
496 | , child_grammar1 | |
497 | ... | |
498 | , proto::vararg<child_grammarN> | |
499 | > | |
500 | {}; | |
501 | } | |
502 | ||
503 | namespace functional | |
504 | { | |
505 | struct make_name; // A polymorphic function object that can be called to create the expression node | |
506 | } | |
507 | ||
508 | namespace result_of | |
509 | { | |
510 | template <typename A0, typename A1 ... typename AN> | |
511 | struct make_name; // The result type of the expression node | |
512 | } | |
513 | ||
514 | // convenience polymorphic function to create an expression node | |
515 | template <typename A0, typename A1 ... typename AN> | |
516 | result_of::make_name<A0, A1 ... AN> | |
517 | make_name(A0 const & a0, A1 const & a1 ... AN const & an); | |
518 | ||
519 | This macros also adds a specialization for `meta_grammar::case_<tag::name>` to | |
520 | enable the rule for further use in actions. | |
521 | ||
522 | [heading Header] | |
523 | ||
524 | #include <boost/phoenix/core/expression.hpp> | |
525 | ||
526 | [heading Example] | |
527 | ||
528 | TBD | |
529 | ||
530 | [endsect] | |
531 | ||
532 | [endsect] | |
533 | ||
534 | [endsect] |