• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
58 namespace boost { namespace spirit
59 {
60     template <int>
61     struct attribute;
62 
63     template <int>
64     struct local_variable;
65 }}
66 
67 BOOST_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 
81 BOOST_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 
95 namespace 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 
contextboost::spirit::context103         context(typename Attributes::car_type attribute)
104           : attributes(attribute, fusion::nil_()), locals() {}
105 
106         template <typename Args, typename Context>
contextboost::spirit::context107         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 
contextboost::spirit::context122         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
evalboost::spirit::attribute194         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
evalboost::spirit::local_variable230         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