1 /*=============================================================================
2 Phoenix V1.2.1
3 Copyright (c) 2001-2002 Joel de Guzman
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #ifndef BOOST_SPIRIT_CLASSIC_PHOENIX_PRIMITIVES_HPP
9 #define BOOST_SPIRIT_CLASSIC_PHOENIX_PRIMITIVES_HPP
10
11 ///////////////////////////////////////////////////////////////////////////////
12 #include <boost/spirit/home/classic/phoenix/actor.hpp>
13
14 ///////////////////////////////////////////////////////////////////////////////
15 namespace phoenix {
16
17 ///////////////////////////////////////////////////////////////////////////////
18 //
19 // argument class
20 //
21 // Lazy arguments
22 //
23 // An actor base class that extracts and returns the Nth argument
24 // from the argument list passed in the 'args' tuple in the eval
25 // member function (see actor.hpp). There are some predefined
26 // argument constants that can be used as actors (arg1..argN).
27 //
28 // The argument actor is a place-holder for the actual arguments
29 // passed by the client. For example, wherever arg1 is seen placed
30 // in a lazy function (see functions.hpp) or lazy operator (see
31 // operators.hpp), this will be replaced by the actual first
32 // argument in the actual function evaluation. Argument actors are
33 // essentially lazy arguments. A lazy argument is a full actor in
34 // its own right and can be evaluated through the actor's operator().
35 //
36 // Example:
37 //
38 // char c = 'A';
39 // int i = 123;
40 // const char* s = "Hello World";
41 //
42 // cout << arg1(c) << ' ';
43 // cout << arg1(i, s) << ' ';
44 // cout << arg2(i, s) << ' ';
45 //
46 // will print out "A 123 Hello World"
47 //
48 ///////////////////////////////////////////////////////////////////////////////
49 template <int N>
50 struct argument {
51
52 template <typename TupleT>
53 struct result { typedef typename tuple_element<N, TupleT>::type type; };
54
55 template <typename TupleT>
56 typename tuple_element<N, TupleT>::type
evalphoenix::argument57 eval(TupleT const& args) const
58 {
59 tuple_index<N> const idx;
60 return args[idx];
61 }
62 };
63
64 //////////////////////////////////
65 actor<argument<0> > const arg1 = argument<0>();
66 actor<argument<1> > const arg2 = argument<1>();
67 actor<argument<2> > const arg3 = argument<2>();
68
69 #if PHOENIX_LIMIT > 3
70 actor<argument<3> > const arg4 = argument<3>();
71 actor<argument<4> > const arg5 = argument<4>();
72 actor<argument<5> > const arg6 = argument<5>();
73
74 #if PHOENIX_LIMIT > 6
75 actor<argument<6> > const arg7 = argument<6>();
76 actor<argument<7> > const arg8 = argument<7>();
77 actor<argument<8> > const arg9 = argument<8>();
78
79 #if PHOENIX_LIMIT > 9
80 actor<argument<9> > const arg10 = argument<9>();
81 actor<argument<10> > const arg11 = argument<10>();
82 actor<argument<11> > const arg12 = argument<11>();
83
84 #if PHOENIX_LIMIT > 12
85 actor<argument<12> > const arg13 = argument<12>();
86 actor<argument<13> > const arg14 = argument<13>();
87 actor<argument<14> > const arg15 = argument<14>();
88
89 #endif
90 #endif
91 #endif
92 #endif
93 ///////////////////////////////////////////////////////////////////////////////
94 //
95 // value class
96 //
97 // Lazy values
98 //
99 // A bound actual parameter is kept in a value class for deferred
100 // access later when needed. A value object is immutable. Value
101 // objects are typically created through the val(x) free function
102 // which returns a value<T> with T deduced from the type of x. x is
103 // held in the value<T> object by value.
104 //
105 // Lazy values are actors. As such, lazy values can be evaluated
106 // through the actor's operator(). Such invocation gives the value's
107 // identity. Example:
108 //
109 // cout << val(3)() << val("Hello World")();
110 //
111 // prints out "3 Hello World"
112 //
113 ///////////////////////////////////////////////////////////////////////////////
114 template <typename T>
115 struct value {
116
117 typedef typename boost::remove_reference<T>::type plain_t;
118
119 template <typename TupleT>
120 struct result { typedef plain_t const type; };
121
valuephoenix::value122 value(plain_t val_)
123 : val(val_) {}
124
125 template <typename TupleT>
126 plain_t const
evalphoenix::value127 eval(TupleT const& /*args*/) const
128 {
129 return val;
130 }
131
132 plain_t val;
133 };
134
135 //////////////////////////////////
136 template <typename T>
137 inline actor<value<T> > const
val(T v)138 val(T v)
139 {
140 return value<T>(v);
141 }
142
143 //////////////////////////////////
144 template <typename BaseT>
145 void
146 val(actor<BaseT> const& v); // This is undefined and not allowed.
147
148 ///////////////////////////////////////////////////////////////////////////
149 //
150 // Arbitrary types T are typically converted to a actor<value<T> >
151 // (see as_actor<T> in actor.hpp). A specialization is also provided
152 // for arrays. T[N] arrays are converted to actor<value<T const*> >.
153 //
154 ///////////////////////////////////////////////////////////////////////////
155 template <typename T>
156 struct as_actor {
157
158 typedef actor<value<T> > type;
convertphoenix::as_actor159 static type convert(T const& x)
160 { return value<T>(x); }
161 };
162
163 //////////////////////////////////
164 template <typename T, int N>
165 struct as_actor<T[N]> {
166
167 typedef actor<value<T const*> > type;
convertphoenix::as_actor168 static type convert(T const x[N])
169 { return value<T const*>(x); }
170 };
171
172 ///////////////////////////////////////////////////////////////////////////////
173 //
174 // variable class
175 //
176 // Lazy variables
177 //
178 // A bound actual parameter may also be held by non-const reference
179 // in a variable class for deferred access later when needed. A
180 // variable object is mutable, i.e. its referenced variable can be
181 // modified. Variable objects are typically created through the
182 // var(x) free function which returns a variable<T> with T deduced
183 // from the type of x. x is held in the value<T> object by
184 // reference.
185 //
186 // Lazy variables are actors. As such, lazy variables can be
187 // evaluated through the actor's operator(). Such invocation gives
188 // the variables's identity. Example:
189 //
190 // int i = 3;
191 // char const* s = "Hello World";
192 // cout << var(i)() << var(s)();
193 //
194 // prints out "3 Hello World"
195 //
196 // Another free function const_(x) may also be used. const_(x) creates
197 // a variable<T const&> object using a constant reference.
198 //
199 ///////////////////////////////////////////////////////////////////////////////
200 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
201 #pragma warning(push)
202 #pragma warning(disable:4512) //assignment operator could not be generated
203 #endif
204
205 template <typename T>
206 struct variable {
207
208 template <typename TupleT>
209 struct result { typedef T& type; };
210
variablephoenix::variable211 variable(T& var_)
212 : var(var_) {}
213
214 template <typename TupleT>
215 T&
evalphoenix::variable216 eval(TupleT const& /*args*/) const
217 {
218 return var;
219 }
220
221 T& var;
222 };
223
224 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
225 #pragma warning(pop)
226 #endif
227
228 //////////////////////////////////
229 template <typename T>
230 inline actor<variable<T> > const
var(T & v)231 var(T& v)
232 {
233 return variable<T>(v);
234 }
235
236 //////////////////////////////////
237 template <typename T>
238 inline actor<variable<T const> > const
const_(T const & v)239 const_(T const& v)
240 {
241 return variable<T const>(v);
242 }
243
244 //////////////////////////////////
245 template <typename BaseT>
246 void
247 var(actor<BaseT> const& v); // This is undefined and not allowed.
248
249 //////////////////////////////////
250 template <typename BaseT>
251 void
252 const_(actor<BaseT> const& v); // This is undefined and not allowed.
253
254 ///////////////////////////////////////////////////////////////////////////////
255 } // namespace phoenix
256
257 #endif
258