kleene.hpp 7.1 KB

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