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