123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- [/==============================================================================
- 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]
|