]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | Copyright (c) 2010-2011 Bryce Lelbach | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | =============================================================================*/ | |
9 | #if !defined(BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM) | |
10 | #define BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM | |
11 | ||
12 | #include <boost/spirit/home/support/attributes.hpp> | |
13 | #include <boost/spirit/home/support/container.hpp> | |
14 | #include <boost/spirit/home/support/utree.hpp> | |
15 | #include <boost/spirit/home/qi/domain.hpp> | |
16 | #include <boost/spirit/home/karma/domain.hpp> | |
17 | #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp> | |
18 | #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp> | |
19 | ||
20 | #include <string> | |
21 | ||
22 | #include <boost/cstdint.hpp> | |
23 | #include <boost/variant.hpp> | |
24 | #include <boost/range/iterator_range.hpp> | |
25 | #include <boost/mpl/bool.hpp> | |
26 | #include <boost/mpl/identity.hpp> | |
27 | #include <boost/mpl/or.hpp> | |
28 | #include <boost/type_traits/is_same.hpp> | |
29 | #include <boost/utility/enable_if.hpp> | |
30 | ||
31 | /////////////////////////////////////////////////////////////////////////////// | |
32 | namespace boost | |
33 | { | |
34 | template <typename T> | |
35 | inline T get(boost::spirit::utree const& x) | |
36 | { | |
37 | return x.get<T>(); | |
38 | } | |
39 | } | |
40 | ||
41 | /////////////////////////////////////////////////////////////////////////////// | |
42 | namespace boost { namespace spirit { namespace traits | |
43 | { | |
44 | namespace detail | |
45 | { | |
46 | inline bool is_list(utree const& ut) | |
47 | { | |
48 | switch (traits::which(ut)) | |
49 | { | |
50 | case utree_type::reference_type: | |
51 | return is_list(ut.deref()); | |
52 | ||
53 | case utree_type::list_type: | |
54 | case utree_type::range_type: | |
55 | return true; | |
56 | ||
57 | default: | |
58 | break; | |
59 | } | |
60 | return false; | |
61 | } | |
62 | ||
63 | inline bool is_uninitialized(utree const& ut) | |
64 | { | |
65 | return traits::which(ut) == utree_type::invalid_type; | |
66 | } | |
67 | } | |
68 | ||
69 | // this specialization tells Spirit how to extract the type of the value | |
70 | // stored in the given utree node | |
71 | template <> | |
72 | struct variant_which<utree> | |
73 | { | |
74 | static int call(utree const& u) { return u.which(); } | |
75 | }; | |
76 | ||
77 | template <> | |
78 | struct variant_which<utree::list_type> | |
79 | { | |
80 | static int call(utree::list_type const& u) { return u.which(); } | |
81 | }; | |
82 | ||
83 | /////////////////////////////////////////////////////////////////////////// | |
84 | // Make sure all components of an alternative expose utree, even if they | |
85 | // actually expose a utree::list_type | |
86 | template <typename Domain> | |
87 | struct alternative_attribute_transform<utree::list_type, Domain> | |
88 | : mpl::identity<utree> | |
89 | {}; | |
90 | ||
91 | /////////////////////////////////////////////////////////////////////////// | |
92 | // Make sure all components of a sequence expose utree, even if they | |
93 | // actually expose a utree::list_type | |
94 | template <typename Domain> | |
95 | struct sequence_attribute_transform<utree::list_type, Domain> | |
96 | : mpl::identity<utree> | |
97 | {}; | |
98 | ||
99 | /////////////////////////////////////////////////////////////////////////// | |
100 | // this specialization lets Spirit know that typed basic_strings | |
101 | // are strings | |
102 | template <typename Base, utree_type::info I> | |
103 | struct is_string<spirit::basic_string<Base, I> > | |
104 | : mpl::true_ | |
105 | {}; | |
106 | ||
107 | /////////////////////////////////////////////////////////////////////////// | |
108 | // these specializations extract the character type of a utree typed string | |
109 | template <typename T, utree_type::info I> | |
110 | struct char_type_of<spirit::basic_string<iterator_range<T>, I> > | |
111 | : char_type_of<T> | |
112 | {}; | |
113 | ||
114 | template <utree_type::info I> | |
115 | struct char_type_of<spirit::basic_string<std::string, I> > | |
116 | : mpl::identity<char> | |
117 | {}; | |
118 | ||
119 | /////////////////////////////////////////////////////////////////////////// | |
120 | // these specializations extract a c string from a utree typed string | |
121 | template <typename String> | |
122 | struct extract_c_string; | |
123 | ||
124 | template <typename T, utree_type::info I> | |
125 | struct extract_c_string< | |
126 | spirit::basic_string<iterator_range<T const*>, I> | |
127 | > { | |
128 | typedef T char_type; | |
129 | ||
130 | typedef spirit::basic_string<iterator_range<T const*>, I> string; | |
131 | ||
132 | static T const* call (string& s) | |
133 | { | |
134 | return s.begin(); | |
135 | } | |
136 | ||
137 | static T const* call (string const& s) | |
138 | { | |
139 | return s.begin(); | |
140 | } | |
141 | }; | |
142 | ||
143 | template <utree_type::info I> | |
144 | struct extract_c_string<spirit::basic_string<std::string, I> > | |
145 | { | |
146 | typedef char char_type; | |
147 | ||
148 | typedef spirit::basic_string<std::string, I> string; | |
149 | ||
150 | static char const* call (string& s) | |
151 | { | |
152 | return s.c_str(); | |
153 | } | |
154 | ||
155 | static char const* call (string const& s) | |
156 | { | |
157 | return s.c_str(); | |
158 | } | |
159 | }; | |
160 | ||
161 | /////////////////////////////////////////////////////////////////////////// | |
162 | // these specializations are needed because utree::value_type == utree | |
163 | template <> | |
164 | struct is_substitute<utree, utree> | |
165 | : mpl::true_ | |
166 | {}; | |
167 | ||
168 | template <> | |
169 | struct is_weak_substitute<utree, utree> | |
170 | : mpl::true_ | |
171 | {}; | |
172 | ||
173 | template <> | |
174 | struct is_substitute<utree::list_type, utree::list_type> | |
175 | : mpl::true_ | |
176 | {}; | |
177 | ||
178 | template <> | |
179 | struct is_weak_substitute<utree::list_type, utree::list_type> | |
180 | : mpl::true_ | |
181 | {}; | |
182 | ||
183 | /////////////////////////////////////////////////////////////////////////// | |
184 | // this specialization tells Spirit.Qi to allow assignment to an utree from | |
185 | // a variant | |
186 | namespace detail | |
187 | { | |
188 | struct assign_to_utree_visitor : static_visitor<> | |
189 | { | |
190 | assign_to_utree_visitor(utree& ut) : ut_(ut) {} | |
191 | ||
192 | template <typename T> | |
193 | void operator()(T& val) const | |
194 | { | |
195 | ut_ = val; | |
196 | } | |
197 | ||
198 | utree& ut_; | |
199 | }; | |
200 | } | |
201 | ||
202 | template <BOOST_VARIANT_ENUM_PARAMS(typename T)> | |
203 | struct assign_to_container_from_value< | |
204 | utree, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > | |
205 | { | |
206 | static void | |
207 | call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val, utree& attr) | |
208 | { | |
209 | apply_visitor(detail::assign_to_utree_visitor(attr), val); | |
210 | } | |
211 | }; | |
212 | ||
213 | /////////////////////////////////////////////////////////////////////////// | |
214 | // this specialization tells Spirit.Qi to allow assignment to an utree from | |
215 | // a STL container | |
216 | template <typename Attribute> | |
217 | struct assign_to_container_from_value<utree, Attribute> | |
218 | { | |
219 | // any non-container type will be either directly assigned or appended | |
220 | static void call(Attribute const& val, utree& attr, mpl::false_) | |
221 | { | |
222 | if (attr.empty()) | |
223 | attr = val; | |
224 | else | |
225 | push_back(attr, val); | |
226 | } | |
227 | ||
228 | // any container type will be converted into a list_type utree | |
229 | static void call(Attribute const& val, utree& attr, mpl::true_) | |
230 | { | |
231 | typedef typename traits::container_iterator<Attribute const>::type | |
232 | iterator_type; | |
233 | ||
234 | // make sure the attribute is a list, at least an empty one | |
235 | if (attr.empty()) | |
236 | attr = empty_list; | |
237 | ||
238 | iterator_type end = traits::end(val); | |
239 | for (iterator_type i = traits::begin(val); i != end; traits::next(i)) | |
240 | push_back(attr, traits::deref(i)); | |
241 | } | |
242 | ||
243 | static void call(Attribute const& val, utree& attr) | |
244 | { | |
245 | call(val, attr, is_container<Attribute>()); | |
246 | } | |
247 | }; | |
248 | ||
249 | /////////////////////////////////////////////////////////////////////////// | |
250 | // this specialization is required to disambiguate the specializations | |
251 | // related to utree | |
252 | template <> | |
253 | struct assign_to_container_from_value<utree, utree> | |
254 | { | |
255 | static void call(utree const& val, utree& attr) | |
256 | { | |
257 | if (attr.empty()) { | |
258 | attr = val; | |
259 | } | |
260 | else if (detail::is_list(val)) { | |
261 | typedef utree::const_iterator iterator_type; | |
262 | ||
263 | iterator_type end = traits::end(val); | |
264 | for (iterator_type i = traits::begin(val); i != end; traits::next(i)) | |
265 | push_back(attr, traits::deref(i)); | |
266 | } | |
267 | else { | |
268 | push_back(attr, val); | |
269 | } | |
270 | } | |
271 | }; | |
272 | ||
273 | template <> | |
274 | struct assign_to_container_from_value<utree, utree::list_type> | |
275 | : assign_to_container_from_value<utree, utree> | |
276 | {}; | |
277 | ||
278 | // If the destination is a utree_list, we need to force the right hand side | |
279 | // value into a new sub-node, always, no questions asked. | |
280 | template <> | |
281 | struct assign_to_container_from_value<utree::list_type, utree> | |
282 | { | |
283 | static void call(utree const& val, utree& attr) | |
284 | { | |
285 | push_back(attr, val); | |
286 | } | |
287 | }; | |
288 | ||
289 | // If both, the right hand side and the left hand side are utree_lists | |
290 | // we have a lhs rule which has a single rule exposing a utree_list as its | |
291 | // rhs (optionally wrapped into a directive or other unary parser). In this | |
292 | // case we do not create a new sub-node. | |
293 | template <> | |
294 | struct assign_to_container_from_value<utree::list_type, utree::list_type> | |
295 | : assign_to_container_from_value<utree, utree> | |
296 | {}; | |
297 | ||
298 | /////////////////////////////////////////////////////////////////////////// | |
299 | // this specialization makes sure strings get assigned as a whole and are | |
300 | // not converted into a utree list | |
301 | template <> | |
302 | struct assign_to_container_from_value<utree, utf8_string_type> | |
303 | { | |
304 | static void call(utf8_string_type const& val, utree& attr) | |
305 | { | |
306 | if (attr.empty()) | |
307 | attr = val; | |
308 | else | |
309 | push_back(attr, val); | |
310 | } | |
311 | }; | |
312 | ||
313 | // this specialization keeps symbols from being transformed into strings | |
314 | template<> | |
315 | struct assign_to_container_from_value<utree, utf8_symbol_type> | |
316 | { | |
317 | static void call (utf8_symbol_type const& val, utree& attr) | |
318 | { | |
319 | if (attr.empty()) | |
320 | attr = val; | |
321 | else | |
322 | push_back(attr, val); | |
323 | } | |
324 | }; | |
325 | ||
326 | template <> | |
327 | struct assign_to_container_from_value<utree, binary_string_type> | |
328 | { | |
329 | static void call(binary_string_type const& val, utree& attr) | |
330 | { | |
331 | if (attr.empty()) | |
332 | attr = val; | |
333 | else | |
334 | push_back(attr, val); | |
335 | } | |
336 | }; | |
337 | ||
338 | template<> | |
339 | struct assign_to_container_from_value<utree, utf8_symbol_range_type> | |
340 | { | |
341 | static void call (utf8_symbol_range_type const& val, utree& attr) | |
342 | { | |
343 | if (attr.empty()) | |
344 | attr = val; | |
345 | else | |
346 | push_back(attr, val); | |
347 | } | |
348 | }; | |
349 | ||
350 | template <> | |
351 | struct assign_to_container_from_value<utree, binary_range_type> | |
352 | { | |
353 | static void call(binary_range_type const& val, utree& attr) | |
354 | { | |
355 | if (attr.empty()) | |
356 | attr = val; | |
357 | else | |
358 | push_back(attr, val); | |
359 | } | |
360 | }; | |
361 | ||
362 | template <> | |
363 | struct assign_to_container_from_value<utree, std::string> | |
364 | { | |
365 | static void call(std::string const& val, utree& attr) | |
366 | { | |
367 | if (attr.empty()) | |
368 | attr = val; | |
369 | else | |
370 | push_back(attr, val); | |
371 | } | |
372 | }; | |
373 | ||
374 | /////////////////////////////////////////////////////////////////////////// | |
375 | // this specialization tells Spirit.Qi to allow assignment to an utree from | |
376 | // generic iterators | |
377 | template <typename Iterator> | |
378 | struct assign_to_attribute_from_iterators<utree, Iterator> | |
379 | { | |
380 | static void | |
381 | call(Iterator const& first, Iterator const& last, utree& attr) | |
382 | { | |
383 | if (attr.empty()) | |
384 | attr.assign(first, last); | |
385 | else { | |
386 | for (Iterator i = first; i != last; ++i) | |
387 | push_back(attr, traits::deref(i)); | |
388 | } | |
389 | } | |
390 | }; | |
391 | ||
392 | /////////////////////////////////////////////////////////////////////////// | |
393 | // Karma only: convert utree node to string | |
394 | namespace detail | |
395 | { | |
396 | struct attribute_as_string_type | |
397 | { | |
398 | typedef utf8_string_range_type type; | |
399 | ||
400 | static type call(utree const& attr) | |
401 | { | |
402 | return boost::get<utf8_string_range_type>(attr); | |
403 | } | |
404 | ||
405 | static bool is_valid(utree const& attr) | |
406 | { | |
407 | switch (traits::which(attr)) | |
408 | { | |
409 | case utree_type::reference_type: | |
410 | return is_valid(attr.deref()); | |
411 | ||
412 | case utree_type::string_range_type: | |
413 | case utree_type::string_type: | |
414 | return true; | |
415 | ||
416 | default: | |
417 | return false; | |
418 | } | |
419 | } | |
420 | }; | |
421 | } | |
422 | ||
423 | template <> | |
424 | struct attribute_as<std::string, utree> | |
425 | : detail::attribute_as_string_type | |
426 | {}; | |
427 | ||
428 | template <> | |
429 | struct attribute_as<utf8_string_type, utree> | |
430 | : detail::attribute_as_string_type | |
431 | {}; | |
432 | ||
433 | template <> | |
434 | struct attribute_as<utf8_string_range_type, utree> | |
435 | : detail::attribute_as_string_type | |
436 | {}; | |
437 | ||
438 | /////////////////////////////////////////////////////////////////////////// | |
439 | namespace detail | |
440 | { | |
441 | struct attribute_as_symbol_type | |
442 | { | |
443 | typedef utf8_symbol_range_type type; | |
444 | ||
445 | static type call(utree const& attr) | |
446 | { | |
447 | return boost::get<utf8_symbol_range_type>(attr); | |
448 | } | |
449 | ||
450 | static bool is_valid(utree const& attr) | |
451 | { | |
452 | switch (traits::which(attr)) | |
453 | { | |
454 | case utree_type::reference_type: | |
455 | return is_valid(attr.deref()); | |
456 | ||
457 | case utree_type::symbol_type: | |
458 | return true; | |
459 | ||
460 | default: | |
461 | return false; | |
462 | } | |
463 | } | |
464 | }; | |
465 | } | |
466 | ||
467 | template <> | |
468 | struct attribute_as<utf8_symbol_type, utree> | |
469 | : detail::attribute_as_symbol_type | |
470 | {}; | |
471 | ||
472 | template <> | |
473 | struct attribute_as<utf8_symbol_range_type, utree> | |
474 | : detail::attribute_as_symbol_type | |
475 | {}; | |
476 | ||
477 | template <typename Attribute> | |
478 | struct attribute_as<Attribute, utree::list_type> | |
479 | : attribute_as<Attribute, utree> | |
480 | {}; | |
481 | ||
482 | /////////////////////////////////////////////////////////////////////////// | |
483 | namespace detail | |
484 | { | |
485 | struct attribute_as_binary_string_type | |
486 | { | |
487 | typedef binary_range_type type; | |
488 | ||
489 | static type call(utree const& attr) | |
490 | { | |
491 | return boost::get<binary_range_type>(attr); | |
492 | } | |
493 | ||
494 | static bool is_valid(utree const& attr) | |
495 | { | |
496 | switch (traits::which(attr)) | |
497 | { | |
498 | case utree_type::reference_type: | |
499 | return is_valid(attr.deref()); | |
500 | ||
501 | case utree_type::binary_type: | |
502 | return true; | |
503 | ||
504 | default: | |
505 | return false; | |
506 | } | |
507 | } | |
508 | }; | |
509 | } | |
510 | ||
511 | template <> | |
512 | struct attribute_as<binary_string_type, utree> | |
513 | : detail::attribute_as_binary_string_type | |
514 | {}; | |
515 | ||
516 | template <> | |
517 | struct attribute_as<binary_range_type, utree> | |
518 | : detail::attribute_as_binary_string_type | |
519 | {}; | |
520 | ||
521 | /////////////////////////////////////////////////////////////////////////// | |
522 | // push_back support for utree | |
523 | template <typename T> | |
524 | struct push_back_container<utree, T> | |
525 | { | |
526 | static bool call(utree& c, T const& val) | |
527 | { | |
528 | switch (traits::which(c)) | |
529 | { | |
530 | case utree_type::invalid_type: | |
531 | case utree_type::nil_type: | |
532 | case utree_type::list_type: | |
533 | c.push_back(val); | |
534 | break; | |
535 | ||
536 | default: | |
537 | { | |
538 | utree ut; | |
539 | ut.push_back(c); | |
540 | ut.push_back(val); | |
541 | c.swap(ut); | |
542 | } | |
543 | break; | |
544 | } | |
545 | return true; | |
546 | } | |
547 | }; | |
548 | ||
549 | template <typename T> | |
550 | struct push_back_container<utree::list_type, T> | |
551 | : push_back_container<utree, T> | |
552 | {}; | |
553 | ||
554 | /////////////////////////////////////////////////////////////////////////// | |
555 | // ensure the utree attribute is an empty list | |
556 | template <> | |
557 | struct make_container_attribute<utree> | |
558 | { | |
559 | static void call(utree& ut) | |
560 | { | |
561 | if (!detail::is_list(ut)) { | |
562 | if (detail::is_uninitialized(ut)) | |
563 | ut = empty_list; | |
564 | else { | |
565 | utree retval (empty_list); | |
566 | retval.push_back(ut); | |
567 | ut.swap(retval); | |
568 | } | |
569 | } | |
570 | } | |
571 | }; | |
572 | ||
573 | template <> | |
574 | struct make_container_attribute<utree::list_type> | |
575 | : make_container_attribute<utree> | |
576 | {}; | |
577 | ||
578 | /////////////////////////////////////////////////////////////////////////// | |
579 | // an utree is a container on its own | |
580 | template <> | |
581 | struct build_std_vector<utree> | |
582 | { | |
583 | typedef utree type; | |
584 | }; | |
585 | ||
586 | template <> | |
587 | struct build_std_vector<utree::list_type> | |
588 | { | |
589 | typedef utree::list_type type; | |
590 | }; | |
591 | ||
592 | /////////////////////////////////////////////////////////////////////////// | |
593 | // debug support for utree | |
594 | template <typename Out> | |
595 | struct print_attribute_debug<Out, utree> | |
596 | { | |
597 | static void call(Out& out, utree const& val) | |
598 | { | |
599 | out << val; | |
600 | } | |
601 | }; | |
602 | ||
603 | /////////////////////////////////////////////////////////////////////////// | |
604 | // force utree list attribute in a sequence to be dereferenced if a rule | |
605 | // or a grammar exposes an utree as it's attribute | |
606 | namespace detail | |
607 | { | |
608 | // Checks whether the exposed Attribute allows to handle utree or | |
609 | // utree::list_type directly. Returning mpl::false_ from this meta | |
610 | // function will force a new utree instance to be created for each | |
611 | // invocation of the embedded parser. | |
612 | ||
613 | // The purpose of using utree::list_type as an attribute is to force a | |
614 | // new sub-node in the result. | |
615 | template <typename Attribute, typename Enable = void> | |
616 | struct handles_utree_list_container | |
617 | : mpl::and_< | |
618 | mpl::not_<is_same<utree::list_type, Attribute> >, | |
619 | traits::is_container<Attribute> > | |
620 | {}; | |
621 | ||
622 | // The following specializations make sure that the actual handling of | |
623 | // an utree (or utree::list_type) attribute is deferred to the embedded | |
624 | // parsers of a sequence, alternative or optional component. | |
625 | template <typename Attribute> | |
626 | struct handles_utree_list_container<Attribute | |
627 | , typename enable_if<fusion::traits::is_sequence<Attribute> >::type> | |
628 | : mpl::true_ | |
629 | {}; | |
630 | ||
631 | template <typename Attribute> | |
632 | struct handles_utree_list_container<boost::optional<Attribute> > | |
633 | : mpl::true_ | |
634 | {}; | |
635 | ||
636 | template <BOOST_VARIANT_ENUM_PARAMS(typename T)> | |
637 | struct handles_utree_list_container< | |
638 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > | |
639 | : mpl::true_ | |
640 | {}; | |
641 | } | |
642 | ||
643 | template < | |
644 | typename IteratorA, typename IteratorB, typename Context | |
645 | , typename T1, typename T2, typename T3, typename T4> | |
646 | struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4> | |
647 | , utree, Context, IteratorB> | |
648 | : detail::handles_utree_list_container<typename attribute_of< | |
649 | qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
650 | >::type> | |
651 | {}; | |
652 | ||
653 | template < | |
654 | typename IteratorA, typename IteratorB, typename Context | |
655 | , typename T1, typename T2, typename T3, typename T4> | |
656 | struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4> | |
657 | , utree, Context, IteratorB> | |
658 | : detail::handles_utree_list_container<typename attribute_of< | |
659 | qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
660 | >::type> | |
661 | {}; | |
662 | ||
663 | template < | |
664 | typename IteratorA, typename IteratorB, typename Context | |
665 | , typename T1, typename T2, typename T3, typename T4> | |
666 | struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4> | |
667 | , utree::list_type, Context, IteratorB> | |
668 | : detail::handles_utree_list_container<typename attribute_of< | |
669 | qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
670 | >::type> | |
671 | {}; | |
672 | ||
673 | template < | |
674 | typename IteratorA, typename IteratorB, typename Context | |
675 | , typename T1, typename T2, typename T3, typename T4> | |
676 | struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4> | |
677 | , utree::list_type, Context, IteratorB> | |
678 | : detail::handles_utree_list_container<typename attribute_of< | |
679 | qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
680 | >::type> | |
681 | {}; | |
682 | ||
683 | /////////////////////////////////////////////////////////////////////////// | |
684 | template <typename Attribute, typename Sequence> | |
685 | struct pass_through_container< | |
686 | utree, utree, Attribute, Sequence, qi::domain> | |
687 | : detail::handles_utree_list_container<Attribute> | |
688 | {}; | |
689 | ||
690 | template <typename Attribute, typename Sequence> | |
691 | struct pass_through_container< | |
692 | utree::list_type, utree, Attribute, Sequence, qi::domain> | |
693 | : detail::handles_utree_list_container<Attribute> | |
694 | {}; | |
695 | ||
696 | /////////////////////////////////////////////////////////////////////////// | |
697 | namespace detail | |
698 | { | |
699 | // Checks whether the exposed Attribute allows to handle utree or | |
700 | // utree::list_type directly. Returning mpl::false_ from this meta | |
701 | // function will force a new utree instance to be created for each | |
702 | // invocation of the embedded parser. | |
703 | ||
704 | // The purpose of using utree::list_type as an attribute is to force a | |
705 | // new sub-node in the result. | |
706 | template <typename Attribute, typename Enable = void> | |
707 | struct handles_utree_container | |
708 | : mpl::and_< | |
709 | mpl::not_<is_same<utree, Attribute> >, | |
710 | traits::is_container<Attribute> > | |
711 | {}; | |
712 | ||
713 | // The following specializations make sure that the actual handling of | |
714 | // an utree (or utree::list_type) attribute is deferred to the embedded | |
715 | // parsers of a sequence, alternative or optional component. | |
716 | template <typename Attribute> | |
717 | struct handles_utree_container<Attribute | |
718 | , typename enable_if<fusion::traits::is_sequence<Attribute> >::type> | |
719 | : mpl::true_ | |
720 | {}; | |
721 | ||
722 | template <typename Attribute> | |
723 | struct handles_utree_container<boost::optional<Attribute> > | |
724 | : mpl::true_ | |
725 | {}; | |
726 | ||
727 | template <BOOST_VARIANT_ENUM_PARAMS(typename T)> | |
728 | struct handles_utree_container< | |
729 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > | |
730 | : mpl::true_ | |
731 | {}; | |
732 | } | |
733 | ||
734 | template < | |
735 | typename IteratorA, typename IteratorB, typename Context | |
736 | , typename T1, typename T2, typename T3, typename T4> | |
737 | struct handles_container<karma::rule<IteratorA, T1, T2, T3, T4> | |
738 | , utree, Context, IteratorB> | |
739 | : detail::handles_utree_container<typename attribute_of< | |
740 | karma::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
741 | >::type> | |
742 | {}; | |
743 | ||
744 | template < | |
745 | typename IteratorA, typename IteratorB, typename Context | |
746 | , typename T1, typename T2, typename T3, typename T4> | |
747 | struct handles_container<karma::grammar<IteratorA, T1, T2, T3, T4> | |
748 | , utree, Context, IteratorB> | |
749 | : detail::handles_utree_container<typename attribute_of< | |
750 | karma::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
751 | >::type> | |
752 | {}; | |
753 | ||
754 | /////////////////////////////////////////////////////////////////////////// | |
755 | template <typename Attribute, typename Sequence> | |
756 | struct pass_through_container< | |
757 | utree, utree, Attribute, Sequence, karma::domain> | |
758 | : detail::handles_utree_container<Attribute> | |
759 | {}; | |
760 | ||
761 | /////////////////////////////////////////////////////////////////////////// | |
762 | // the specialization below tells Spirit how to handle utree if it is used | |
763 | // with an optional component | |
764 | template <> | |
765 | struct optional_attribute<utree> | |
766 | { | |
767 | typedef utree const& type; | |
768 | ||
769 | static type call(utree const& val) | |
770 | { | |
771 | return val; | |
772 | } | |
773 | ||
774 | // only 'invalid_type' utree nodes are not valid | |
775 | static bool is_valid(utree const& val) | |
776 | { | |
777 | return !detail::is_uninitialized(val); | |
778 | } | |
779 | }; | |
780 | ||
781 | template <> | |
782 | struct build_optional<utree> | |
783 | { | |
784 | typedef utree type; | |
785 | }; | |
786 | ||
787 | template <> | |
788 | struct build_optional<utree::list_type> | |
789 | { | |
790 | typedef utree::list_type type; | |
791 | }; | |
792 | ||
793 | // an utree is an optional (in any domain) | |
794 | template <> | |
795 | struct not_is_optional<utree, qi::domain> | |
796 | : mpl::false_ | |
797 | {}; | |
798 | ||
799 | template <> | |
800 | struct not_is_optional<utree::list_type, qi::domain> | |
801 | : mpl::false_ | |
802 | {}; | |
803 | ||
804 | template <> | |
805 | struct not_is_optional<utree, karma::domain> | |
806 | : mpl::false_ | |
807 | {}; | |
808 | ||
809 | template <> | |
810 | struct not_is_optional<utree::list_type, karma::domain> | |
811 | : mpl::false_ | |
812 | {}; | |
813 | ||
814 | /////////////////////////////////////////////////////////////////////////// | |
815 | // the specialization below tells Spirit to handle utree as if it | |
816 | // where a 'real' variant (in the context of karma) | |
817 | template <> | |
818 | struct not_is_variant<utree, karma::domain> | |
819 | : mpl::false_ | |
820 | {}; | |
821 | ||
822 | template <> | |
823 | struct not_is_variant<utree::list_type, karma::domain> | |
824 | : mpl::false_ | |
825 | {}; | |
826 | ||
827 | // The specializations below tell Spirit to verify whether an attribute | |
828 | // type is compatible with a given variant type | |
829 | template <> | |
830 | struct compute_compatible_component_variant< | |
831 | utree, iterator_range<utree::iterator> > | |
832 | : mpl::true_ | |
833 | { | |
834 | typedef iterator_range<utree::iterator> compatible_type; | |
835 | ||
836 | static bool is_compatible(int d) | |
837 | { | |
838 | return d == utree_type::list_type; | |
839 | } | |
840 | }; | |
841 | ||
842 | template <> | |
843 | struct compute_compatible_component_variant< | |
844 | utree, iterator_range<utree::const_iterator> > | |
845 | : mpl::true_ | |
846 | { | |
847 | typedef iterator_range<utree::const_iterator> compatible_type; | |
848 | ||
849 | static bool is_compatible(int d) | |
850 | { | |
851 | return d == utree_type::list_type; | |
852 | } | |
853 | }; | |
854 | ||
855 | template <> | |
856 | struct compute_compatible_component_variant<utree, utree::invalid_type> | |
857 | : mpl::true_ | |
858 | { | |
859 | typedef utree::invalid_type compatible_type; | |
860 | ||
861 | static bool is_compatible(int d) | |
862 | { | |
863 | return d == utree_type::invalid_type; | |
864 | } | |
865 | }; | |
866 | ||
867 | template <> | |
868 | struct compute_compatible_component_variant<utree, utree::nil_type> | |
869 | : mpl::true_ | |
870 | { | |
871 | typedef utree::nil_type compatible_type; | |
872 | ||
873 | static bool is_compatible(int d) | |
874 | { | |
875 | return d == utree_type::nil_type; | |
876 | } | |
877 | }; | |
878 | ||
879 | template <> | |
880 | struct compute_compatible_component_variant<utree, bool> | |
881 | : mpl::true_ | |
882 | { | |
883 | typedef bool compatible_type; | |
884 | ||
885 | static bool is_compatible(int d) | |
886 | { | |
887 | return d == utree_type::bool_type; | |
888 | } | |
889 | }; | |
890 | ||
891 | template <> | |
892 | struct compute_compatible_component_variant<utree, int> | |
893 | : mpl::true_ | |
894 | { | |
895 | typedef int compatible_type; | |
896 | ||
897 | static bool is_compatible(int d) | |
898 | { | |
899 | return d == utree_type::int_type; | |
900 | } | |
901 | }; | |
902 | ||
903 | template <> | |
904 | struct compute_compatible_component_variant<utree, double> | |
905 | : mpl::true_ | |
906 | { | |
907 | typedef double compatible_type; | |
908 | ||
909 | static bool is_compatible(int d) | |
910 | { | |
911 | return d == utree_type::double_type; | |
912 | } | |
913 | }; | |
914 | ||
915 | template <> | |
916 | struct compute_compatible_component_variant< | |
917 | utree, utf8_string_range_type> | |
918 | : mpl::true_ | |
919 | { | |
920 | typedef utf8_string_range_type compatible_type; | |
921 | ||
922 | static bool is_compatible(int d) | |
923 | { | |
924 | return d == utree_type::string_type; | |
925 | } | |
926 | }; | |
927 | ||
928 | template <> | |
929 | struct compute_compatible_component_variant< | |
930 | utree, utf8_string_type> | |
931 | : mpl::true_ | |
932 | { | |
933 | typedef utf8_string_type compatible_type; | |
934 | ||
935 | static bool is_compatible(int d) | |
936 | { | |
937 | return d == utree_type::string_type; | |
938 | } | |
939 | }; | |
940 | ||
941 | template <> | |
942 | struct compute_compatible_component_variant< | |
943 | utree, utf8_symbol_range_type> | |
944 | : mpl::true_ | |
945 | { | |
946 | typedef utf8_symbol_range_type compatible_type; | |
947 | ||
948 | static bool is_compatible(int d) | |
949 | { | |
950 | return d == utree_type::symbol_type; | |
951 | } | |
952 | }; | |
953 | ||
954 | template <> | |
955 | struct compute_compatible_component_variant< | |
956 | utree, utf8_symbol_type> | |
957 | : mpl::true_ | |
958 | { | |
959 | typedef utf8_symbol_type compatible_type; | |
960 | ||
961 | static bool is_compatible(int d) | |
962 | { | |
963 | return d == utree_type::symbol_type; | |
964 | } | |
965 | }; | |
966 | ||
967 | template <> | |
968 | struct compute_compatible_component_variant< | |
969 | utree, binary_range_type> | |
970 | : mpl::true_ | |
971 | { | |
972 | typedef binary_range_type compatible_type; | |
973 | ||
974 | static bool is_compatible(int d) | |
975 | { | |
976 | return d == utree_type::binary_type; | |
977 | } | |
978 | }; | |
979 | ||
980 | template <> | |
981 | struct compute_compatible_component_variant< | |
982 | utree, binary_string_type> | |
983 | : mpl::true_ | |
984 | { | |
985 | typedef binary_string_type compatible_type; | |
986 | ||
987 | static bool is_compatible(int d) | |
988 | { | |
989 | return d == utree_type::binary_type; | |
990 | } | |
991 | }; | |
992 | ||
993 | template <> | |
994 | struct compute_compatible_component_variant<utree, utree> | |
995 | : mpl::true_ | |
996 | { | |
997 | typedef utree compatible_type; | |
998 | ||
999 | static bool is_compatible(int d) | |
1000 | { | |
1001 | return d >= utree_type::invalid_type && | |
1002 | d <= utree_type::reference_type; | |
1003 | } | |
1004 | }; | |
1005 | ||
1006 | template <> | |
1007 | struct compute_compatible_component_variant< | |
1008 | utree, std::vector<utree> > | |
1009 | : mpl::true_ | |
1010 | { | |
1011 | typedef utree compatible_type; | |
1012 | ||
1013 | static bool is_compatible(int d) | |
1014 | { | |
1015 | return d >= utree_type::invalid_type && | |
1016 | d <= utree_type::reference_type; | |
1017 | } | |
1018 | }; | |
1019 | ||
1020 | template <typename Sequence> | |
1021 | struct compute_compatible_component_variant<utree, Sequence | |
1022 | , mpl::false_ | |
1023 | , typename enable_if<fusion::traits::is_sequence<Sequence> >::type> | |
1024 | : mpl::true_ | |
1025 | { | |
1026 | typedef iterator_range<utree::const_iterator> compatible_type; | |
1027 | ||
1028 | static bool is_compatible(int d) | |
1029 | { | |
1030 | return d == utree_type::list_type; | |
1031 | } | |
1032 | }; | |
1033 | ||
1034 | template <typename Attribute> | |
1035 | struct compute_compatible_component_variant<utree::list_type, Attribute> | |
1036 | : compute_compatible_component_variant<utree, Attribute> | |
1037 | {}; | |
1038 | ||
1039 | /////////////////////////////////////////////////////////////////////////// | |
1040 | template <> | |
1041 | struct symbols_lookup<utree, utf8_symbol_type> | |
1042 | { | |
1043 | typedef std::string type; | |
1044 | ||
1045 | static type call(utree const& t) | |
1046 | { | |
1047 | utf8_symbol_range_type r = boost::get<utf8_symbol_range_type>(t); | |
1048 | return std::string(traits::begin(r), traits::end(r)); | |
1049 | } | |
1050 | }; | |
1051 | ||
1052 | template <> | |
1053 | struct symbols_lookup<utf8_symbol_type, utf8_symbol_type> | |
1054 | { | |
1055 | typedef std::string type; | |
1056 | ||
1057 | static type call(utf8_symbol_type const& t) | |
1058 | { | |
1059 | return t; | |
1060 | } | |
1061 | }; | |
1062 | ||
1063 | /////////////////////////////////////////////////////////////////////////// | |
1064 | namespace detail | |
1065 | { | |
1066 | template <typename T> | |
1067 | inline T get_or_deref(utree const& t) | |
1068 | { | |
1069 | if (detail::is_list(t)) | |
1070 | return boost::get<T>(t.front()); | |
1071 | return boost::get<T>(t); | |
1072 | } | |
1073 | } | |
1074 | ||
1075 | template <> | |
1076 | struct extract_from_container<utree, utree::nil_type> | |
1077 | { | |
1078 | typedef utree::nil_type type; | |
1079 | ||
1080 | template <typename Context> | |
1081 | static type call(utree const&, Context&) | |
1082 | { | |
1083 | return nil; | |
1084 | } | |
1085 | }; | |
1086 | ||
1087 | template <> | |
1088 | struct extract_from_container<utree, char> | |
1089 | { | |
1090 | typedef char type; | |
1091 | ||
1092 | template <typename Context> | |
1093 | static type call(utree const& t, Context&) | |
1094 | { | |
1095 | utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t); | |
1096 | return r.front(); | |
1097 | } | |
1098 | }; | |
1099 | ||
1100 | template <> | |
1101 | struct extract_from_container<utree, bool> | |
1102 | { | |
1103 | typedef bool type; | |
1104 | ||
1105 | template <typename Context> | |
1106 | static type call(utree const& t, Context&) | |
1107 | { | |
1108 | return detail::get_or_deref<bool>(t); | |
1109 | } | |
1110 | }; | |
1111 | ||
1112 | template <> | |
1113 | struct extract_from_container<utree, int> | |
1114 | { | |
1115 | typedef int type; | |
1116 | ||
1117 | template <typename Context> | |
1118 | static type call(utree const& t, Context&) | |
1119 | { | |
1120 | return detail::get_or_deref<int>(t); | |
1121 | } | |
1122 | }; | |
1123 | ||
1124 | template <> | |
1125 | struct extract_from_container<utree, double> | |
1126 | { | |
1127 | typedef double type; | |
1128 | ||
1129 | template <typename Context> | |
1130 | static type call(utree const& t, Context&) | |
1131 | { | |
1132 | return detail::get_or_deref<double>(t); | |
1133 | } | |
1134 | }; | |
1135 | ||
1136 | template <typename Traits, typename Alloc> | |
1137 | struct extract_from_container<utree, std::basic_string<char, Traits, Alloc> > | |
1138 | { | |
1139 | typedef std::basic_string<char, Traits, Alloc> type; | |
1140 | ||
1141 | template <typename Context> | |
1142 | static type call(utree const& t, Context&) | |
1143 | { | |
1144 | utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t); | |
1145 | return type(traits::begin(r), traits::end(r)); | |
1146 | } | |
1147 | }; | |
1148 | ||
1149 | template <> | |
1150 | struct extract_from_container<utree, utf8_symbol_type> | |
1151 | { | |
1152 | typedef std::string type; | |
1153 | ||
1154 | template <typename Context> | |
1155 | static type call(utree const& t, Context&) | |
1156 | { | |
1157 | utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t); | |
1158 | return std::string(traits::begin(r), traits::end(r)); | |
1159 | } | |
1160 | }; | |
1161 | ||
1162 | template <> | |
1163 | struct extract_from_container<utree, utf8_string_type> | |
1164 | { | |
1165 | typedef std::string type; | |
1166 | ||
1167 | template <typename Context> | |
1168 | static type call(utree const& t, Context&) | |
1169 | { | |
1170 | utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t); | |
1171 | return std::string(traits::begin(r), traits::end(r)); | |
1172 | } | |
1173 | }; | |
1174 | ||
1175 | /////////////////////////////////////////////////////////////////////////// | |
1176 | template <> | |
1177 | struct transform_attribute<utree const, utree::nil_type, karma::domain> | |
1178 | { | |
1179 | typedef utree::nil_type type; | |
1180 | ||
1181 | static type pre(utree const&) | |
1182 | { | |
1183 | return nil; | |
1184 | } | |
1185 | }; | |
1186 | ||
1187 | template <> | |
1188 | struct transform_attribute<utree const, char, karma::domain> | |
1189 | { | |
1190 | typedef char type; | |
1191 | ||
1192 | static type pre(utree const& t) | |
1193 | { | |
1194 | utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t); | |
1195 | return r.front(); | |
1196 | } | |
1197 | }; | |
1198 | ||
1199 | template <> | |
1200 | struct transform_attribute<utree const, bool, karma::domain> | |
1201 | { | |
1202 | typedef bool type; | |
1203 | ||
1204 | static type pre(utree const& t) | |
1205 | { | |
1206 | return detail::get_or_deref<bool>(t); | |
1207 | } | |
1208 | }; | |
1209 | ||
1210 | template <> | |
1211 | struct transform_attribute<utree const, int, karma::domain> | |
1212 | { | |
1213 | typedef int type; | |
1214 | ||
1215 | static type pre(utree const& t) | |
1216 | { | |
1217 | return detail::get_or_deref<int>(t); | |
1218 | } | |
1219 | }; | |
1220 | ||
1221 | template <> | |
1222 | struct transform_attribute<utree const, double, karma::domain> | |
1223 | { | |
1224 | typedef double type; | |
1225 | ||
1226 | static type pre(utree const& t) | |
1227 | { | |
1228 | return detail::get_or_deref<double>(t); | |
1229 | } | |
1230 | }; | |
1231 | ||
1232 | template <typename Traits, typename Alloc> | |
1233 | struct transform_attribute< | |
1234 | utree const, std::basic_string<char, Traits, Alloc>, karma::domain> | |
1235 | { | |
1236 | typedef std::basic_string<char, Traits, Alloc> type; | |
1237 | ||
1238 | static type pre(utree const& t) | |
1239 | { | |
1240 | utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t); | |
1241 | return type(traits::begin(r), traits::end(r)); | |
1242 | } | |
1243 | }; | |
1244 | ||
1245 | // this specialization is used whenever a utree is passed to a rule as part | |
1246 | // of a sequence | |
1247 | template <typename Iterator> | |
1248 | struct transform_attribute< | |
1249 | iterator_range<Iterator> const, utree, karma::domain> | |
1250 | { | |
1251 | typedef utree type; | |
1252 | ||
1253 | static type pre(iterator_range<Iterator> const& t) | |
1254 | { | |
1255 | // return utree the begin iterator points to | |
1256 | Iterator it = boost::begin(t); | |
1257 | utree result(boost::ref(*it)); | |
1258 | ++it; | |
1259 | return result; | |
1260 | } | |
1261 | }; | |
1262 | ||
1263 | /////////////////////////////////////////////////////////////////////////// | |
1264 | template <> | |
1265 | struct transform_attribute<utree const, utf8_string_type, karma::domain> | |
1266 | { | |
1267 | typedef std::string type; | |
1268 | ||
1269 | static type pre(utree const& t) | |
1270 | { | |
1271 | utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t); | |
1272 | return std::string(traits::begin(r), traits::end(r)); | |
1273 | } | |
1274 | }; | |
1275 | ||
1276 | template <> | |
1277 | struct transform_attribute<utree const, utf8_symbol_type, karma::domain> | |
1278 | { | |
1279 | typedef std::string type; | |
1280 | ||
1281 | static type pre(utree const& t) | |
1282 | { | |
1283 | utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t); | |
1284 | return std::string(traits::begin(r), traits::end(r)); | |
1285 | } | |
1286 | }; | |
1287 | ||
1288 | template <typename Attribute> | |
1289 | struct transform_attribute<utree::list_type const, Attribute, karma::domain> | |
1290 | : transform_attribute<utree const, Attribute, karma::domain> | |
1291 | {}; | |
1292 | }}} | |
1293 | ||
1294 | #endif |