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:actions More on Actions] 11 12As you know from the [link phoenix.inside.actor Actors in Detail] section, 13Actions are what brings life to a Phoenix expression tree. 14 15When dealing with a Phoenix expression tree, it gets evaluated top-down. 16Example: 17 18 _1 + 3 * _2 19 20Can be visualized as an AST in the following way: 21 22[$images/simple_ast.png] 23 24In terms of actions this means: 25 26* `rule::plus` is matched 27* evaluate left: 28 * `rule::placeholder` is matched 29* evaluate right: 30 * `rule::multiplies` is matched 31 * evaluate left: 32 * `rule::value` is matched 33 * evaluate right: 34 * `rule::placeholder` is matched 35 36Every time a rule is matched, an action will be called. The action determines 37how the Phoenix AST will be traversed. 38 39[heading Writing an Action] 40 41As mentioned in [link phoenix.inside.actor Actors in Detail] actions are 42__proto_primitive_transforms__ for convenience Phoenix provides an abstraction 43to this: 44 45 template <typename Fun> 46 struct call; 47 48This is similar to __proto_call__ but does more. It calls the `Fun` function 49object passed as template parameter with the `Context` and the children of the 50expression associated with the rule. 51 52Lets have an (simplified) example on how to write an evaluation action for 53`rule::plus`: 54 55 struct plus_eval 56 { 57 typedef int result_type; 58 59 template <typename Lhs, typename Rhs, typename Context> 60 result_type operator()(Lhs const& lhs, Rhs const &rhs, Context & ctx) 61 { 62 return eval(lhs, ctx) + eval(rhs, ctx); 63 } 64 }; 65 66 template <> 67 struct default_actions::when<rule::plus> 68 : call<plus_eval> 69 {}; 70 71That's it. When evaluating a `plus` expression, the `plus_eval` callable gets 72called with the left hand side and right hand side expression and the associated 73Context. 74 75[*But there is more:] As Actions /can/ be full fletched __proto_transforms__, you can 76in fact use any proto expression you can imagine as the action. Phoenix predifines a 77set of callables and transform to deal with the Context information passed along and 78of course every Phoenix expression can be used as a Phoenix grammar or 79__proto_pass_through_transform__. 80 81[variablelist 82 [ 83 [`functional::context(Env, Actions)`] 84 [A __proto_callable__ that creates a new context out of the `Env` and `Actions` parameter] 85 ] 86 [ 87 [`functional::env(Context)`] 88 [A __proto_callable__ that returns the environment out of the `Context` parameter] 89 ] 90 [ 91 [`functional::actions(Context)`] 92 [A __proto_callable__ that returns the actions out of the `Context` parameter] 93 ] 94 [ 95 [`_context`] 96 [A __proto_primitive_transform__ that returns the current context] 97 ] 98 [ 99 [`_env`] 100 [A __proto_primitive_transform__ that returns the current environment] 101 ] 102 [ 103 [`_actions`] 104 [A __proto_primitive_transform__ that returns the current actions] 105 ] 106 [ 107 [`context(env, actions)`] 108 [A regular function that creates a context] 109 ] 110 [ 111 [`env(ctx)`] 112 [A regular function that returns the environment from the given context] 113 ] 114 [ 115 [`actions(ctx)`] 116 [A regular function that returns the actions from the given context] 117 ] 118] 119 120Phoenix is equipped with a predefined set of expressions, rules and actions to 121make all the stuff work you learned in the __phoenix_starter_kit__ and __phoenix_modules__ 122sections. See the [link phoenix.inside.rules next section] for more details! 123 124[endsect] 125