alternative.hpp 7.2 KB

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