kleene.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (c) 2001-2011 Joel de Guzman
  2. // Copyright (c) 2001-2011 Hartmut Kaiser
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM)
  7. #define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/domain.hpp>
  12. #include <boost/spirit/home/karma/generator.hpp>
  13. #include <boost/spirit/home/karma/meta_compiler.hpp>
  14. #include <boost/spirit/home/karma/detail/output_iterator.hpp>
  15. #include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
  16. #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
  17. #include <boost/spirit/home/karma/detail/pass_container.hpp>
  18. #include <boost/spirit/home/karma/detail/fail_function.hpp>
  19. #include <boost/spirit/home/support/info.hpp>
  20. #include <boost/spirit/home/support/unused.hpp>
  21. #include <boost/spirit/home/support/container.hpp>
  22. #include <boost/spirit/home/support/handles_container.hpp>
  23. #include <boost/spirit/home/karma/detail/attributes.hpp>
  24. #include <boost/proto/operators.hpp>
  25. #include <boost/proto/tags.hpp>
  26. #include <boost/type_traits/add_const.hpp>
  27. namespace boost { namespace spirit
  28. {
  29. ///////////////////////////////////////////////////////////////////////////
  30. // Enablers
  31. ///////////////////////////////////////////////////////////////////////////
  32. template <>
  33. struct use_operator<karma::domain, proto::tag::dereference> // enables *g
  34. : mpl::true_ {};
  35. }}
  36. ///////////////////////////////////////////////////////////////////////////////
  37. namespace boost { namespace spirit { namespace karma
  38. {
  39. template <typename Subject, typename Strict, typename Derived>
  40. struct base_kleene : unary_generator<Derived>
  41. {
  42. private:
  43. // Ignore return value in relaxed mode (failing subject generators
  44. // are just skipped). This allows to selectively generate items in
  45. // the provided attribute.
  46. template <typename F, typename Attribute>
  47. bool generate_subject(F f, Attribute const&, mpl::false_) const
  48. {
  49. bool r = !f(subject);
  50. if (!r && !f.is_at_end())
  51. f.next();
  52. return true;
  53. }
  54. template <typename F, typename Attribute>
  55. bool generate_subject(F f, Attribute const&, mpl::true_) const
  56. {
  57. return !f(subject);
  58. }
  59. // There is no way to distinguish a failed generator from a
  60. // generator to be skipped. We assume the user takes responsibility
  61. // for ending the loop if no attribute is specified.
  62. template <typename F>
  63. bool generate_subject(F f, unused_type, mpl::false_) const
  64. {
  65. return !f(subject);
  66. }
  67. // template <typename F>
  68. // bool generate_subject(F f, unused_type, mpl::true_) const
  69. // {
  70. // return !f(subject);
  71. // }
  72. public:
  73. typedef Subject subject_type;
  74. typedef typename subject_type::properties properties;
  75. // Build a std::vector from the subject's attribute. Note
  76. // that build_std_vector may return unused_type if the
  77. // subject's attribute is an unused_type.
  78. template <typename Context, typename Iterator>
  79. struct attribute
  80. : traits::build_std_vector<
  81. typename traits::attribute_of<Subject, Context, Iterator>::type
  82. >
  83. {};
  84. base_kleene(Subject const& subject)
  85. : subject(subject) {}
  86. template <
  87. typename OutputIterator, typename Context, typename Delimiter
  88. , typename Attribute>
  89. bool generate(OutputIterator& sink, Context& ctx
  90. , Delimiter const& d, Attribute const& attr) const
  91. {
  92. typedef detail::fail_function<
  93. OutputIterator, Context, Delimiter> fail_function;
  94. typedef typename traits::container_iterator<
  95. typename add_const<Attribute>::type
  96. >::type iterator_type;
  97. typedef
  98. typename traits::make_indirect_iterator<iterator_type>::type
  99. indirect_iterator_type;
  100. typedef detail::pass_container<
  101. fail_function, Attribute, indirect_iterator_type, mpl::false_>
  102. pass_container;
  103. iterator_type it = traits::begin(attr);
  104. iterator_type end = traits::end(attr);
  105. pass_container pass(fail_function(sink, ctx, d),
  106. indirect_iterator_type(it), indirect_iterator_type(end));
  107. // kleene fails only if the underlying output fails
  108. while (!pass.is_at_end())
  109. {
  110. if (!generate_subject(pass, attr, Strict()))
  111. break;
  112. }
  113. return detail::sink_is_good(sink);
  114. }
  115. template <typename Context>
  116. info what(Context& context) const
  117. {
  118. return info("kleene", subject.what(context));
  119. }
  120. Subject subject;
  121. };
  122. template <typename Subject>
  123. struct kleene
  124. : base_kleene<Subject, mpl::false_, kleene<Subject> >
  125. {
  126. typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
  127. kleene(Subject const& subject)
  128. : base_kleene_(subject) {}
  129. };
  130. template <typename Subject>
  131. struct strict_kleene
  132. : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
  133. {
  134. typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
  135. strict_kleene(Subject const& subject)
  136. : base_kleene_(subject) {}
  137. };
  138. ///////////////////////////////////////////////////////////////////////////
  139. // Generator generators: make_xxx function (objects)
  140. ///////////////////////////////////////////////////////////////////////////
  141. namespace detail
  142. {
  143. template <typename Subject, bool strict_mode = false>
  144. struct make_kleene
  145. : make_unary_composite<Subject, kleene>
  146. {};
  147. template <typename Subject>
  148. struct make_kleene<Subject, true>
  149. : make_unary_composite<Subject, strict_kleene>
  150. {};
  151. }
  152. template <typename Subject, typename Modifiers>
  153. struct make_composite<proto::tag::dereference, Subject, Modifiers>
  154. : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
  155. {};
  156. }}}
  157. namespace boost { namespace spirit { namespace traits
  158. {
  159. ///////////////////////////////////////////////////////////////////////////
  160. template <typename Subject>
  161. struct has_semantic_action<karma::kleene<Subject> >
  162. : unary_has_semantic_action<Subject> {};
  163. template <typename Subject>
  164. struct has_semantic_action<karma::strict_kleene<Subject> >
  165. : unary_has_semantic_action<Subject> {};
  166. ///////////////////////////////////////////////////////////////////////////
  167. template <typename Subject, typename Attribute, typename Context
  168. , typename Iterator>
  169. struct handles_container<karma::kleene<Subject>, Attribute
  170. , Context, Iterator>
  171. : mpl::true_ {};
  172. template <typename Subject, typename Attribute, typename Context
  173. , typename Iterator>
  174. struct handles_container<karma::strict_kleene<Subject>, Attribute
  175. , Context, Iterator>
  176. : mpl::true_ {};
  177. }}}
  178. #endif