• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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