argument.hpp 6.5 KB

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