| [/============================================================================== |
| Copyright (C) 2001-2010 Joel de Guzman |
| Copyright (C) 2001-2005 Dan Marsden |
| Copyright (C) 2001-2010 Thomas Heller |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ===============================================================================/] |
| |
| [section:expression Phoenix Expressions] |
| |
| A Phoenix Expression is a model of the __proto_expr__ Concept. These expressions |
| are wrapped inside an [link phoenix.inside.actor Actor] template. The `actor` provides |
| the function call operator which evaluates the expressions. |
| The `actor` is the domain specific wrapper around Phoenix expressions. |
| |
| By design, Phoenix Expressions do not carry any information on how they will be |
| evaluated later on. They are the data structure on which the `Actions` will work. |
| |
| The library provides a convenience template to define expressions: |
| |
| template <template <typename> Actor, typename Tag, typename A0, ..., typename A1> |
| struct expr_ext |
| : proto::transform<expr_ext<Actor, Tag, A0, ..., A1> > |
| { |
| typedef __unspecified__ base_expr; |
| typedef Actor<base_expr> type; |
| |
| typedef __unspecified__ proto_grammar; |
| |
| static type make(A0 a0, ..., A1 a1); |
| }; |
| |
| template <typename Tag, typename A0, ..., typename A1> |
| struct expr : expr_ext<actor, Tag, A0, ..., A1> {}; |
| |
| [*Notation] |
| [variablelist |
| [[`A0...AN`] [Child node types]] |
| [[`a0...aN`] [Child node objects]] |
| [[`G0...GN`] [__proto__ grammar types]] |
| ] |
| |
| [*Expression Semantics] |
| [table |
| [[Expression] [Semantics]] |
| [[`expr<Tag, A0...AN>::type`] [The type of Expression having tag `Tag` and `A0...AN` children]] |
| [[`expr<Tag, G0...GN>`] [A __proto__ grammar and __proto_pass_through_transform__]] |
| [[`expr<Tag, A0...AN>::make(a0...aN)`] [Returns a Phoenix Expression]] |
| ] |
| |
| [note |
| You might have noticed the template template argument `Actor` used in |
| `expr_ext`. This can be a user supplied custom Actor adding other member |
| functions or objects than the default `actor` template. See |
| [link phoenix.examples.extending_actors Extending Actors] for more details. |
| ] |
| |
| [heading meta_grammar] |
| |
| Defining expressions is only part of the game to make it a valid Phoenix Expression. |
| In order to use the expressions in the Phoenix domain, we need to "register" them |
| to our grammar. |
| |
| The `meta_grammar` is a struct for exactly that purpose. It is an openly extendable __proto__ Grammar: |
| |
| struct meta_grammar |
| : proto::switch_<meta_grammar> |
| { |
| template <typename Tag, typename Dummy> |
| struct case_ |
| : proto::not_<proto::_> |
| {}; |
| }; |
| |
| As you can see, by default the `meta_grammar` matches nothing. With every [link phoenix.modules Module] |
| you include this grammar gets extended by various expressions. |
| |
| [heading Example] |
| |
| Define an expression: |
| |
| template <typename Lhs, typename Rhs> |
| struct plus |
| : expr<proto::tag::plus, Lhs, Rhs> |
| {}; |
| |
| And add it to the grammar: |
| |
| template <> |
| struct meta_grammar::case_<proto::tag::plus> |
| : enable_rule< |
| plus< |
| meta_grammar |
| , meta_grammar |
| > |
| > |
| {}; |
| |
| Define a generator function to make the life of our potential users easier: |
| |
| template <typename Lhs, typename Rhs> |
| typename plus<Lhs, Rhs>::type |
| plus(Lhs const & lhs, Rhs const & rhs) |
| { |
| return expression::plus<Lhs, Rhs>::make(lhs, rhs); |
| } |
| |
| Look if it really works: |
| |
| plus(6, 5)(); |
| |
| returns 11! |
| |
| proto::display_expr(plus(5, 6)); |
| |
| prints: |
| |
| plus( |
| terminal(6) |
| , terminal(5) |
| ) |
| |
| See [@../../example/define_expression.cpp define_expression.cpp] for the full example. |
| |
| [note |
| The example shown here only works because `default_actions` knows how to handle |
| an expression having the `proto::tag::plus` and two children. This is because |
| `default_actions` uses the `proto::_default<meta_grammar>` transform to |
| evaluate operators and functions. Learn more about actions |
| [link phoenix.inside.actions here]. |
| ] |
| |
| [section Boilerplate Macros] |
| |
| When having more and more expressions, you start to realize that this is a very |
| repetetive task. Phoenix provides boilerplate macros that make defining Phoenix |
| Expressions as you have seen in the |
| [link phoenix.inside.expression previous section] look like a piece of cake. |
| |
| |
| [/ |
| These expressions generate the following: |
| * A tag (in the underlying namespace tag) |
| * An expression |
| * an expression type in namespace expression |
| ] |
| |
| [section BOOST_PHOENIX_DEFINE_EXPRESSION] |
| |
| [heading Description] |
| |
| `BOOST_PHOENIX_DEFINE_EXPRESSION` is a macro that can be used to generate all the |
| necessary boilerplate to create Phoenix Expressions |
| |
| [heading Synopsis] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION( |
| (namespace_seq)(name) |
| , (child_grammar0) |
| (child_grammar1) |
| ... |
| ) |
| |
| [heading Semantics] |
| |
| The above macro generates the necessary code for an expression `name` in |
| namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many |
| children the expression will have and what `proto::grammar` they match. |
| |
| The macro should be used at global scope. `namespace_seq` shall be the sequence |
| of namespaces under which the following symbols will be defined: |
| |
| namespace tag |
| { |
| struct name; |
| } |
| |
| namespace expression |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct name |
| : boost::phoenix::expr< |
| tag::name |
| , A0 |
| , A1 |
| ... |
| , AN |
| > |
| } |
| |
| namespace rule |
| { |
| struct name |
| : boost::phoenix::expr< |
| child_grammar0 |
| , child_grammar1 |
| ... |
| , child_grammarN |
| > |
| {}; |
| } |
| |
| namespace functional |
| { |
| struct make_name; // A polymorphic function object that can be called to create the expression node |
| } |
| |
| namespace result_of |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct make_name; // The result type of the expression node |
| } |
| |
| // convenience polymorphic function to create an expression node |
| template <typename A0, typename A1 ... typename AN> |
| result_of::make_name<A0, A1 ... AN> |
| make_name(A0 const & a0, A1 const & a1 ... AN const & an); |
| |
| This macros also adds a specialization for `meta_grammar::case_<tag::name>` to |
| enable the rule for further use in actions. |
| |
| [heading Header] |
| |
| #include <boost/phoenix/core/expression.hpp> |
| |
| [heading Example] |
| |
| The example from the previous section can be rewritten as: |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION( |
| (plus) |
| , (meta_grammar) // Lhs |
| (meta_grammar) // Rhs |
| ) |
| |
| template <typename Lhs, typename Rhs> |
| typename plus<Lhs, Rhs>::type |
| plus(Lhs const & lhs, Rhs const & rhs) |
| { |
| return expression::plus<Lhs, Rhs>::make(lhs, rhs); |
| } |
| |
| [endsect] |
| |
| [section BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG] |
| |
| [heading Description] |
| |
| `BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG` is a macro that can be used to generate all the |
| necessary boilerplate to create Phoenix Expressions |
| |
| [heading Synopsis] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( |
| (namespace_seq)(name) |
| , (child_grammar0) |
| (child_grammar1) |
| ... |
| (child_grammarN) |
| , N |
| ) |
| |
| [heading Semantics] |
| |
| The above macro generates the necessary code for an expression `name` in |
| namespace `namespace_seq`. `N` is the maximum number of variable children. |
| All but the last elements in the grammar sequence are required children of |
| the expression, and the last denotes a variable number of children. The number |
| of children an expression of this kind can hold is therefor `N-1` plus the size of |
| the sequence |
| |
| The macro should be used at global scope. `namespace_seq` shall be the sequence |
| of namespaces under which the following symbols will be defined: |
| |
| namespace tag |
| { |
| struct name; |
| } |
| |
| namespace expression |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct name |
| : boost::phoenix::expr< |
| tag::name |
| , A0 |
| , A1 |
| ... |
| , AN |
| > |
| {}; |
| } |
| |
| namespace rule |
| { |
| struct name |
| : expression::name< |
| child_grammar0 |
| , child_grammar1 |
| ... |
| , proto::vararg<child_grammarN> |
| > |
| {}; |
| } |
| |
| namespace functional |
| { |
| struct make_name; // A polymorphic function object that can be called to create the expression node |
| } |
| |
| namespace result_of |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct make_name; // The result type of the expression node |
| } |
| |
| // convenience polymorphic function to create an expression node |
| template <typename A0, typename A1 ... typename AN> |
| result_of::make_name<A0, A1 ... AN> |
| make_name(A0 const & a0, A1 const & a1 ... AN const & an); |
| |
| This macros also adds a specialization for `meta_grammar::case_<tag::name>` to |
| enable the rule for further use in actions. |
| |
| [heading Header] |
| |
| #include <boost/phoenix/core/expression.hpp> |
| |
| [heading Example] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( |
| (boost)(phoenix)(mem_fun_ptr) |
| , (meta_grammar) // Pointer to Object |
| (meta_grammar) // Member pointer |
| (meta_grammar) // Variable number of arguments |
| , BOOST_PHOENIX_LIMIT |
| ) |
| |
| This defines the member function pointer operator expression as described in |
| [link phoenix.modules.operator operators]. |
| |
| [endsect] |
| |
| [section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT] |
| |
| [heading Description] |
| |
| `BOOST_PHOENIX_DEFINE_EXPRESSION_EXT` is a macro that can be used to generate all the |
| necessary boilerplate to create Phoenix Expressions |
| |
| [heading Synopsis] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( |
| actor |
| , (namespace_seq)(name) |
| , (child_grammar0) |
| (child_grammar1) |
| ... |
| (child_grammarN) |
| , N |
| ) |
| |
| [heading Semantics] |
| |
| The above macro generates the necessary code for an expression `name` in |
| namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many |
| children the expression will have and what `proto::grammar` they match. |
| |
| The macro should be used at global scope. `namespace_seq` shall be the sequence |
| of namespaces under which the following symbols will be defined: |
| |
| namespace tag |
| { |
| struct name; |
| } |
| |
| namespace expression |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct name |
| : boost::phoenix::expr_ext< |
| actor |
| , tag::name |
| , A0 |
| , A1 |
| ... |
| , AN |
| > |
| } |
| |
| namespace rule |
| { |
| struct name |
| : boost::phoenix::expr< |
| child_grammar0 |
| , child_grammar1 |
| ... |
| , child_grammarN |
| > |
| {}; |
| } |
| |
| namespace functional |
| { |
| struct make_name; // A polymorphic function object that can be called to create the expression node |
| } |
| |
| namespace result_of |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct make_name; // The result type of the expression node |
| } |
| |
| // convenience polymorphic function to create an expression node |
| template <typename A0, typename A1 ... typename AN> |
| result_of::make_name<A0, A1 ... AN> |
| make_name(A0 const & a0, A1 const & a1 ... AN const & an); |
| |
| This macros also adds a specialization for `meta_grammar::case_<tag::name>` to |
| enable the rule for further use in actions. |
| |
| [heading Header] |
| |
| #include <boost/phoenix/core/expression.hpp> |
| |
| [heading Example] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( |
| if_actor |
| , (boost)(phoenix)(if_) |
| , (meta_grammar) // Cond |
| (meta_grammar) // Then |
| ) |
| |
| This defines the if_ expression. The custom actor defines `else_` as a member. |
| |
| [endsect] |
| |
| [section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG] |
| |
| [heading Description] |
| |
| `BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG` is a macro that can be used to generate all the |
| necessary boilerplate to create Phoenix Expressions |
| |
| [heading Synopsis] |
| |
| BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG( |
| actor |
| , (namespace_seq)(name) |
| , (child_grammar0) |
| (child_grammar1) |
| ... |
| (child_grammarN) |
| , N |
| ) |
| |
| [heading Semantics] |
| |
| The above macro generates the necessary code for an expression `name` in |
| namespace `namespace_seq`. `N` is the maximum number of variable children. |
| All but the last elements in the grammar sequence are required children of |
| the expression, and the last denotes a variable number of children. The number |
| of children an expression of this kind can hold is therefor `N-1` plus the size of |
| the sequence |
| |
| The macro should be used at global scope. `namespace_seq` shall be the sequence |
| of namespaces under which the following symbols will be defined: |
| |
| namespace tag |
| { |
| struct name; |
| } |
| |
| namespace expression |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct name |
| : boost::phoenix::expr_ext< |
| actor |
| , tag::name |
| , A0 |
| , A1 |
| ... |
| , AN |
| > |
| {}; |
| } |
| |
| namespace rule |
| { |
| struct name |
| : expression::name< |
| child_grammar0 |
| , child_grammar1 |
| ... |
| , proto::vararg<child_grammarN> |
| > |
| {}; |
| } |
| |
| namespace functional |
| { |
| struct make_name; // A polymorphic function object that can be called to create the expression node |
| } |
| |
| namespace result_of |
| { |
| template <typename A0, typename A1 ... typename AN> |
| struct make_name; // The result type of the expression node |
| } |
| |
| // convenience polymorphic function to create an expression node |
| template <typename A0, typename A1 ... typename AN> |
| result_of::make_name<A0, A1 ... AN> |
| make_name(A0 const & a0, A1 const & a1 ... AN const & an); |
| |
| This macros also adds a specialization for `meta_grammar::case_<tag::name>` to |
| enable the rule for further use in actions. |
| |
| [heading Header] |
| |
| #include <boost/phoenix/core/expression.hpp> |
| |
| [heading Example] |
| |
| TBD |
| |
| [endsect] |
| |
| [endsect] |
| |
| [endsect] |