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