123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- [/==============================================================================
- 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:actions More on Actions]
- As you know from the [link phoenix.inside.actor Actors in Detail] section,
- Actions are what brings life to a Phoenix expression tree.
- When dealing with a Phoenix expression tree, it gets evaluated top-down.
- Example:
- _1 + 3 * _2
- Can be visualized as an AST in the following way:
- [$images/simple_ast.png]
- In terms of actions this means:
- * `rule::plus` is matched
- * evaluate left:
- * `rule::placeholder` is matched
- * evaluate right:
- * `rule::multiplies` is matched
- * evaluate left:
- * `rule::value` is matched
- * evaluate right:
- * `rule::placeholder` is matched
- Every time a rule is matched, an action will be called. The action determines
- how the Phoenix AST will be traversed.
- [heading Writing an Action]
- As mentioned in [link phoenix.inside.actor Actors in Detail] actions are
- __proto_primitive_transforms__ for convenience Phoenix provides an abstraction
- to this:
- template <typename Fun>
- struct call;
- This is similar to __proto_call__ but does more. It calls the `Fun` function
- object passed as template parameter with the `Context` and the children of the
- expression associated with the rule.
- Lets have an (simplified) example on how to write an evaluation action for
- `rule::plus`:
- struct plus_eval
- {
- typedef int result_type;
- template <typename Lhs, typename Rhs, typename Context>
- result_type operator()(Lhs const& lhs, Rhs const &rhs, Context & ctx)
- {
- return eval(lhs, ctx) + eval(rhs, ctx);
- }
- };
- template <>
- struct default_actions::when<rule::plus>
- : call<plus_eval>
- {};
- That's it. When evaluating a `plus` expression, the `plus_eval` callable gets
- called with the left hand side and right hand side expression and the associated
- Context.
- [*But there is more:] As Actions /can/ be full fletched __proto_transforms__, you can
- in fact use any proto expression you can imagine as the action. Phoenix predifines a
- set of callables and transform to deal with the Context information passed along and
- of course every Phoenix expression can be used as a Phoenix grammar or
- __proto_pass_through_transform__.
- [variablelist
- [
- [`functional::context(Env, Actions)`]
- [A __proto_callable__ that creates a new context out of the `Env` and `Actions` parameter]
- ]
- [
- [`functional::env(Context)`]
- [A __proto_callable__ that returns the environment out of the `Context` parameter]
- ]
- [
- [`functional::actions(Context)`]
- [A __proto_callable__ that returns the actions out of the `Context` parameter]
- ]
- [
- [`_context`]
- [A __proto_primitive_transform__ that returns the current context]
- ]
- [
- [`_env`]
- [A __proto_primitive_transform__ that returns the current environment]
- ]
- [
- [`_actions`]
- [A __proto_primitive_transform__ that returns the current actions]
- ]
- [
- [`context(env, actions)`]
- [A regular function that creates a context]
- ]
- [
- [`env(ctx)`]
- [A regular function that returns the environment from the given context]
- ]
- [
- [`actions(ctx)`]
- [A regular function that returns the actions from the given context]
- ]
- ]
- Phoenix is equipped with a predefined set of expressions, rules and actions to
- make all the stuff work you learned in the __phoenix_starter_kit__ and __phoenix_modules__
- sections. See the [link phoenix.inside.rules next section] for more details!
- [endsect]
|