permutation.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  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. =============================================================================*/
  6. #ifndef BOOST_SPIRIT_QI_OPERATOR_PERMUTATION_HPP
  7. #define BOOST_SPIRIT_QI_OPERATOR_PERMUTATION_HPP
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/meta_compiler.hpp>
  12. #include <boost/spirit/home/qi/detail/permute_function.hpp>
  13. #include <boost/spirit/home/qi/detail/attributes.hpp>
  14. #include <boost/spirit/home/support/algorithm/any_if_ns.hpp>
  15. #include <boost/spirit/home/support/detail/what_function.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/support/info.hpp>
  19. #include <boost/fusion/include/size.hpp>
  20. #include <boost/optional.hpp>
  21. #include <boost/array.hpp>
  22. #include <boost/proto/operators.hpp>
  23. #include <boost/proto/tags.hpp>
  24. namespace boost { namespace spirit
  25. {
  26. ///////////////////////////////////////////////////////////////////////////
  27. // Enablers
  28. ///////////////////////////////////////////////////////////////////////////
  29. template <>
  30. struct use_operator<qi::domain, proto::tag::bitwise_xor> // enables ^
  31. : mpl::true_ {};
  32. template <>
  33. struct flatten_tree<qi::domain, proto::tag::bitwise_xor> // flattens ^
  34. : mpl::true_ {};
  35. }}
  36. namespace boost { namespace spirit { namespace qi
  37. {
  38. template <typename Elements>
  39. struct permutation : nary_parser<permutation<Elements> >
  40. {
  41. template <typename Context, typename Iterator>
  42. struct attribute
  43. {
  44. // Put all the element attributes in a tuple,
  45. // wrapping each element in a boost::optional
  46. typedef typename traits::build_attribute_sequence<
  47. Elements, Context, traits::permutation_attribute_transform
  48. , Iterator, qi::domain
  49. >::type all_attributes;
  50. // Now, build a fusion vector over the attributes. Note
  51. // that build_fusion_vector 1) removes all unused attributes
  52. // and 2) may return unused_type if all elements have
  53. // unused_type(s).
  54. typedef typename
  55. traits::build_fusion_vector<all_attributes>::type
  56. type;
  57. };
  58. permutation(Elements const& elements_)
  59. : elements(elements_) {}
  60. template <typename Iterator, typename Context
  61. , typename Skipper, typename Attribute>
  62. bool parse(Iterator& first, Iterator const& last
  63. , Context& context, Skipper const& skipper
  64. , Attribute& attr_) const
  65. {
  66. typedef traits::attribute_not_unused<Context, Iterator> predicate;
  67. detail::permute_function<Iterator, Context, Skipper>
  68. f(first, last, context, skipper);
  69. boost::array<bool, fusion::result_of::size<Elements>::value> flags;
  70. flags.fill(false);
  71. // wrap the attribute in a tuple if it is not a tuple
  72. typename traits::wrap_if_not_tuple<Attribute>::type attr_local(attr_);
  73. // We have a bool array 'flags' with one flag for each parser.
  74. // permute_function sets the slot to true when the corresponding
  75. // parser successful matches. We loop until there are no more
  76. // successful parsers.
  77. bool result = false;
  78. f.taken = flags.begin();
  79. while (spirit::any_if_ns(elements, attr_local, f, predicate()))
  80. {
  81. f.taken = flags.begin();
  82. result = true;
  83. }
  84. return result;
  85. }
  86. template <typename Context>
  87. info what(Context& context) const
  88. {
  89. info result("permutation");
  90. fusion::for_each(elements,
  91. spirit::detail::what_function<Context>(result, context));
  92. return result;
  93. }
  94. Elements elements;
  95. };
  96. ///////////////////////////////////////////////////////////////////////////
  97. // Parser generators: make_xxx function (objects)
  98. ///////////////////////////////////////////////////////////////////////////
  99. template <typename Elements, typename Modifiers>
  100. struct make_composite<proto::tag::bitwise_xor, Elements, Modifiers>
  101. : make_nary_composite<Elements, permutation>
  102. {};
  103. }}}
  104. namespace boost { namespace spirit { namespace traits
  105. {
  106. ///////////////////////////////////////////////////////////////////////////
  107. // We specialize this for permutation (see support/attributes.hpp).
  108. // For permutation, we only wrap the attribute in a tuple IFF
  109. // it is not already a fusion tuple.
  110. template <typename Elements, typename Attribute>
  111. struct pass_attribute<qi::permutation<Elements>, Attribute>
  112. : wrap_if_not_tuple<Attribute> {};
  113. ///////////////////////////////////////////////////////////////////////////
  114. template <typename Elements>
  115. struct has_semantic_action<qi::permutation<Elements> >
  116. : nary_has_semantic_action<Elements> {};
  117. ///////////////////////////////////////////////////////////////////////////
  118. template <typename Elements, typename Attribute, typename Context
  119. , typename Iterator>
  120. struct handles_container<qi::permutation<Elements>, Attribute, Context
  121. , Iterator>
  122. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  123. }}}
  124. #endif