]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/spirit/home/support/context.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / spirit / home / support / context.hpp
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