]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/x3/operator/detail/sequence.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / x3 / operator / detail / sequence.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_SEQUENCE_DETAIL_JAN_06_2013_1015AM)
8 #define SPIRIT_SEQUENCE_DETAIL_JAN_06_2013_1015AM
9
10 #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
11 #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
12 #include <boost/spirit/home/x3/support/traits/make_attribute.hpp>
13 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
14 #include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
15 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
16 #include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
17
18 #include <boost/fusion/include/begin.hpp>
19 #include <boost/fusion/include/end.hpp>
20 #include <boost/fusion/include/advance.hpp>
21 #include <boost/fusion/include/empty.hpp>
22 #include <boost/fusion/include/front.hpp>
23 #include <boost/fusion/include/iterator_range.hpp>
24 #include <boost/fusion/include/as_deque.hpp>
25 #include <boost/fusion/include/mpl.hpp>
26
27 #include <boost/mpl/copy_if.hpp>
28 #include <boost/mpl/not.hpp>
29 #include <boost/mpl/if.hpp>
30 #include <boost/mpl/insert_range.hpp>
31 #include <boost/mpl/eval_if.hpp>
32 #include <boost/mpl/vector.hpp>
33 #include <boost/mpl/identity.hpp>
34
35 #include <boost/type_traits/add_reference.hpp>
36 #include <boost/type_traits/is_same.hpp>
37
38 namespace boost { namespace spirit { namespace x3
39 {
40 template <typename Left, typename Right>
41 struct sequence;
42 }}}
43
44 namespace boost { namespace spirit { namespace x3 { namespace detail
45 {
46 template <typename Parser, typename Context, typename Enable = void>
47 struct sequence_size
48 {
49 static int const value = traits::has_attribute<Parser, Context>::value;
50 };
51
52 template <typename Parser, typename Context>
53 struct sequence_size_subject
54 : sequence_size<typename Parser::subject_type, Context> {};
55
56 template <typename Parser, typename Context>
57 struct sequence_size<Parser, Context
58 , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
59 : sequence_size_subject<Parser, Context> {};
60
61 template <typename L, typename R, typename Context>
62 struct sequence_size<sequence<L, R>, Context>
63 {
64 static int const value =
65 sequence_size<L, Context>::value +
66 sequence_size<R, Context>::value;
67 };
68
69 struct pass_sequence_attribute_unused
70 {
71 typedef unused_type type;
72
73 template <typename T>
74 static unused_type
75 call(T&)
76 {
77 return unused_type();
78 }
79 };
80
81 template <typename Attribute>
82 struct pass_sequence_attribute_front
83 {
84 typedef typename fusion::result_of::front<Attribute>::type type;
85
86 static typename add_reference<type>::type
87 call(Attribute& attr)
88 {
89 return fusion::front(attr);
90 }
91 };
92
93 template <typename Attribute>
94 struct pass_through_sequence_attribute
95 {
96 typedef Attribute& type;
97
98 template <typename Attribute_>
99 static Attribute_&
100 call(Attribute_& attr)
101 {
102 return attr;
103 }
104 };
105
106 template <typename Parser, typename Attribute, bool pass_through>
107 struct pass_sequence_attribute_used :
108 mpl::if_c<
109 (!pass_through && traits::is_size_one_sequence<Attribute>::value)
110 , pass_sequence_attribute_front<Attribute>
111 , pass_through_sequence_attribute<Attribute>>::type {};
112
113 template <typename Parser, typename Attribute, bool pass_through = false, typename Enable = void>
114 struct pass_sequence_attribute :
115 mpl::if_<
116 fusion::result_of::empty<Attribute>
117 , pass_sequence_attribute_unused
118 , pass_sequence_attribute_used<Parser, Attribute, pass_through>>::type {};
119
120 template <typename L, typename R, typename Attribute, bool pass_through>
121 struct pass_sequence_attribute<sequence<L, R>, Attribute, pass_through>
122 : pass_through_sequence_attribute<Attribute> {};
123
124 template <typename Parser, typename Attribute>
125 struct pass_sequence_attribute_subject :
126 pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
127
128 template <typename Parser, typename Attribute, bool pass_through>
129 struct pass_sequence_attribute<Parser, Attribute, pass_through
130 , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
131 : pass_sequence_attribute_subject<Parser, Attribute> {};
132
133 template <typename L, typename R, typename Attribute, typename Context
134 , typename Enable = void>
135 struct partition_attribute
136 {
137 static int const l_size = sequence_size<L, Context>::value;
138 static int const r_size = sequence_size<R, Context>::value;
139
140 // If you got an error here, then you are trying to pass
141 // a fusion sequence with the wrong number of elements
142 // as that expected by the (sequence) parser.
143 static_assert(
144 fusion::result_of::size<Attribute>::value == (l_size + r_size)
145 , "Attribute does not have the expected size."
146 );
147
148 typedef typename fusion::result_of::begin<Attribute>::type l_begin;
149 typedef typename fusion::result_of::advance_c<l_begin, l_size>::type l_end;
150 typedef typename fusion::result_of::end<Attribute>::type r_end;
151 typedef fusion::iterator_range<l_begin, l_end> l_part;
152 typedef fusion::iterator_range<l_end, r_end> r_part;
153 typedef pass_sequence_attribute<L, l_part, false> l_pass;
154 typedef pass_sequence_attribute<R, r_part, false> r_pass;
155
156 static l_part left(Attribute& s)
157 {
158 auto i = fusion::begin(s);
159 return l_part(i, fusion::advance_c<l_size>(i));
160 }
161
162 static r_part right(Attribute& s)
163 {
164 return r_part(
165 fusion::advance_c<l_size>(fusion::begin(s))
166 , fusion::end(s));
167 }
168 };
169
170 template <typename L, typename R, typename Attribute, typename Context>
171 struct partition_attribute<L, R, Attribute, Context,
172 typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
173 traits::has_attribute<R, Context>::value)>::type>
174 {
175 typedef unused_type l_part;
176 typedef Attribute& r_part;
177 typedef pass_sequence_attribute_unused l_pass;
178 typedef pass_sequence_attribute<R, Attribute, true> r_pass;
179
180 static unused_type left(Attribute&)
181 {
182 return unused;
183 }
184
185 static Attribute& right(Attribute& s)
186 {
187 return s;
188 }
189 };
190
191 template <typename L, typename R, typename Attribute, typename Context>
192 struct partition_attribute<L, R, Attribute, Context,
193 typename enable_if_c<(traits::has_attribute<L, Context>::value &&
194 !traits::has_attribute<R, Context>::value)>::type>
195 {
196 typedef Attribute& l_part;
197 typedef unused_type r_part;
198 typedef pass_sequence_attribute<L, Attribute, true> l_pass;
199 typedef pass_sequence_attribute_unused r_pass;
200
201 static Attribute& left(Attribute& s)
202 {
203 return s;
204 }
205
206 static unused_type right(Attribute&)
207 {
208 return unused;
209 }
210 };
211
212 template <typename L, typename R, typename Attribute, typename Context>
213 struct partition_attribute<L, R, Attribute, Context,
214 typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
215 !traits::has_attribute<R, Context>::value)>::type>
216 {
217 typedef unused_type l_part;
218 typedef unused_type r_part;
219 typedef pass_sequence_attribute_unused l_pass;
220 typedef pass_sequence_attribute_unused r_pass;
221
222 static unused_type left(Attribute&)
223 {
224 return unused;
225 }
226
227 static unused_type right(Attribute&)
228 {
229 return unused;
230 }
231 };
232
233 template <typename L, typename R, typename C>
234 struct get_sequence_types
235 {
236 typedef
237 mpl::vector<
238 typename traits::attribute_of<L, C>::type
239 , typename traits::attribute_of<R, C>::type
240 >
241 type;
242 };
243
244 template <typename LL, typename LR, typename R, typename C>
245 struct get_sequence_types<sequence<LL, LR>, R, C>
246 : mpl::push_back< typename get_sequence_types<LL, LR, C>::type
247 , typename traits::attribute_of<R, C>::type> {};
248
249 template <typename L, typename RL, typename RR, typename C>
250 struct get_sequence_types<L, sequence<RL, RR>, C>
251 : mpl::push_front< typename get_sequence_types<RL, RR, C>::type
252 , typename traits::attribute_of<L, C>::type> {};
253
254 template <typename LL, typename LR, typename RL, typename RR, typename C>
255 struct get_sequence_types<sequence<LL, LR>, sequence<RL, RR>, C>
256 {
257 typedef typename get_sequence_types<LL, LR, C>::type left;
258 typedef typename get_sequence_types<RL, RR, C>::type right;
259 typedef typename
260 mpl::insert_range<left, typename mpl::end<left>::type, right>::type
261 type;
262 };
263
264 template <typename L, typename R, typename C>
265 struct attribute_of_sequence
266 {
267 // Get all sequence attribute types
268 typedef typename get_sequence_types<L, R, C>::type all_types;
269
270 // Filter all unused_types
271 typedef typename
272 mpl::copy_if<
273 all_types
274 , mpl::not_<is_same<mpl::_1, unused_type>>
275 , mpl::back_inserter<mpl::vector<>>
276 >::type
277 filtered_types;
278
279 // Build a fusion::deque if filtered_types is not empty,
280 // else just return unused_type
281 typedef typename
282 mpl::eval_if<
283 mpl::empty<filtered_types>
284 , mpl::identity<unused_type>
285 , mpl::if_<mpl::equal_to<mpl::size<filtered_types>, mpl::int_<1> >,
286 typename mpl::front<filtered_types>::type
287 , typename fusion::result_of::as_deque<filtered_types>::type >
288 >::type
289 type;
290 };
291
292 template <typename Parser, typename Iterator, typename Context
293 , typename RContext, typename Attribute>
294 bool parse_sequence(
295 Parser const& parser, Iterator& first, Iterator const& last
296 , Context const& context, RContext& rcontext, Attribute& attr
297 , traits::tuple_attribute)
298 {
299 typedef typename Parser::left_type Left;
300 typedef typename Parser::right_type Right;
301 typedef partition_attribute<Left, Right, Attribute, Context> partition;
302 typedef typename partition::l_pass l_pass;
303 typedef typename partition::r_pass r_pass;
304
305 typename partition::l_part l_part = partition::left(attr);
306 typename partition::r_part r_part = partition::right(attr);
307 typename l_pass::type l_attr = l_pass::call(l_part);
308 typename r_pass::type r_attr = r_pass::call(r_part);
309
310 Iterator save = first;
311 if (parser.left.parse(first, last, context, rcontext, l_attr)
312 && parser.right.parse(first, last, context, rcontext, r_attr))
313 return true;
314 first = save;
315 return false;
316 }
317
318 template <typename Parser, typename Iterator, typename Context
319 , typename RContext, typename Attribute>
320 bool parse_sequence_plain(
321 Parser const& parser, Iterator& first, Iterator const& last
322 , Context const& context, RContext& rcontext, Attribute& attr)
323 {
324 typedef typename Parser::left_type Left;
325 typedef typename Parser::right_type Right;
326 typedef typename traits::attribute_of<Left, Context>::type l_attr_type;
327 typedef typename traits::attribute_of<Right, Context>::type r_attr_type;
328 typedef traits::make_attribute<l_attr_type, Attribute> l_make_attribute;
329 typedef traits::make_attribute<r_attr_type, Attribute> r_make_attribute;
330
331 typename l_make_attribute::type l_attr = l_make_attribute::call(attr);
332 typename r_make_attribute::type r_attr = r_make_attribute::call(attr);
333
334 Iterator save = first;
335 if (parser.left.parse(first, last, context, rcontext, l_attr)
336 && parser.right.parse(first, last, context, rcontext, r_attr))
337 return true;
338 first = save;
339 return false;
340 }
341
342 template <typename Parser, typename Iterator, typename Context
343 , typename RContext, typename Attribute>
344 bool parse_sequence(
345 Parser const& parser, Iterator& first, Iterator const& last
346 , Context const& context, RContext& rcontext, Attribute& attr
347 , traits::plain_attribute)
348 {
349 return parse_sequence_plain(parser, first, last, context, rcontext, attr);
350 }
351
352 template <typename Parser, typename Iterator, typename Context
353 , typename RContext, typename Attribute>
354 bool parse_sequence(
355 Parser const& parser, Iterator& first, Iterator const& last
356 , Context const& context, RContext& rcontext, Attribute& attr
357 , traits::variant_attribute)
358 {
359 return parse_sequence_plain(parser, first, last, context, rcontext, attr);
360 }
361
362 template <typename Left, typename Right, typename Iterator
363 , typename Context, typename RContext, typename Attribute>
364 bool parse_sequence(
365 Left const& left, Right const& right
366 , Iterator& first, Iterator const& last
367 , Context const& context, RContext& rcontext, Attribute& attr
368 , traits::container_attribute);
369
370 template <typename Parser, typename Iterator, typename Context
371 , typename RContext, typename Attribute>
372 bool parse_sequence(
373 Parser const& parser , Iterator& first, Iterator const& last
374 , Context const& context, RContext& rcontext, Attribute& attr
375 , traits::container_attribute)
376 {
377 Iterator save = first;
378 if (parse_into_container(parser.left, first, last, context, rcontext, attr)
379 && parse_into_container(parser.right, first, last, context, rcontext, attr))
380 return true;
381 first = save;
382 return false;
383 }
384
385 template <typename Parser, typename Iterator, typename Context
386 , typename RContext, typename Attribute>
387 bool parse_sequence_assoc(
388 Parser const& parser , Iterator& first, Iterator const& last
389 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/)
390 {
391 return parse_into_container(parser, first, last, context, rcontext, attr);
392 }
393
394 template <typename Parser, typename Iterator, typename Context
395 , typename RContext, typename Attribute>
396 bool parse_sequence_assoc(
397 Parser const& parser , Iterator& first, Iterator const& last
398 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/)
399 {
400 Iterator save = first;
401 if (parser.left.parse( first, last, context, rcontext, attr)
402 && parser.right.parse(first, last, context, rcontext, attr))
403 return true;
404 first = save;
405 return false;
406 }
407
408 template <typename Parser, typename Iterator, typename Context
409 , typename RContext, typename Attribute>
410 bool parse_sequence(
411 Parser const& parser, Iterator& first, Iterator const& last
412 , Context const& context, RContext& rcontext, Attribute& attr
413 , traits::associative_attribute)
414 {
415 // we can come here in 2 cases:
416 // - when sequence is key >> value and therefore must
417 // be parsed with tuple synthesized attribute and then
418 // that tuple is used to save into associative attribute provided here.
419 // Example: key >> value;
420 //
421 // - when either this->left or this->right provides full key-value
422 // pair (like in case 1) and another one provides nothing.
423 // Example: eps >> rule<class x; fusion::map<...> >
424 //
425 // first case must be parsed as whole, and second one should
426 // be parsed separately for left and right.
427
428 typedef typename traits::attribute_of<
429 decltype(parser.left), Context>::type l_attr_type;
430 typedef typename traits::attribute_of<
431 decltype(parser.right), Context>::type r_attr_type;
432
433 typedef typename
434 mpl::or_<
435 is_same<l_attr_type, unused_type>
436 , is_same<r_attr_type, unused_type> >
437 should_split;
438
439 return parse_sequence_assoc(parser, first, last, context, rcontext, attr
440 , should_split());
441 }
442
443 template <typename Left, typename Right, typename Context, typename RContext>
444 struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
445 {
446 typedef sequence<Left, Right> parser_type;
447
448 template <typename Iterator, typename Attribute>
449 static bool call(
450 parser_type const& parser
451 , Iterator& first, Iterator const& last
452 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
453 {
454 // inform user what went wrong if we jumped here in attempt to
455 // parse incompatible sequence into fusion::map
456 static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
457 traits::associative_attribute>::value,
458 "To parse directly into fusion::map sequence must produce tuple attribute "
459 "where type of first element is existing key in fusion::map and second element "
460 "is value to be stored under that key");
461
462 Attribute attr_;
463 if (!parse_sequence(parser
464 , first, last, context, rcontext, attr_, traits::container_attribute()))
465 {
466 return false;
467 }
468 traits::append(attr, traits::begin(attr_), traits::end(attr_));
469 return true;
470 }
471
472 template <typename Iterator, typename Attribute>
473 static bool call(
474 parser_type const& parser
475 , Iterator& first, Iterator const& last
476 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
477 {
478 return parse_into_container_base_impl<parser_type>::call(
479 parser, first, last, context, rcontext, attr);
480 }
481
482 template <typename Iterator, typename Attribute>
483 static bool call(
484 parser_type const& parser
485 , Iterator& first, Iterator const& last
486 , Context const& context, RContext& rcontext, Attribute& attr)
487 {
488 typedef typename
489 traits::attribute_of<parser_type, Context>::type
490 attribute_type;
491
492 typedef typename
493 traits::container_value<Attribute>::type
494 value_type;
495
496 return call(parser, first, last, context, rcontext, attr
497 , typename traits::is_substitute<attribute_type, value_type>::type());
498 }
499 };
500
501 }}}}
502
503 #endif