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