action.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #if !defined(SPIRIT_ACTION_JANUARY_07_2007_1128AM)
  7. #define SPIRIT_ACTION_JANUARY_07_2007_1128AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/meta_compiler.hpp>
  12. #include <boost/spirit/home/qi/parser.hpp>
  13. #include <boost/spirit/home/qi/detail/attributes.hpp>
  14. #include <boost/spirit/home/support/argument.hpp>
  15. #include <boost/spirit/home/support/context.hpp>
  16. #include <boost/spirit/home/support/unused.hpp>
  17. #include <boost/spirit/home/support/info.hpp>
  18. #include <boost/spirit/home/support/action_dispatch.hpp>
  19. #include <boost/spirit/home/support/handles_container.hpp>
  20. #include <boost/mpl/bool.hpp>
  21. #include <boost/mpl/if.hpp>
  22. #include <boost/type_traits/remove_const.hpp>
  23. #include <boost/type_traits/is_same.hpp>
  24. namespace boost { namespace spirit { namespace qi
  25. {
  26. BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
  27. template <typename Subject, typename Action>
  28. struct action : unary_parser<action<Subject, Action> >
  29. {
  30. typedef Subject subject_type;
  31. typedef Action action_type;
  32. template <typename Context, typename Iterator>
  33. struct attribute
  34. : traits::attribute_of<Subject, Context, Iterator>
  35. {};
  36. action(Subject const& subject_, Action f_)
  37. : subject(subject_), f(f_) {}
  38. #ifndef BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT
  39. template <typename Iterator, typename Context
  40. , typename Skipper, typename Attribute>
  41. bool parse(Iterator& first, Iterator const& last
  42. , Context& context, Skipper const& skipper
  43. , Attribute& attr_) const
  44. {
  45. typedef typename attribute<Context, Iterator>::type attr_type;
  46. // create an attribute if one is not supplied
  47. typedef traits::transform_attribute<
  48. Attribute, attr_type, domain> transform;
  49. typename transform::type attr = transform::pre(attr_);
  50. Iterator save = first;
  51. if (subject.parse(first, last, context, skipper, attr))
  52. {
  53. // call the function, passing the attribute, the context.
  54. // The client can return false to fail parsing.
  55. if (traits::action_dispatch<Subject>()(f, attr, context))
  56. {
  57. // Do up-stream transformation, this integrates the results
  58. // back into the original attribute value, if appropriate.
  59. transform::post(attr_, attr);
  60. return true;
  61. }
  62. // reset iterators if semantic action failed the match
  63. // retrospectively
  64. first = save;
  65. }
  66. return false;
  67. }
  68. #else
  69. template <typename Iterator, typename Context
  70. , typename Skipper, typename Attribute>
  71. bool parse(Iterator& first, Iterator const& last
  72. , Context& context, Skipper const& skipper
  73. , Attribute& attr) const
  74. {
  75. Iterator save = first;
  76. if (subject.parse(first, last, context, skipper, attr)) // Use the attribute as-is
  77. {
  78. // call the function, passing the attribute, the context.
  79. // The client can return false to fail parsing.
  80. if (traits::action_dispatch<Subject>()(f, attr, context))
  81. return true;
  82. // reset iterators if semantic action failed the match
  83. // retrospectively
  84. first = save;
  85. }
  86. return false;
  87. }
  88. template <typename Iterator, typename Context
  89. , typename Skipper>
  90. bool parse(Iterator& first, Iterator const& last
  91. , Context& context, Skipper const& skipper
  92. , unused_type) const
  93. {
  94. typedef typename attribute<Context, Iterator>::type attr_type;
  95. // synthesize the attribute since one is not supplied
  96. attr_type attr = attr_type();
  97. Iterator save = first;
  98. if (subject.parse(first, last, context, skipper, attr))
  99. {
  100. // call the function, passing the attribute, the context.
  101. // The client can return false to fail parsing.
  102. if (traits::action_dispatch<Subject>()(f, attr, context))
  103. return true;
  104. // reset iterators if semantic action failed the match
  105. // retrospectively
  106. first = save;
  107. }
  108. return false;
  109. }
  110. #endif
  111. template <typename Context>
  112. info what(Context& context) const
  113. {
  114. // the action is transparent (does not add any info)
  115. return subject.what(context);
  116. }
  117. Subject subject;
  118. Action f;
  119. // silence MSVC warning C4512: assignment operator could not be generated
  120. BOOST_DELETED_FUNCTION(action& operator= (action const&))
  121. };
  122. }}}
  123. namespace boost { namespace spirit
  124. {
  125. // Qi action meta-compiler
  126. template <>
  127. struct make_component<qi::domain, tag::action>
  128. {
  129. template <typename Sig>
  130. struct result;
  131. template <typename This, typename Elements, typename Modifiers>
  132. struct result<This(Elements, Modifiers)>
  133. {
  134. typedef typename
  135. remove_const<typename Elements::car_type>::type
  136. subject_type;
  137. typedef typename
  138. remove_const<typename Elements::cdr_type::car_type>::type
  139. action_type;
  140. typedef qi::action<subject_type, action_type> type;
  141. };
  142. template <typename Elements>
  143. typename result<make_component(Elements, unused_type)>::type
  144. operator()(Elements const& elements, unused_type) const
  145. {
  146. typename result<make_component(Elements, unused_type)>::type
  147. result(elements.car, elements.cdr.car);
  148. return result;
  149. }
  150. };
  151. }}
  152. namespace boost { namespace spirit { namespace traits
  153. {
  154. ///////////////////////////////////////////////////////////////////////////
  155. template <typename Subject, typename Action>
  156. struct has_semantic_action<qi::action<Subject, Action> >
  157. : mpl::true_ {};
  158. ///////////////////////////////////////////////////////////////////////////
  159. template <typename Subject, typename Action, typename Attribute
  160. , typename Context, typename Iterator>
  161. struct handles_container<qi::action<Subject, Action>, Attribute
  162. , Context, Iterator>
  163. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  164. }}}
  165. #endif