argument.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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_ARGUMENT_FEBRUARY_17_2007_0339PM)
  9. #define BOOST_SPIRIT_ARGUMENT_FEBRUARY_17_2007_0339PM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  14. #include <boost/preprocessor/arithmetic/inc.hpp>
  15. #include <boost/spirit/include/phoenix_core.hpp>
  16. #include <boost/spirit/home/support/assert_msg.hpp>
  17. #include <boost/spirit/home/support/limits.hpp>
  18. #include <boost/fusion/include/at.hpp>
  19. #include <boost/fusion/include/size.hpp>
  20. #include <boost/mpl/size.hpp>
  21. #include <boost/mpl/at.hpp>
  22. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  23. #define SPIRIT_DECLARE_ARG(z, n, data) \
  24. typedef phoenix::actor<argument<n> > \
  25. BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type); \
  26. phoenix::actor<argument<n> > const \
  27. BOOST_PP_CAT(_, BOOST_PP_INC(n)) = \
  28. BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type)(); \
  29. /***/
  30. #define SPIRIT_USING_ARGUMENT(z, n, data) \
  31. using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_, n), _type); \
  32. using spirit::BOOST_PP_CAT(_, n); \
  33. /***/
  34. #else
  35. #define SPIRIT_DECLARE_ARG(z, n, data) \
  36. typedef phoenix::actor<argument<n> > \
  37. BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type); \
  38. /***/
  39. #define SPIRIT_USING_ARGUMENT(z, n, data) \
  40. using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_, n), _type); \
  41. /***/
  42. #endif
  43. namespace boost { namespace spirit
  44. {
  45. template <int N>
  46. struct argument;
  47. template <typename Dummy>
  48. struct attribute_context;
  49. }}
  50. BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(
  51. template <int N>
  52. , boost::spirit::argument<N>
  53. , mpl::false_ // is not nullary
  54. , v2_eval(
  55. proto::make<
  56. boost::spirit::argument<N>()
  57. >
  58. , proto::call<
  59. functional::env(proto::_state)
  60. >
  61. )
  62. )
  63. BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(
  64. template <typename Dummy>
  65. , boost::spirit::attribute_context<Dummy>
  66. , mpl::false_ // is not nullary
  67. , v2_eval(
  68. proto::make<
  69. boost::spirit::attribute_context<Dummy>()
  70. >
  71. , proto::call<
  72. functional::env(proto::_state)
  73. >
  74. )
  75. )
  76. namespace boost { namespace spirit
  77. {
  78. namespace result_of
  79. {
  80. template <typename Sequence, int N>
  81. struct get_arg
  82. {
  83. typedef typename
  84. fusion::result_of::size<Sequence>::type
  85. sequence_size;
  86. // report invalid argument not found (N is out of bounds)
  87. BOOST_SPIRIT_ASSERT_MSG(
  88. (N < sequence_size::value),
  89. index_is_out_of_bounds, ());
  90. typedef typename
  91. fusion::result_of::at_c<Sequence, N>::type
  92. type;
  93. static type call(Sequence& seq)
  94. {
  95. return fusion::at_c<N>(seq);
  96. }
  97. };
  98. template <typename Sequence, int N>
  99. struct get_arg<Sequence&, N> : get_arg<Sequence, N>
  100. {
  101. };
  102. }
  103. template <int N, typename T>
  104. typename result_of::get_arg<T, N>::type
  105. get_arg(T& val)
  106. {
  107. return result_of::get_arg<T, N>::call(val);
  108. }
  109. template <typename>
  110. struct attribute_context
  111. {
  112. typedef mpl::true_ no_nullary;
  113. template <typename Env>
  114. struct result
  115. {
  116. // FIXME: is this remove_const really necessary?
  117. typedef typename
  118. remove_const<
  119. typename mpl::at_c<typename Env::args_type, 0>::type
  120. >::type
  121. type;
  122. };
  123. template <typename Env>
  124. typename result<Env>::type
  125. eval(Env const& env) const
  126. {
  127. return fusion::at_c<0>(env.args());
  128. }
  129. };
  130. template <int N>
  131. struct argument
  132. {
  133. typedef mpl::true_ no_nullary;
  134. template <typename Env>
  135. struct result
  136. {
  137. typedef typename
  138. mpl::at_c<typename Env::args_type, 0>::type
  139. arg_type;
  140. typedef typename result_of::get_arg<arg_type, N>::type type;
  141. };
  142. template <typename Env>
  143. typename result<Env>::type
  144. eval(Env const& env) const
  145. {
  146. return get_arg<N>(fusion::at_c<0>(env.args()));
  147. }
  148. };
  149. // _0 refers to the whole attribute as generated by the lhs parser
  150. typedef phoenix::actor<attribute_context<void> > _0_type;
  151. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  152. _0_type const _0 = _0_type();
  153. #endif
  154. // _1, _2, ... refer to the attributes of the single components the lhs
  155. // parser is composed of
  156. typedef phoenix::actor<argument<0> > _1_type;
  157. typedef phoenix::actor<argument<1> > _2_type;
  158. typedef phoenix::actor<argument<2> > _3_type;
  159. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  160. _1_type const _1 = _1_type();
  161. _2_type const _2 = _2_type();
  162. _3_type const _3 = _3_type();
  163. #endif
  164. // '_pass' may be used to make a match fail in retrospective
  165. typedef phoenix::arg_names::_3_type _pass_type;
  166. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  167. _pass_type const _pass = _pass_type();
  168. #endif
  169. // Bring in the rest of the arguments and attributes (_4 .. _N+1), using PP
  170. BOOST_PP_REPEAT_FROM_TO(
  171. 3, SPIRIT_ARGUMENTS_LIMIT, SPIRIT_DECLARE_ARG, _)
  172. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  173. // You can bring these in with the using directive
  174. // without worrying about bringing in too much.
  175. namespace labels
  176. {
  177. BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
  178. }
  179. #endif
  180. }}
  181. #undef SPIRIT_DECLARE_ARG
  182. #endif