]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / operator / detail / sequence.hpp
CommitLineData
7c673cae
FG
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=============================================================================*/
11fdf7f2
TL
7#if !defined(BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM)
8#define BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM
7c673cae
FG
9
10#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
11#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
7c673cae
FG
12#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
13#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
14#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
11fdf7f2 15#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
7c673cae
FG
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>
11fdf7f2 21#include <boost/fusion/include/deref.hpp>
7c673cae
FG
22#include <boost/fusion/include/empty.hpp>
23#include <boost/fusion/include/front.hpp>
24#include <boost/fusion/include/iterator_range.hpp>
7c673cae 25
7c673cae 26#include <boost/mpl/if.hpp>
7c673cae
FG
27
28#include <boost/type_traits/add_reference.hpp>
29#include <boost/type_traits/is_same.hpp>
30
92f5a8d4
TL
31#include <iterator> // for std::make_move_iterator
32
7c673cae
FG
33namespace boost { namespace spirit { namespace x3
34{
35 template <typename Left, typename Right>
36 struct sequence;
37}}}
38
39namespace boost { namespace spirit { namespace x3 { namespace detail
40{
41 template <typename Parser, typename Context, typename Enable = void>
42 struct sequence_size
43 {
44 static int const value = traits::has_attribute<Parser, Context>::value;
45 };
46
47 template <typename Parser, typename Context>
48 struct sequence_size_subject
49 : sequence_size<typename Parser::subject_type, Context> {};
50
51 template <typename Parser, typename Context>
52 struct sequence_size<Parser, Context
53 , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
54 : sequence_size_subject<Parser, Context> {};
55
56 template <typename L, typename R, typename Context>
57 struct sequence_size<sequence<L, R>, Context>
58 {
59 static int const value =
60 sequence_size<L, Context>::value +
61 sequence_size<R, Context>::value;
62 };
63
64 struct pass_sequence_attribute_unused
65 {
66 typedef unused_type type;
67
68 template <typename T>
69 static unused_type
70 call(T&)
71 {
72 return unused_type();
73 }
74 };
75
76 template <typename Attribute>
11fdf7f2 77 struct pass_sequence_attribute_size_one_view
7c673cae 78 {
11fdf7f2
TL
79 typedef typename fusion::result_of::deref<
80 typename fusion::result_of::begin<Attribute>::type
81 >::type type;
7c673cae 82
1e59de90 83 static type call(Attribute& attribute)
7c673cae 84 {
1e59de90 85 return fusion::deref(fusion::begin(attribute));
7c673cae
FG
86 }
87 };
88
89 template <typename Attribute>
90 struct pass_through_sequence_attribute
91 {
92 typedef Attribute& type;
93
94 template <typename Attribute_>
95 static Attribute_&
1e59de90 96 call(Attribute_& attribute)
7c673cae 97 {
1e59de90 98 return attribute;
7c673cae
FG
99 }
100 };
101
92f5a8d4
TL
102 template <typename Parser, typename Attribute, typename Enable = void>
103 struct pass_sequence_attribute :
11fdf7f2
TL
104 mpl::if_<
105 traits::is_size_one_view<Attribute>
106 , pass_sequence_attribute_size_one_view<Attribute>
7c673cae
FG
107 , pass_through_sequence_attribute<Attribute>>::type {};
108
11fdf7f2
TL
109 template <typename L, typename R, typename Attribute>
110 struct pass_sequence_attribute<sequence<L, R>, Attribute>
7c673cae
FG
111 : pass_through_sequence_attribute<Attribute> {};
112
113 template <typename Parser, typename Attribute>
114 struct pass_sequence_attribute_subject :
115 pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
116
11fdf7f2
TL
117 template <typename Parser, typename Attribute>
118 struct pass_sequence_attribute<Parser, Attribute
7c673cae
FG
119 , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
120 : pass_sequence_attribute_subject<Parser, Attribute> {};
121
122 template <typename L, typename R, typename Attribute, typename Context
123 , typename Enable = void>
124 struct partition_attribute
125 {
92f5a8d4
TL
126 using attr_category = typename traits::attribute_category<Attribute>::type;
127 static_assert(is_same<traits::tuple_attribute, attr_category>::value,
128 "The parser expects tuple-like attribute type");
129
7c673cae
FG
130 static int const l_size = sequence_size<L, Context>::value;
131 static int const r_size = sequence_size<R, Context>::value;
132
92f5a8d4
TL
133 static int constexpr actual_size = fusion::result_of::size<Attribute>::value;
134 static int constexpr expected_size = l_size + r_size;
135
7c673cae
FG
136 // If you got an error here, then you are trying to pass
137 // a fusion sequence with the wrong number of elements
138 // as that expected by the (sequence) parser.
139 static_assert(
92f5a8d4
TL
140 actual_size >= expected_size
141 , "Size of the passed attribute is less than expected."
142 );
143 static_assert(
144 actual_size <= expected_size
145 , "Size of the passed attribute is bigger than expected."
7c673cae
FG
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;
11fdf7f2
TL
153 typedef pass_sequence_attribute<L, l_part> l_pass;
154 typedef pass_sequence_attribute<R, r_part> r_pass;
7c673cae
FG
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;
11fdf7f2 178 typedef pass_sequence_attribute<R, Attribute> r_pass;
7c673cae
FG
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;
11fdf7f2 198 typedef pass_sequence_attribute<L, Attribute> l_pass;
7c673cae
FG
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
7c673cae 233 template <typename Parser, typename Iterator, typename Context
92f5a8d4 234 , typename RContext, typename Attribute, typename AttributeCategory>
7c673cae
FG
235 bool parse_sequence(
236 Parser const& parser, Iterator& first, Iterator const& last
237 , Context const& context, RContext& rcontext, Attribute& attr
92f5a8d4 238 , AttributeCategory)
7c673cae 239 {
92f5a8d4
TL
240 using Left = typename Parser::left_type;
241 using Right = typename Parser::right_type;
242 using partition = partition_attribute<Left, Right, Attribute, Context>;
243 using l_pass = typename partition::l_pass;
244 using r_pass = typename partition::r_pass;
7c673cae
FG
245
246 typename partition::l_part l_part = partition::left(attr);
247 typename partition::r_part r_part = partition::right(attr);
248 typename l_pass::type l_attr = l_pass::call(l_part);
249 typename r_pass::type r_attr = r_pass::call(r_part);
250
251 Iterator save = first;
252 if (parser.left.parse(first, last, context, rcontext, l_attr)
253 && parser.right.parse(first, last, context, rcontext, r_attr))
254 return true;
255 first = save;
256 return false;
257 }
258
92f5a8d4
TL
259 template <typename Parser, typename Context>
260 constexpr bool pass_sequence_container_attribute
261 = sequence_size<Parser, Context>::value > 1;
7c673cae 262
11fdf7f2
TL
263 template <typename Parser, typename Iterator, typename Context
264 , typename RContext, typename Attribute>
92f5a8d4
TL
265 typename enable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
266 parse_sequence_container(
267 Parser const& parser
268 , Iterator& first, Iterator const& last, Context const& context
269 , RContext& rcontext, Attribute& attr)
11fdf7f2 270 {
92f5a8d4 271 return parser.parse(first, last, context, rcontext, attr);
11fdf7f2
TL
272 }
273
274 template <typename Parser, typename Iterator, typename Context
275 , typename RContext, typename Attribute>
92f5a8d4
TL
276 typename disable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
277 parse_sequence_container(
278 Parser const& parser
279 , Iterator& first, Iterator const& last, Context const& context
280 , RContext& rcontext, Attribute& attr)
11fdf7f2 281 {
92f5a8d4 282 return parse_into_container(parser, first, last, context, rcontext, attr);
11fdf7f2
TL
283 }
284
7c673cae
FG
285 template <typename Parser, typename Iterator, typename Context
286 , typename RContext, typename Attribute>
287 bool parse_sequence(
288 Parser const& parser , Iterator& first, Iterator const& last
289 , Context const& context, RContext& rcontext, Attribute& attr
290 , traits::container_attribute)
291 {
292 Iterator save = first;
92f5a8d4
TL
293 if (parse_sequence_container(parser.left, first, last, context, rcontext, attr)
294 && parse_sequence_container(parser.right, first, last, context, rcontext, attr))
7c673cae
FG
295 return true;
296 first = save;
297 return false;
298 }
299
300 template <typename Parser, typename Iterator, typename Context
301 , typename RContext, typename Attribute>
302 bool parse_sequence_assoc(
303 Parser const& parser , Iterator& first, Iterator const& last
304 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/)
305 {
306 return parse_into_container(parser, first, last, context, rcontext, attr);
307 }
308
309 template <typename Parser, typename Iterator, typename Context
310 , typename RContext, typename Attribute>
311 bool parse_sequence_assoc(
312 Parser const& parser , Iterator& first, Iterator const& last
313 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/)
314 {
315 Iterator save = first;
316 if (parser.left.parse( first, last, context, rcontext, attr)
317 && parser.right.parse(first, last, context, rcontext, attr))
318 return true;
319 first = save;
320 return false;
321 }
322
323 template <typename Parser, typename Iterator, typename Context
324 , typename RContext, typename Attribute>
325 bool parse_sequence(
326 Parser const& parser, Iterator& first, Iterator const& last
327 , Context const& context, RContext& rcontext, Attribute& attr
328 , traits::associative_attribute)
329 {
330 // we can come here in 2 cases:
331 // - when sequence is key >> value and therefore must
332 // be parsed with tuple synthesized attribute and then
333 // that tuple is used to save into associative attribute provided here.
334 // Example: key >> value;
335 //
336 // - when either this->left or this->right provides full key-value
337 // pair (like in case 1) and another one provides nothing.
338 // Example: eps >> rule<class x; fusion::map<...> >
339 //
340 // first case must be parsed as whole, and second one should
341 // be parsed separately for left and right.
342
343 typedef typename traits::attribute_of<
344 decltype(parser.left), Context>::type l_attr_type;
345 typedef typename traits::attribute_of<
346 decltype(parser.right), Context>::type r_attr_type;
347
348 typedef typename
349 mpl::or_<
350 is_same<l_attr_type, unused_type>
351 , is_same<r_attr_type, unused_type> >
352 should_split;
353
354 return parse_sequence_assoc(parser, first, last, context, rcontext, attr
355 , should_split());
356 }
357
358 template <typename Left, typename Right, typename Context, typename RContext>
359 struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
360 {
361 typedef sequence<Left, Right> parser_type;
362
363 template <typename Iterator, typename Attribute>
364 static bool call(
365 parser_type const& parser
366 , Iterator& first, Iterator const& last
367 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
368 {
369 // inform user what went wrong if we jumped here in attempt to
370 // parse incompatible sequence into fusion::map
371 static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
372 traits::associative_attribute>::value,
373 "To parse directly into fusion::map sequence must produce tuple attribute "
374 "where type of first element is existing key in fusion::map and second element "
375 "is value to be stored under that key");
376
f67539c2 377 Attribute attr_{};
7c673cae
FG
378 if (!parse_sequence(parser
379 , first, last, context, rcontext, attr_, traits::container_attribute()))
380 {
381 return false;
382 }
92f5a8d4
TL
383 traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
384 std::make_move_iterator(traits::end(attr_)));
7c673cae
FG
385 return true;
386 }
387
388 template <typename Iterator, typename Attribute>
389 static bool call(
390 parser_type const& parser
391 , Iterator& first, Iterator const& last
392 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
393 {
394 return parse_into_container_base_impl<parser_type>::call(
395 parser, first, last, context, rcontext, attr);
396 }
397
398 template <typename Iterator, typename Attribute>
399 static bool call(
400 parser_type const& parser
401 , Iterator& first, Iterator const& last
402 , Context const& context, RContext& rcontext, Attribute& attr)
403 {
404 typedef typename
405 traits::attribute_of<parser_type, Context>::type
406 attribute_type;
407
408 typedef typename
409 traits::container_value<Attribute>::type
410 value_type;
411
412 return call(parser, first, last, context, rcontext, attr
413 , typename traits::is_substitute<attribute_type, value_type>::type());
414 }
415 };
416
417}}}}
418
419#endif