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