b63b71e9c8
[SVN r72412]
535 lines
14 KiB
Plaintext
535 lines
14 KiB
Plaintext
[/==============================================================================
|
|
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]
|