• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
12A Phoenix Expression is a model of the __proto_expr__ Concept. These expressions
13are wrapped inside an [link phoenix.inside.actor Actor] template. The `actor` provides
14the function call operator which evaluates the expressions.
15The `actor` is the domain specific wrapper around Phoenix expressions.
16
17By design, Phoenix Expressions do not carry any information on how they will be
18evaluated later on. They are the data structure on which the `Actions` will work.
19
20The 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
61Defining expressions is only part of the game to make it a valid Phoenix Expression.
62In order to use the expressions in the Phoenix domain, we need to "register" them
63to our grammar.
64
65The `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
76As you can see, by default the `meta_grammar` matches nothing. With every [link phoenix.modules Module]
77you include this grammar gets extended by various expressions.
78
79[heading Example]
80
81Define an expression:
82
83    template <typename Lhs, typename Rhs>
84    struct plus
85        : expr<proto::tag::plus, Lhs, Rhs>
86    {};
87
88And 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
100Define 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
109Look if it really works:
110
111    plus(6, 5)();
112
113returns 11!
114
115    proto::display_expr(plus(5, 6));
116
117prints:
118
119    plus(
120        terminal(6)
121      , terminal(5)
122    )
123
124See [@../../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
136When having more and more expressions, you start to realize that this is a very
137repetetive task. Phoenix provides boilerplate macros that make defining Phoenix
138Expressions as you have seen in the
139[link phoenix.inside.expression previous section] look like a piece of cake.
140
141
142[/
143These 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
154necessary 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
167The above macro generates the necessary code for an expression `name` in
168namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many
169children the expression will have and what `proto::grammar` they match.
170
171The macro should be used at global scope. `namespace_seq` shall be the sequence
172of 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
220This macros also adds a specialization for `meta_grammar::case_<tag::name>` to
221enable the rule for further use in actions.
222
223[heading Header]
224
225    #include <boost/phoenix/core/expression.hpp>
226
227[heading Example]
228
229The 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
251necessary 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
266The above macro generates the necessary code for an expression `name` in
267namespace `namespace_seq`. `N` is the maximum number of variable children.
268All but the last elements in the grammar sequence are required children of
269the expression, and the last denotes a variable number of children. The number
270of children an expression of this kind can hold is therefor `N-1` plus the size of
271the sequence
272
273The macro should be used at global scope. `namespace_seq` shall be the sequence
274of 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
323This macros also adds a specialization for `meta_grammar::case_<tag::name>` to
324enable 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
340This 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
350necessary 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
366The above macro generates the necessary code for an expression `name` in
367namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many
368children the expression will have and what `proto::grammar` they match.
369
370The macro should be used at global scope. `namespace_seq` shall be the sequence
371of 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
420This macros also adds a specialization for `meta_grammar::case_<tag::name>` to
421enable 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
436This 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
445necessary 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
461The above macro generates the necessary code for an expression `name` in
462namespace `namespace_seq`. `N` is the maximum number of variable children.
463All but the last elements in the grammar sequence are required children of
464the expression, and the last denotes a variable number of children. The number
465of children an expression of this kind can hold is therefor `N-1` plus the size of
466the sequence
467
468The macro should be used at global scope. `namespace_seq` shall be the sequence
469of 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
519This macros also adds a specialization for `meta_grammar::case_<tag::name>` to
520enable the rule for further use in actions.
521
522[heading Header]
523
524    #include <boost/phoenix/core/expression.hpp>
525
526[heading Example]
527
528TBD
529
530[endsect]
531
532[endsect]
533
534[endsect]
535