action.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  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. #if !defined(BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM)
  6. #define BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/karma/detail/attributes.hpp>
  11. #include <boost/spirit/home/support/argument.hpp>
  12. #include <boost/spirit/home/support/context.hpp>
  13. #include <boost/spirit/home/support/unused.hpp>
  14. #include <boost/spirit/home/support/info.hpp>
  15. #include <boost/spirit/home/support/action_dispatch.hpp>
  16. #include <boost/spirit/home/support/has_semantic_action.hpp>
  17. #include <boost/spirit/home/support/handles_container.hpp>
  18. #include <boost/spirit/home/karma/domain.hpp>
  19. #include <boost/spirit/home/karma/meta_compiler.hpp>
  20. #include <boost/spirit/home/karma/generator.hpp>
  21. #include <boost/mpl/bool.hpp>
  22. #include <boost/mpl/if.hpp>
  23. #include <boost/type_traits/remove_const.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. namespace boost { namespace spirit { namespace karma
  26. {
  27. ///////////////////////////////////////////////////////////////////////////
  28. BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
  29. template <typename Subject, typename Action>
  30. struct action : unary_generator<action<Subject, Action> >
  31. {
  32. typedef Subject subject_type;
  33. typedef typename subject_type::properties properties;
  34. template <typename Context, typename Iterator>
  35. struct attribute
  36. : traits::attribute_of<Subject, Context, Iterator>
  37. {};
  38. action(Subject const& subject, Action f)
  39. : subject(subject), f(f) {}
  40. template <
  41. typename OutputIterator, typename Context, typename Delimiter
  42. , typename Attribute>
  43. bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
  44. , Attribute const& attr_) const
  45. {
  46. typedef typename attribute<Context, unused_type>::type attr_type;
  47. typedef traits::make_attribute<attr_type, Attribute> make_attribute;
  48. // create a attribute if none is supplied
  49. // this creates a _copy_ of the attribute because the semantic
  50. // action will likely change parts of this
  51. typedef traits::transform_attribute<
  52. typename make_attribute::type, attr_type, domain> transform;
  53. typename transform::type attr =
  54. traits::pre_transform<domain, attr_type>(make_attribute::call(attr_));
  55. // call the function, passing the attribute, the context and a bool
  56. // flag that the client can set to false to fail generating.
  57. return traits::action_dispatch<Subject>()(f, attr, ctx) &&
  58. subject.generate(sink, ctx, d, attr);
  59. }
  60. template <typename Context>
  61. info what(Context& context) const
  62. {
  63. // the action is transparent (does not add any info)
  64. return subject.what(context);
  65. }
  66. subject_type subject;
  67. Action f;
  68. };
  69. }}}
  70. ///////////////////////////////////////////////////////////////////////////////
  71. namespace boost { namespace spirit
  72. {
  73. ///////////////////////////////////////////////////////////////////////////
  74. // Karma action meta-compiler
  75. template <>
  76. struct make_component<karma::domain, tag::action>
  77. {
  78. template <typename Sig>
  79. struct result;
  80. template <typename This, typename Elements, typename Modifiers>
  81. struct result<This(Elements, Modifiers)>
  82. {
  83. typedef typename
  84. remove_const<typename Elements::car_type>::type
  85. subject_type;
  86. typedef typename
  87. remove_const<typename Elements::cdr_type::car_type>::type
  88. action_type;
  89. typedef karma::action<subject_type, action_type> type;
  90. };
  91. template <typename Elements>
  92. typename result<make_component(Elements, unused_type)>::type
  93. operator()(Elements const& elements, unused_type) const
  94. {
  95. typename result<make_component(Elements, unused_type)>::type
  96. result(elements.car, elements.cdr.car);
  97. return result;
  98. }
  99. };
  100. }}
  101. namespace boost { namespace spirit { namespace traits
  102. {
  103. ///////////////////////////////////////////////////////////////////////////
  104. template <typename Subject, typename Action>
  105. struct has_semantic_action<karma::action<Subject, Action> >
  106. : mpl::true_ {};
  107. ///////////////////////////////////////////////////////////////////////////
  108. template <typename Subject, typename Action, typename Attribute
  109. , typename Context, typename Iterator>
  110. struct handles_container<karma::action<Subject, Action>, Attribute
  111. , Context, Iterator>
  112. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  113. }}}
  114. #endif