]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / x3 / core / detail / parse_into_container.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 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 #if !defined(SPIRIT_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM)
8 #define SPIRIT_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM
9
10 #include <type_traits>
11
12 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
13 #include <boost/spirit/home/x3/support/traits/value_traits.hpp>
14 #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
15 #include <boost/spirit/home/x3/support/traits/handles_container.hpp>
16 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
17 #include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
18 #include <boost/spirit/home/x3/support/traits/move_to.hpp>
19 #include <boost/mpl/and.hpp>
20 #include <boost/fusion/include/front.hpp>
21 #include <boost/fusion/include/back.hpp>
22 #include <boost/variant/apply_visitor.hpp>
23
24 namespace boost { namespace spirit { namespace x3 { namespace detail
25 {
26 template <typename Attribute, typename Value>
27 struct saver_visitor;
28
29 // save to associative fusion container where Key is simple type
30 template <typename Key, typename Enable = void>
31 struct save_to_assoc_attr
32 {
33 template <typename Value, typename Attribute>
34 static void call(const Key, Value& value, Attribute& attr)
35 {
36 traits::move_to(value, fusion::at_key<Key>(attr));
37 }
38 };
39
40 /* $$$ clang reports: warning: class template partial specialization contains
41 * a template parameter that can not be deduced; this partial specialization
42 * will never be used $$$
43 *
44 // save to associative fusion container where Key
45 // is variant over possible keys
46 template <typename ...T>
47 struct save_to_assoc_attr<variant<T...> >
48 {
49 typedef variant<T...> variant_t;
50
51 template <typename Value, typename Attribute>
52 static void call(const variant_t key, Value& value, Attribute& attr)
53 {
54 apply_visitor(saver_visitor<Attribute, Value>(attr, value), key);
55 }
56 };
57 */
58 template <typename Attribute, typename Value>
59 struct saver_visitor : boost::static_visitor<void>
60 {
61 saver_visitor(Attribute& attr, Value& value)
62 : attr(attr), value(value) {};
63
64 Attribute& attr;
65 Value& value;
66
67 template <typename Key>
68 void operator()(Key) const
69 {
70 save_to_assoc_attr<Key>::call(Key(), value,attr);
71 }
72 };
73
74 template <typename Parser, typename Container, typename Context>
75 struct parser_accepts_container
76 : traits::is_substitute<
77 typename traits::attribute_of<Parser, Context>::type
78 , Container
79 >
80 {};
81
82 template <typename Parser>
83 struct parse_into_container_base_impl
84 {
85 private:
86
87 // Parser has attribute (synthesize; Attribute is a container)
88 template <typename Iterator, typename Context
89 , typename RContext, typename Attribute>
90 static bool call_synthesize_x(
91 Parser const& parser
92 , Iterator& first, Iterator const& last
93 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
94 {
95 // synthesized attribute needs to be value initialized
96 typedef typename
97 traits::container_value<Attribute>::type
98 value_type;
99 value_type val = traits::value_initialize<value_type>::call();
100
101 if (!parser.parse(first, last, context, rcontext, val))
102 return false;
103
104 // push the parsed value into our attribute
105 traits::push_back(attr, val);
106 return true;
107 }
108
109 // Parser has attribute (synthesize; Attribute is a container)
110 template <typename Iterator, typename Context
111 , typename RContext, typename Attribute>
112 static bool call_synthesize_x(
113 Parser const& parser
114 , Iterator& first, Iterator const& last
115 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
116 {
117 return parser.parse(first, last, context, rcontext, attr);
118 }
119
120 // Parser has attribute (synthesize; Attribute is a container)
121 template <typename Iterator, typename Context
122 , typename RContext, typename Attribute>
123 static bool call_synthesize(
124 Parser const& parser
125 , Iterator& first, Iterator const& last
126 , Context const& context, RContext& rcontext, Attribute& attr)
127 {
128 typedef
129 parser_accepts_container<Parser, Attribute, Context>
130 parser_accepts_container;
131
132 return call_synthesize_x(parser, first, last, context, rcontext, attr
133 , parser_accepts_container());
134 }
135
136 // Parser has attribute (synthesize; Attribute is a single element fusion sequence)
137 template <typename Iterator, typename Context
138 , typename RContext, typename Attribute>
139 static bool call_synthesize_into_fusion_seq(Parser const& parser
140 , Iterator& first, Iterator const& last, Context const& context
141 , RContext& rcontext, Attribute& attr, mpl::false_ /* is_associative */)
142 {
143 static_assert(traits::has_size<Attribute, 1>::value,
144 "Expecting a single element fusion sequence");
145 return call_synthesize(parser, first, last, context, rcontext,
146 fusion::front(attr));
147 }
148
149 // Parser has attribute (synthesize; Attribute is fusion map sequence)
150 template <typename Iterator, typename Context, typename RContext, typename Attribute>
151 static bool call_synthesize_into_fusion_seq(
152 Parser const& parser
153 , Iterator& first, Iterator const& last, Context const& context
154 , RContext& rcontext, Attribute& attr, mpl::true_ /*is_associative*/)
155 {
156 using attribute_type = typename traits::attribute_of<Parser, Context>::type;
157 static_assert(traits::has_size<attribute_type, 2>::value,
158 "To parse directly into fusion map parser must produce 2 element attr");
159
160 // use type of first element of attribute as key
161 using key = typename std::remove_reference<
162 typename fusion::result_of::front<attribute_type>::type>::type;
163
164 attribute_type attr_;
165 if (!parser.parse(first, last, context, rcontext, attr_))
166 return false;
167
168 save_to_assoc_attr<key>::call(fusion::front(attr_), fusion::back(attr_), attr);
169 return true;
170 }
171
172 template <typename Iterator, typename Context, typename RContext, typename Attribute>
173 static bool call_synthesize_dispatch_by_seq(Parser const& parser
174 , Iterator& first, Iterator const& last, Context const& context
175 , RContext& rcontext, Attribute& attr, mpl::true_ /*is_sequence*/)
176 {
177 return call_synthesize_into_fusion_seq(
178 parser, first, last, context, rcontext, attr
179 , fusion::traits::is_associative<Attribute>());
180 }
181
182 template <typename Iterator, typename Context, typename RContext, typename Attribute>
183 static bool call_synthesize_dispatch_by_seq(Parser const& parser
184 , Iterator& first, Iterator const& last, Context const& context
185 , RContext& rcontext, Attribute& attr, mpl::false_ /*is_sequence*/)
186 {
187 return call_synthesize(parser, first, last, context, rcontext, attr);
188 }
189
190 // Parser has attribute (synthesize)
191 template <typename Iterator, typename Context, typename RContext, typename Attribute>
192 static bool call(Parser const& parser
193 , Iterator& first, Iterator const& last, Context const& context
194 , RContext& rcontext, Attribute& attr, mpl::true_)
195 {
196 return call_synthesize_dispatch_by_seq(parser, first, last, context, rcontext, attr
197 , fusion::traits::is_sequence<Attribute>());
198 }
199
200 // Parser has no attribute (pass unused)
201 template <typename Iterator, typename Context, typename RContext, typename Attribute>
202 static bool call(
203 Parser const& parser
204 , Iterator& first, Iterator const& last, Context const& context
205 , RContext& rcontext, Attribute& attr, mpl::false_)
206 {
207 return parser.parse(first, last, context, rcontext, unused);
208 }
209
210
211 public:
212
213 template <typename Iterator, typename Context, typename RContext, typename Attribute>
214 static bool call(Parser const& parser
215 , Iterator& first, Iterator const& last, Context const& context
216 , RContext& rcontext, Attribute& attr)
217 {
218 return call(parser, first, last, context, rcontext, attr
219 , mpl::bool_<traits::has_attribute<Parser, Context>::value>());
220 }
221 };
222
223 template <typename Parser, typename Context, typename RContext, typename Enable = void>
224 struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
225
226 template <typename Parser, typename Container, typename Context>
227 struct parser_attr_is_substitute_for_container_value
228 : traits::is_substitute<
229 typename traits::attribute_of<Parser, Context>::type
230 , typename traits::container_value<Container>::type
231 >
232 {};
233
234 template <typename Parser, typename Context, typename RContext>
235 struct parse_into_container_impl<Parser, Context, RContext,
236 typename enable_if<traits::handles_container<Parser, Context>>::type>
237 {
238 template <typename Iterator, typename Attribute>
239 static bool call(
240 Parser const& parser
241 , Iterator& first, Iterator const& last
242 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
243 {
244 return parse_into_container_base_impl<Parser>::call(
245 parser, first, last, context, rcontext, attr);
246 }
247
248 template <typename Iterator, typename Attribute>
249 static bool call(
250 Parser const& parser
251 , Iterator& first, Iterator const& last
252 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
253 {
254 return parser.parse(first, last, context, rcontext, attr);
255 }
256
257 template <typename Iterator, typename Attribute>
258 static bool call(Parser const& parser
259 , Iterator& first, Iterator const& last
260 , Context const& context, RContext& rcontext, Attribute& attr)
261 {
262 typedef parser_accepts_container<
263 Parser, Attribute, Context>
264 parser_accepts_container;
265
266 typedef parser_attr_is_substitute_for_container_value<
267 Parser, Attribute, Context>
268 parser_attr_is_substitute_for_container_value;
269
270 typedef mpl::or_<
271 parser_accepts_container
272 , mpl::not_<parser_attr_is_substitute_for_container_value>>
273 pass_attibute_as_is;
274
275 return call(parser, first, last, context, rcontext, attr,
276 pass_attibute_as_is());
277 }
278 };
279
280 template <typename Parser, typename Iterator, typename Context
281 , typename RContext, typename Attribute>
282 bool parse_into_container(
283 Parser const& parser
284 , Iterator& first, Iterator const& last, Context const& context
285 , RContext& rcontext, Attribute& attr)
286 {
287 return parse_into_container_impl<Parser, Context, RContext>::call(
288 parser, first, last, context, rcontext, attr);
289 }
290
291 }}}}
292
293 #endif