1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 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#if !defined(BOOST_SPIRIT_CONTEXT_OCTOBER_31_2008_0654PM)
10#define BOOST_SPIRIT_CONTEXT_OCTOBER_31_2008_0654PM
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/preprocessor/repetition/repeat_from_to.hpp>
17#include <boost/spirit/home/support/nonterminal/expand_arg.hpp>
18#include <boost/spirit/home/support/assert_msg.hpp>
19#include <boost/spirit/home/support/argument.hpp>
20#include <boost/spirit/home/support/limits.hpp>
21#include <boost/fusion/include/at.hpp>
22#include <boost/fusion/include/size.hpp>
23#include <boost/fusion/include/as_list.hpp>
24#include <boost/fusion/include/transform.hpp>
25#include <boost/mpl/size.hpp>
26#include <boost/mpl/at.hpp>
27#include <boost/phoenix/core/actor.hpp>
28#include <boost/phoenix/core/terminal.hpp>
29#include <boost/phoenix/core/v2_eval.hpp>
30#include <boost/proto/proto_fwd.hpp> // for transform placeholders
31
32///////////////////////////////////////////////////////////////////////////////
33#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
34
35#define SPIRIT_DECLARE_ATTRIBUTE(z, n, data) \
36 typedef phoenix::actor<attribute<n> > \
37 BOOST_PP_CAT(BOOST_PP_CAT(_r, n), _type); \
38 phoenix::actor<attribute<n> > const \
39 BOOST_PP_CAT(_r, n) = BOOST_PP_CAT(BOOST_PP_CAT(_r, n), _type)();
40 /***/
41#define SPIRIT_USING_ATTRIBUTE(z, n, data) \
42 using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_r, n), _type); \
43 using spirit::BOOST_PP_CAT(_r, n); \
44 /***/
45
46#else
47
48#define SPIRIT_DECLARE_ATTRIBUTE(z, n, data) \
49 typedef phoenix::actor<attribute<n> > \
50 BOOST_PP_CAT(BOOST_PP_CAT(_r, n), _type); \
51 /***/
52#define SPIRIT_USING_ATTRIBUTE(z, n, data) \
53 using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_r, n), _type); \
54 /***/
55
56#endif
57
58namespace boost { namespace spirit
59{
60 template <int>
61 struct attribute;
62
63 template <int>
64 struct local_variable;
65}}
66
67BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(
68 template <int N>
69 , boost::spirit::attribute<N>
70 , mpl::false_ // is not nullary
71 , v2_eval(
72 proto::make<
73 boost::spirit::attribute<N>()
74 >
75 , proto::call<
76 functional::env(proto::_state)
77 >
78 )
79)
80
81BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(
82 template <int N>
83 , boost::spirit::local_variable<N>
84 , mpl::false_ // is not nullary
85 , v2_eval(
86 proto::make<
87 boost::spirit::local_variable<N>()
88 >
89 , proto::call<
90 functional::env(proto::_state)
91 >
92 )
93)
94
95namespace boost { namespace spirit
96{
97 template <typename Attributes, typename Locals>
98 struct context
99 {
100 typedef Attributes attributes_type;
101 typedef Locals locals_type;
102
103 context(typename Attributes::car_type attribute)
104 : attributes(attribute, fusion::nil_()), locals() {}
105
106 template <typename Args, typename Context>
107 context(
108 typename Attributes::car_type attribute
109 , Args const& args
110 , Context& caller_context
111 ) : attributes(
112 attribute
113 , fusion::as_list(
114 fusion::transform(
115 args
116 , detail::expand_arg<Context>(caller_context)
117 )
118 )
119 )
120 , locals() {}
121
122 context(Attributes const& attributes_)
123 : attributes(attributes_), locals() {}
124
125 Attributes attributes; // The attributes
126 Locals locals; // Local variables
127 };
128
129 template <typename Context>
130 struct attributes_of
131 {
132 typedef typename Context::attributes_type type;
133 };
134
135 template <typename Context>
136 struct attributes_of<Context const>
137 {
138 typedef typename Context::attributes_type const type;
139 };
140
141 template <typename Context>
142 struct attributes_of<Context &>
143 : attributes_of<Context>
144 {};
145
146 template <typename Context>
147 struct locals_of
148 {
149 typedef typename Context::locals_type type;
150 };
151
152 template <typename Context>
153 struct locals_of<Context const>
154 {
155 typedef typename Context::locals_type const type;
156 };
157
158 template <typename Context>
159 struct locals_of<Context &>
160 {
161 typedef typename Context::locals_type type;
162 };
163
164 template <int N>
165 struct attribute
166 {
167 typedef mpl::true_ no_nullary;
168
169 template <typename Env>
170 struct result
171 {
172 typedef typename
173 attributes_of<typename
174 mpl::at_c<typename Env::args_type, 1>::type
175 >::type
176 attributes_type;
177
178 typedef typename
179 fusion::result_of::size<attributes_type>::type
180 attributes_size;
181
182 // report invalid argument not found (N is out of bounds)
183 BOOST_SPIRIT_ASSERT_MSG(
184 (N < attributes_size::value),
185 index_is_out_of_bounds, ());
186
187 typedef typename
188 fusion::result_of::at_c<attributes_type, N>::type
189 type;
190 };
191
192 template <typename Env>
193 typename result<Env>::type
194 eval(Env const& env) const
195 {
196 return fusion::at_c<N>((fusion::at_c<1>(env.args())).attributes);
197 }
198 };
199
200 template <int N>
201 struct local_variable
202 {
203 typedef mpl::true_ no_nullary;
204
205 template <typename Env>
206 struct result
207 {
208 typedef typename
209 locals_of<typename
210 mpl::at_c<typename Env::args_type, 1>::type
211 >::type
212 locals_type;
213
214 typedef typename
215 fusion::result_of::size<locals_type>::type
216 locals_size;
217
218 // report invalid argument not found (N is out of bounds)
219 BOOST_SPIRIT_ASSERT_MSG(
220 (N < locals_size::value),
221 index_is_out_of_bounds, ());
222
223 typedef typename
224 fusion::result_of::at_c<locals_type, N>::type
225 type;
226 };
227
228 template <typename Env>
229 typename result<Env>::type
230 eval(Env const& env) const
231 {
232 return get_arg<N>((fusion::at_c<1>(env.args())).locals);
233 }
234 };
235
236 typedef phoenix::actor<attribute<0> > _val_type;
237 typedef phoenix::actor<attribute<0> > _r0_type;
238 typedef phoenix::actor<attribute<1> > _r1_type;
239 typedef phoenix::actor<attribute<2> > _r2_type;
240
241#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
242 // _val refers to the 'return' value of a rule (same as _r0)
243 // _r1, _r2, ... refer to the rule arguments
244 _val_type const _val = _val_type();
245 _r0_type const _r0 = _r0_type();
246 _r1_type const _r1 = _r1_type();
247 _r2_type const _r2 = _r2_type();
248#endif
249
250 // Bring in the rest of the attributes (_r4 .. _rN+1), using PP
251 BOOST_PP_REPEAT_FROM_TO(
252 3, SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_DECLARE_ATTRIBUTE, _)
253
254 typedef phoenix::actor<local_variable<0> > _a_type;
255 typedef phoenix::actor<local_variable<1> > _b_type;
256 typedef phoenix::actor<local_variable<2> > _c_type;
257 typedef phoenix::actor<local_variable<3> > _d_type;
258 typedef phoenix::actor<local_variable<4> > _e_type;
259 typedef phoenix::actor<local_variable<5> > _f_type;
260 typedef phoenix::actor<local_variable<6> > _g_type;
261 typedef phoenix::actor<local_variable<7> > _h_type;
262 typedef phoenix::actor<local_variable<8> > _i_type;
263 typedef phoenix::actor<local_variable<9> > _j_type;
264
265#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
266 // _a, _b, ... refer to the local variables of a rule
267 _a_type const _a = _a_type();
268 _b_type const _b = _b_type();
269 _c_type const _c = _c_type();
270 _d_type const _d = _d_type();
271 _e_type const _e = _e_type();
272 _f_type const _f = _f_type();
273 _g_type const _g = _g_type();
274 _h_type const _h = _h_type();
275 _i_type const _i = _i_type();
276 _j_type const _j = _j_type();
277#endif
278
279 // You can bring these in with the using directive
280 // without worrying about bringing in too much.
281 namespace labels
282 {
283 BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
284 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
285
286#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
287 using spirit::_val;
288 using spirit::_a;
289 using spirit::_b;
290 using spirit::_c;
291 using spirit::_d;
292 using spirit::_e;
293 using spirit::_f;
294 using spirit::_g;
295 using spirit::_h;
296 using spirit::_i;
297 using spirit::_j;
298#endif
299 }
300}}
301
302#endif
303