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 contextboost::spirit::context100 context(typename Attributes::car_type attribute) 101 : attributes(attribute, fusion::nil()), locals() {} 102 103 template <typename Args, typename Context> contextboost::spirit::context104 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 contextboost::spirit::context119 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 evalboost::spirit::attribute191 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 evalboost::spirit::local_variable227 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 300