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 Adding an expression]
11
12This is not a toy example. This is actually part of the library. Remember the
13[link phoenix.modules.statement.while__statement `while`] lazy statement? Putting together
14everything we've learned so far, we eill present it here in its entirety
15(verbatim):
16
17    BOOST_PHOENIX_DEFINE_EXPRESSION(
18        (boost)(phoenix)(while_)
19      , (meta_grammar)           // Cond
20        (meta_grammar)           // Do
21    )
22
23    namespace boost { namespace phoenix
24    {
25        struct while_eval
26        {
27            typedef void result_type;
28
29            template <typename Cond, typename Do, typename Context>
30            result_type
31            operator()(Cond const& cond, Do const& do_, Context & ctx) const
32            {
33                while(eval(cond, ctx))
34                {
35                    eval(do_, ctx);
36                }
37            }
38        };
39
40        template <typename Dummy>
41        struct default_actions::when<rule::while_, Dummy>
42            : call<while_eval, Dummy>
43        {};
44
45        template <typename Cond>
46        struct while_gen
47        {
48            while_gen(Cond const& cond) : cond(cond) {}
49
50            template <typename Do>
51            typename expression::while_<Cond, Do>::type const
52            operator[](Do const& do_) const
53            {
54                return expression::while_<Cond, Do>::make(cond, do_);
55            }
56
57            Cond const& cond;
58        };
59
60        template <typename Cond>
61        while_gen<Cond> const
62        while_(Cond const& cond)
63        {
64            return while_gen<Cond>(cond);
65        }
66    }}
67
68`while_eval` is an example of how to evaluate an expression. It gets called in
69the `rule::while` action. `while_gen` and `while_` are the expression template
70front ends. Let's break this apart to undestand what's happening. Let's start at
71the bottom. It's easier that way.
72
73When you write:
74
75    while_(cond)
76
77we generate an instance of `while_gen<Cond>`, where `Cond` is the type of `cond`.
78`cond` can be an arbitrarily complex actor expression. The `while_gen` template
79class has an `operator[]` accepting another expression. If we write:
80
81    while_(cond)
82    [
83        do_
84    ]
85
86it will generate a proper composite with the type:
87
88    expression::while_<Cond, Do>::type
89
90where `Cond` is the type of `cond` and `Do` is the type of `do_`. Notice how we are using Phoenix's
91[link phoenix.inside.expression Expression] mechanism here
92
93    template <typename Do>
94    typename expression::while_<Cond, Do>::type const
95    operator[](Do const& do_) const
96    {
97        return expression::while_<Cond, Do>::make(cond, do_);
98    }
99
100Finally, the `while_eval` does its thing:
101
102    while(eval(cond, ctx))
103    {
104        eval(do_, ctx);
105    }
106
107`cond` and `do_`, at this point, are instances of [link phoenix.inside.actor Actor]. `cond` and `do_` are the [link phoenix.inside.actor Actors]
108passed as parameters by `call`, ctx is the [link phoenix.inside.actor Context]
109
110[endsect]
111
112