Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/spirit/phoenix/example/fundamental/sample9.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 9.8 KB
Line 
1/*=============================================================================
2    Phoenix V1.2.1
3    Copyright (c) 2001-2003 Joel de Guzman
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8==============================================================================*/
9#include <vector>
10#include <algorithm>
11#include <iostream>
12
13#define PHOENIX_LIMIT 5
14#include <boost/spirit/phoenix/operators.hpp>
15#include <boost/spirit/phoenix/primitives.hpp>
16#include <boost/spirit/phoenix/composite.hpp>
17#include <boost/spirit/phoenix/special_ops.hpp>
18#include <boost/spirit/phoenix/statements.hpp>
19
20namespace phoenix {
21
22///////////////////////////////////////////////////////////////////////////////
23//
24//  local_tuple
25//
26//      This *is a* tuple like the one we see in TupleT in any actor
27//      base class' eval member function. local_tuple should look and
28//      feel the same as a tupled-args, that's why it is derived from
29//      TupleArgsT. It has an added member, locs which is another tuple
30//      where the local variables will be stored. locs is mutable to
31//      allow read-write access to our locals regardless of
32//      local_tuple's constness (The eval member function accepts it as
33//      a const argument).
34//
35///////////////////////////////////////////////////////////////////////////////
36template <typename TupleArgsT, typename TupleLocsT>
37struct local_tuple : public TupleArgsT {
38
39    typedef TupleLocsT local_vars_t;
40    typedef TupleArgsT parent_t;
41
42    local_tuple(TupleArgsT const& args, TupleLocsT const& locs_)
43    :   TupleArgsT(args), locs(locs_) {}
44
45    TupleArgsT&         parent()        { return *this; }
46    TupleArgsT const&   parent() const  { return *this; }
47
48    mutable TupleLocsT locs;
49};
50
51///////////////////////////////////////////////////////////////////////////////
52//
53//  local_var_result
54//
55//      This is a return type computer. Given a constant integer N, a
56//      parent index and a tuple, get the Nth local variable type. The
57//      parent index is an integer specifying which parent scope to
58//      access; 0==current scope, 1==parent scope, 2==parent's parent
59//      scope.
60//
61//      This is a metaprogram with partial specializations. There is a
62//      general case, a special case for local_tuples and a terminating
63//      special case for local_tuples.
64//
65//      General case: If TupleT is not really a local_tuple, we just return nil_t.
66//
67//      local_tuples case:
68//          Parent index is 0: We get the Nth local variable.
69//          Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT>
70//
71///////////////////////////////////////////////////////////////////////////////
72template <int N, int Parent, typename TupleT>
73struct local_var_result {
74
75    typedef nil_t type;
76};
77
78//////////////////////////////////
79template <int N, int Parent, typename TupleArgsT, typename TupleLocsT>
80struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> >
81:   public local_var_result<N, Parent-1, TupleArgsT> {};
82
83//////////////////////////////////
84template <int N, typename TupleArgsT, typename TupleLocsT>
85struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > {
86
87    typedef typename tuple_element<
88        N, TupleLocsT
89    >::type& type;
90
91    static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple)
92    { return tuple.locs[tuple_index<N>()]; }
93};
94
95///////////////////////////////////////////////////////////////////////////////
96//
97//  local_var
98//
99//      This class looks so curiously like the argument class. local_var
100//      provides access to the Nth local variable packed in the tuple
101//      duo local_tuple above. Parent specifies the Nth parent scope.
102//      0==current scope, 1==parent scope, 2==parent's parent scope. The
103//      member function parent<N>() may be called to provide access to
104//      outer scopes.
105//
106//      Note that the member function eval expects a local_tuple
107//      argument. Otherwise there will be acompile-time error. local_var
108//      primitives only work within the context of a context_composite
109//      (see below).
110//
111//      Provided are some predefined local_var actors for 0..N local
112//      variable access: loc1..locN.
113//
114///////////////////////////////////////////////////////////////////////////////
115template <int N, int Parent = 0>
116struct local_var {
117
118    template <typename TupleT>
119    struct result {
120
121        typedef typename local_var_result<N, Parent, TupleT>::type type;
122    };
123
124    template <typename TupleT>
125    typename local_var_result<N, Parent, TupleT>::type
126    eval(TupleT const& tuple) const
127    {
128        return local_var_result<N, Parent, TupleT>::get(tuple);
129    }
130
131    template <int PIndex>
132    actor<local_var<N, Parent+PIndex> >
133    parent() const
134    {
135        return local_var<N, Parent+PIndex>();
136    }
137};
138
139//////////////////////////////////
140namespace locals {
141
142    actor<local_var<0> > const result   = local_var<0>();
143    actor<local_var<1> > const loc1     = local_var<1>();
144    actor<local_var<2> > const loc2     = local_var<2>();
145    actor<local_var<3> > const loc3     = local_var<3>();
146    actor<local_var<4> > const loc4     = local_var<4>();
147}
148
149///////////////////////////////////////////////////////////////////////////////
150//
151//  context_composite
152//
153//      This class encapsulates an actor and some local variable
154//      initializers packed in a tuple.
155//
156//      context_composite is just like a proxy and delegates the actual
157//      evaluation to the actor. The actor does the actual work. In the
158//      eval member function, before invoking the embedded actor's eval
159//      member function, we first stuff an instance of our locals and
160//      bundle both 'args' and 'locals' in a local_tuple. This
161//      local_tuple instance is created in the stack initializing it
162//      with our locals member. We then pass this local_tuple instance
163//      as an argument to the actor's eval member function.
164//
165///////////////////////////////////////////////////////////////////////////////
166template <typename ActorT, typename LocsT>
167struct context_composite {
168
169    typedef context_composite<ActorT, LocsT> self_t;
170
171    template <typename TupleT>
172    struct result { typedef typename tuple_element<0, LocsT>::type type; };
173
174    context_composite(ActorT const& actor_, LocsT const& locals_)
175    :   actor(actor_), locals(locals_) {}
176
177    template <typename TupleT>
178    typename tuple_element<0, LocsT>::type
179    eval(TupleT const& args) const
180    {
181        local_tuple<TupleT, LocsT>  local_context(args, locals);
182        actor.eval(local_context);
183        return local_context.locs[tuple_index<0>()];
184    }
185
186    ActorT actor;
187    LocsT locals;
188};
189
190///////////////////////////////////////////////////////////////////////////////
191//
192//  context_gen
193//
194//      At construction time, this class is given some local var-
195//      initializers packed in a tuple. We just store this for later.
196//      The operator[] of this class creates the actual context_composite
197//      given an actor. This is responsible for the construct
198//      context<types>[actor].
199//
200///////////////////////////////////////////////////////////////////////////////
201template <typename LocsT>
202struct context_gen {
203
204    context_gen(LocsT const& locals_)
205    :   locals(locals_) {}
206
207    template <typename ActorT>
208    actor<context_composite<typename as_actor<ActorT>::type, LocsT> >
209    operator[](ActorT const& actor)
210    {
211        return context_composite<typename as_actor<ActorT>::type, LocsT>
212            (as_actor<ActorT>::convert(actor), locals);
213    }
214
215    LocsT locals;
216};
217
218///////////////////////////////////////////////////////////////////////////////
219//
220//    Front end generator functions. These generators are overloaded for
221//    1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen
222//    objects (see above).
223//
224///////////////////////////////////////////////////////////////////////////////
225template <typename T0>
226inline context_gen<tuple<T0> >
227context()
228{
229    typedef tuple<T0> tuple_t;
230    return context_gen<tuple_t>(tuple_t(T0()));
231}
232
233//////////////////////////////////
234template <typename T0, typename T1>
235inline context_gen<tuple<T0, T1> >
236context(
237    T1 const& _1 = T1()
238)
239{
240    typedef tuple<T0, T1> tuple_t;
241    return context_gen<tuple_t>(tuple_t(T0(), _1));
242}
243
244//////////////////////////////////
245template <typename T0, typename T1, typename T2>
246inline context_gen<tuple<T0, T1, T2> >
247context(
248    T1 const& _1 = T1(),
249    T2 const& _2 = T2()
250)
251{
252    typedef tuple<T0, T1, T2> tuple_t;
253    return context_gen<tuple_t>(tuple_t(T0(), _1, _2));
254}
255
256//////////////////////////////////
257template <typename T0, typename T1, typename T2, typename T3>
258inline context_gen<tuple<T0, T1, T2, T3> >
259context(
260    T1 const& _1 = T1(),
261    T2 const& _2 = T2(),
262    T3 const& _3 = T3()
263)
264{
265    typedef tuple<T0, T1, T2, T3> tuple_t;
266    return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3));
267}
268
269//////////////////////////////////
270template <typename T0, typename T1, typename T2, typename T3, typename T4>
271inline context_gen<tuple<T0, T1, T2, T3, T4> >
272context(
273    T1 const& _1 = T1(),
274    T2 const& _2 = T2(),
275    T3 const& _3 = T3(),
276    T4 const& _4 = T4()
277)
278{
279    typedef tuple<T0, T1, T2, T3> tuple_t;
280    return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4));
281}
282
283///////////////////////////////////////////////////////////////////////////////
284}
285
286//////////////////////////////////
287using namespace std;
288using namespace phoenix;
289using namespace phoenix::locals;
290
291//////////////////////////////////
292int
293main()
294{
295    context<nil_t>(1)
296    [
297        cout << loc1 << '\n',
298        context<nil_t>(2)
299        [
300            cout << loc1.parent<1>() << ' ' << loc1 << '\n',
301            context<nil_t>(3)
302            [
303                cout << loc1.parent<2>() << ' ' << loc1.parent<1>() << ' ' << loc1 << '\n'
304            ]
305        ]
306    ]
307
308    ();
309
310    return 0;
311}
Note: See TracBrowser for help on using the repository browser.