permutation.hpp 5.4 KB

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