action.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. typedef traits::make_attribute<attr_type, Attribute> make_attribute;
  47. // create an attribute if one is not supplied
  48. typedef traits::transform_attribute<
  49. typename make_attribute::type, attr_type, domain> transform;
  50. typename make_attribute::type made_attr = make_attribute::call(attr_);
  51. typename transform::type attr = transform::pre(made_attr);
  52. Iterator save = first;
  53. if (subject.parse(first, last, context, skipper, attr))
  54. {
  55. // call the function, passing the attribute, the context.
  56. // The client can return false to fail parsing.
  57. if (traits::action_dispatch<Subject>()(f, attr, context))
  58. {
  59. // Do up-stream transformation, this integrates the results
  60. // back into the original attribute value, if appropriate.
  61. traits::post_transform(attr_, attr);
  62. return true;
  63. }
  64. // reset iterators if semantic action failed the match
  65. // retrospectively
  66. first = save;
  67. }
  68. return false;
  69. }
  70. #else
  71. template <typename Iterator, typename Context
  72. , typename Skipper, typename Attribute>
  73. bool parse(Iterator& first, Iterator const& last
  74. , Context& context, Skipper const& skipper
  75. , Attribute& attr) const
  76. {
  77. Iterator save = first;
  78. if (subject.parse(first, last, context, skipper, attr)) // Use the attribute as-is
  79. {
  80. // call the function, passing the attribute, the context.
  81. // The client can return false to fail parsing.
  82. if (traits::action_dispatch<Subject>()(f, attr, context))
  83. return true;
  84. // reset iterators if semantic action failed the match
  85. // retrospectively
  86. first = save;
  87. }
  88. return false;
  89. }
  90. template <typename Iterator, typename Context
  91. , typename Skipper>
  92. bool parse(Iterator& first, Iterator const& last
  93. , Context& context, Skipper const& skipper
  94. , unused_type) const
  95. {
  96. typedef typename attribute<Context, Iterator>::type attr_type;
  97. typedef traits::make_attribute<attr_type, unused_type> make_attribute;
  98. // synthesize the attribute since one is not supplied
  99. typedef traits::transform_attribute<
  100. typename make_attribute::type, attr_type, domain> transform;
  101. typename make_attribute::type made_attr = make_attribute::call(unused_type());
  102. typename transform::type attr = transform::pre(made_attr);
  103. Iterator save = first;
  104. if (subject.parse(first, last, context, skipper, attr))
  105. {
  106. // call the function, passing the attribute, the context.
  107. // The client can return false to fail parsing.
  108. if (traits::action_dispatch<Subject>()(f, attr, context))
  109. return true;
  110. // reset iterators if semantic action failed the match
  111. // retrospectively
  112. first = save;
  113. }
  114. return false;
  115. }
  116. #endif
  117. template <typename Context>
  118. info what(Context& context) const
  119. {
  120. // the action is transparent (does not add any info)
  121. return subject.what(context);
  122. }
  123. Subject subject;
  124. Action f;
  125. private:
  126. // silence MSVC warning C4512: assignment operator could not be generated
  127. action& operator= (action const&);
  128. };
  129. }}}
  130. namespace boost { namespace spirit
  131. {
  132. // Qi action meta-compiler
  133. template <>
  134. struct make_component<qi::domain, tag::action>
  135. {
  136. template <typename Sig>
  137. struct result;
  138. template <typename This, typename Elements, typename Modifiers>
  139. struct result<This(Elements, Modifiers)>
  140. {
  141. typedef typename
  142. remove_const<typename Elements::car_type>::type
  143. subject_type;
  144. typedef typename
  145. remove_const<typename Elements::cdr_type::car_type>::type
  146. action_type;
  147. typedef qi::action<subject_type, action_type> type;
  148. };
  149. template <typename Elements>
  150. typename result<make_component(Elements, unused_type)>::type
  151. operator()(Elements const& elements, unused_type) const
  152. {
  153. typename result<make_component(Elements, unused_type)>::type
  154. result(elements.car, elements.cdr.car);
  155. return result;
  156. }
  157. };
  158. }}
  159. namespace boost { namespace spirit { namespace traits
  160. {
  161. ///////////////////////////////////////////////////////////////////////////
  162. template <typename Subject, typename Action>
  163. struct has_semantic_action<qi::action<Subject, Action> >
  164. : mpl::true_ {};
  165. ///////////////////////////////////////////////////////////////////////////
  166. template <typename Subject, typename Action, typename Attribute
  167. , typename Context, typename Iterator>
  168. struct handles_container<qi::action<Subject, Action>, Attribute
  169. , Context, Iterator>
  170. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  171. }}}
  172. #endif