context.hpp 9.0 KB

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