alternative.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2001-2011 Joel de Guzman
  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. #ifndef BOOST_SPIRIT_KARMA_OPERATOR_ALTERNATIVE_HPP
  7. #define BOOST_SPIRIT_KARMA_OPERATOR_ALTERNATIVE_HPP
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/detail/alternative_function.hpp>
  12. #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
  13. #include <boost/spirit/home/karma/domain.hpp>
  14. #include <boost/spirit/home/karma/generator.hpp>
  15. #include <boost/spirit/home/karma/meta_compiler.hpp>
  16. #include <boost/spirit/home/support/info.hpp>
  17. #include <boost/spirit/home/support/unused.hpp>
  18. #include <boost/spirit/home/support/has_semantic_action.hpp>
  19. #include <boost/spirit/home/support/handles_container.hpp>
  20. #include <boost/spirit/home/support/detail/what_function.hpp>
  21. #include <boost/fusion/include/any.hpp>
  22. #include <boost/fusion/include/mpl.hpp>
  23. #include <boost/fusion/include/for_each.hpp>
  24. #include <boost/mpl/accumulate.hpp>
  25. #include <boost/mpl/bitor.hpp>
  26. #include <boost/proto/tags.hpp>
  27. #include <boost/config.hpp>
  28. namespace boost { namespace spirit
  29. {
  30. ///////////////////////////////////////////////////////////////////////////
  31. // Enablers
  32. ///////////////////////////////////////////////////////////////////////////
  33. template <>
  34. struct use_operator<karma::domain, proto::tag::bitwise_or> // enables |
  35. : mpl::true_ {};
  36. template <>
  37. struct flatten_tree<karma::domain, proto::tag::bitwise_or> // flattens |
  38. : mpl::true_ {};
  39. }}
  40. ///////////////////////////////////////////////////////////////////////////////
  41. namespace boost { namespace spirit { namespace traits
  42. {
  43. // specialization for sequences
  44. template <typename Elements>
  45. struct alternative_properties
  46. {
  47. struct element_properties
  48. {
  49. template <typename T>
  50. struct result;
  51. template <typename F, typename Element>
  52. struct result<F(Element)>
  53. {
  54. typedef properties_of<Element> type;
  55. };
  56. // never called, but needed for decltype-based result_of (C++0x)
  57. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  58. template <typename Element>
  59. typename result<element_properties(Element)>::type
  60. operator()(Element&&) const;
  61. #endif
  62. };
  63. typedef typename mpl::accumulate<
  64. typename fusion::result_of::transform<
  65. Elements, element_properties>::type
  66. , mpl::int_<karma::generator_properties::countingbuffer>
  67. , mpl::bitor_<mpl::_2, mpl::_1>
  68. >::type type;
  69. };
  70. }}}
  71. namespace boost { namespace spirit { namespace karma
  72. {
  73. template <typename Elements, typename Strict, typename Derived>
  74. struct base_alternative : nary_generator<Derived>
  75. {
  76. typedef typename traits::alternative_properties<Elements>::type
  77. properties;
  78. template <typename Context, typename Iterator = unused_type>
  79. struct attribute
  80. {
  81. // Put all the element attributes in a tuple
  82. typedef typename traits::build_attribute_sequence<
  83. Elements, Context, traits::alternative_attribute_transform
  84. , Iterator, karma::domain
  85. >::type all_attributes;
  86. // Ok, now make a variant over the attribute sequence. Note that
  87. // build_variant makes sure that 1) all attributes in the variant
  88. // are unique 2) puts the unused attribute, if there is any, to
  89. // the front and 3) collapses single element variants, variant<T>
  90. // to T.
  91. typedef typename traits::build_variant<all_attributes>::type type;
  92. };
  93. base_alternative(Elements const& elements)
  94. : elements(elements) {}
  95. template <
  96. typename OutputIterator, typename Context, typename Delimiter
  97. , typename Attribute>
  98. bool generate(OutputIterator& sink, Context& ctx
  99. , Delimiter const& d, Attribute const& attr) const
  100. {
  101. typedef detail::alternative_generate_function<
  102. OutputIterator, Context, Delimiter, Attribute, Strict
  103. > functor;
  104. // f return true if *any* of the parser succeeds
  105. functor f (sink, ctx, d, attr);
  106. return fusion::any(elements, f);
  107. }
  108. template <typename Context>
  109. info what(Context& context) const
  110. {
  111. info result("alternative");
  112. fusion::for_each(elements,
  113. spirit::detail::what_function<Context>(result, context));
  114. return result;
  115. }
  116. Elements elements;
  117. };
  118. template <typename Elements>
  119. struct alternative
  120. : base_alternative<Elements, mpl::false_, alternative<Elements> >
  121. {
  122. typedef base_alternative<Elements, mpl::false_, alternative>
  123. base_alternative_;
  124. alternative(Elements const& elements)
  125. : base_alternative_(elements) {}
  126. };
  127. template <typename Elements>
  128. struct strict_alternative
  129. : base_alternative<Elements, mpl::true_, strict_alternative<Elements> >
  130. {
  131. typedef base_alternative<Elements, mpl::true_, strict_alternative>
  132. base_alternative_;
  133. strict_alternative(Elements const& elements)
  134. : base_alternative_(elements) {}
  135. };
  136. ///////////////////////////////////////////////////////////////////////////
  137. // Generator generators: make_xxx function (objects)
  138. ///////////////////////////////////////////////////////////////////////////
  139. namespace detail
  140. {
  141. template <typename Elements, bool strict_mode = false>
  142. struct make_alternative
  143. : make_nary_composite<Elements, alternative>
  144. {};
  145. template <typename Elements>
  146. struct make_alternative<Elements, true>
  147. : make_nary_composite<Elements, strict_alternative>
  148. {};
  149. }
  150. template <typename Elements, typename Modifiers>
  151. struct make_composite<proto::tag::bitwise_or, Elements, Modifiers>
  152. : detail::make_alternative<Elements
  153. , detail::get_stricttag<Modifiers>::value>
  154. {};
  155. }}}
  156. namespace boost { namespace spirit { namespace traits
  157. {
  158. ///////////////////////////////////////////////////////////////////////////
  159. template <typename Elements>
  160. struct has_semantic_action<karma::alternative<Elements> >
  161. : nary_has_semantic_action<Elements> {};
  162. template <typename Elements>
  163. struct has_semantic_action<karma::strict_alternative<Elements> >
  164. : nary_has_semantic_action<Elements> {};
  165. ///////////////////////////////////////////////////////////////////////////
  166. template <typename Elements, typename Attribute, typename Context
  167. , typename Iterator>
  168. struct handles_container<karma::alternative<Elements>
  169. , Attribute, Context, Iterator>
  170. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  171. template <typename Elements, typename Attribute, typename Context
  172. , typename Iterator>
  173. struct handles_container<karma::strict_alternative<Elements>
  174. , Attribute, Context, Iterator>
  175. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  176. }}}
  177. #endif