1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2012 Hartmut Kaiser
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM)
9 #define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
15 #include <boost/spirit/home/support/unused.hpp>
16 #include <boost/spirit/home/support/has_semantic_action.hpp>
17 #include <boost/spirit/home/support/attributes_fwd.hpp>
18 #include <boost/spirit/home/support/container.hpp>
19 #include <boost/spirit/home/support/detail/hold_any.hpp>
20 #include <boost/spirit/home/support/detail/as_variant.hpp>
21 #include <boost/optional/optional.hpp>
22 #include <boost/fusion/include/transform.hpp>
23 #include <boost/fusion/include/filter_if.hpp>
24 #include <boost/fusion/include/as_vector.hpp>
25 #include <boost/fusion/include/push_front.hpp>
26 #include <boost/fusion/include/pop_front.hpp>
27 #include <boost/fusion/include/is_sequence.hpp>
28 #include <boost/fusion/include/for_each.hpp>
29 #include <boost/fusion/include/is_view.hpp>
30 #include <boost/fusion/include/mpl.hpp>
31 #include <boost/foreach.hpp>
32 #include <boost/utility/value_init.hpp>
33 #include <boost/type_traits/is_same.hpp>
34 #include <boost/type_traits/is_convertible.hpp>
35 #include <boost/mpl/eval_if.hpp>
36 #include <boost/mpl/end.hpp>
37 #include <boost/mpl/find_if.hpp>
38 #include <boost/mpl/identity.hpp>
39 #include <boost/mpl/deref.hpp>
40 #include <boost/mpl/distance.hpp>
41 #include <boost/mpl/or.hpp>
42 #include <boost/mpl/has_xxx.hpp>
43 #include <boost/mpl/equal.hpp>
44 #include <boost/proto/proto_fwd.hpp>
45 #include <boost/utility/enable_if.hpp>
46 #include <boost/variant.hpp>
47 #include <boost/range/iterator_range.hpp>
48 #include <boost/config.hpp>
49 #include <vector>
50 #include <utility>
51 #include <ios>
52 
53 ///////////////////////////////////////////////////////////////////////////////
54 namespace boost { namespace spirit { namespace traits
55 {
56     ///////////////////////////////////////////////////////////////////////////
57     // This file deals with attribute related functions and meta-functions
58     // including generalized attribute transformation utilities for Spirit
59     // components.
60     ///////////////////////////////////////////////////////////////////////////
61 
62     ///////////////////////////////////////////////////////////////////////////
63     // Find out if T can be a (strong) substitute for Expected attribute
64     namespace detail
65     {
66         template <typename T, typename Expected>
67         struct value_type_is_substitute
68           : is_substitute<
69                 typename container_value<T>::type
70               , typename container_value<Expected>::type>
71         {};
72 
73         template <typename T, typename Expected, typename Enable = void>
74         struct is_substitute_impl : is_same<T, Expected> {};
75 
76         template <typename T, typename Expected>
77         struct is_substitute_impl<T, Expected,
78             typename enable_if<
79                 mpl::and_<
80                     fusion::traits::is_sequence<T>,
81                     fusion::traits::is_sequence<Expected>,
82                     mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> >
83                 >
84             >::type>
85           : mpl::true_ {};
86 
87         template <typename T, typename Expected>
88         struct is_substitute_impl<T, Expected,
89             typename enable_if<
90                 mpl::and_<
91                     is_container<T>,
92                     is_container<Expected>,
93                     detail::value_type_is_substitute<T, Expected>
94                 >
95             >::type>
96           : mpl::true_ {};
97     }
98 
99     template <typename T, typename Expected, typename Enable /*= void*/>
100     struct is_substitute
101       : detail::is_substitute_impl<T, Expected> {};
102 
103     template <typename T, typename Expected>
104     struct is_substitute<optional<T>, optional<Expected> >
105       : is_substitute<T, Expected> {};
106 
107     template <typename T>
108     struct is_substitute<T, T
109           , typename enable_if<not_is_optional<T> >::type>
110       : mpl::true_ {};
111 
112     ///////////////////////////////////////////////////////////////////////////
113     // Find out if T can be a weak substitute for Expected attribute
114     namespace detail
115     {
116         // A type, which is convertible to the attribute is at the same time
117         // usable as its weak substitute.
118         template <typename T, typename Expected, typename Enable = void>
119         struct is_weak_substitute_impl : is_convertible<T, Expected> {};
120 
121 //        // An exposed attribute is a weak substitute for a supplied container
122 //        // attribute if it is a weak substitute for its value_type. This is
123 //        // true as all character parsers are compatible with a container
124 //        // attribute having the corresponding character type as its value_type.
125 //        template <typename T, typename Expected>
126 //        struct is_weak_substitute_for_value_type
127 //          : is_weak_substitute<T, typename container_value<Expected>::type>
128 //        {};
129 //
130 //        template <typename T, typename Expected>
131 //        struct is_weak_substitute_impl<T, Expected,
132 //            typename enable_if<
133 //                mpl::and_<
134 //                    mpl::not_<is_string<T> >
135 //                  , is_string<Expected>
136 //                  , is_weak_substitute_for_value_type<T, Expected> >
137 //            >::type>
138 //          : mpl::true_
139 //        {};
140 
141         // An exposed container attribute is a weak substitute for a supplied
142         // container attribute if and only if their value_types are weak
143         // substitutes.
144         template <typename T, typename Expected>
145         struct value_type_is_weak_substitute
146           : is_weak_substitute<
147                 typename container_value<T>::type
148               , typename container_value<Expected>::type>
149         {};
150 
151         template <typename T, typename Expected>
152         struct is_weak_substitute_impl<T, Expected,
153             typename enable_if<
154                 mpl::and_<
155                     is_container<T>
156                   , is_container<Expected>
157                   , value_type_is_weak_substitute<T, Expected> >
158             >::type>
159           : mpl::true_ {};
160 
161         // Two fusion sequences are weak substitutes if and only if their
162         // elements are pairwise weak substitutes.
163         template <typename T, typename Expected>
164         struct is_weak_substitute_impl<T, Expected,
165             typename enable_if<
166                 mpl::and_<
167                     fusion::traits::is_sequence<T>
168                   , fusion::traits::is_sequence<Expected>
169                   , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > >
170             >::type>
171           : mpl::true_ {};
172 
173         // If this is not defined, the main template definition above will return
174         // true if T is convertible to the first type in a fusion::vector. We
175         // globally declare any non-Fusion sequence T as not compatible with any
176         // Fusion sequence 'Expected'.
177         template <typename T, typename Expected>
178         struct is_weak_substitute_impl<T, Expected,
179             typename enable_if<
180                 mpl::and_<
181                     mpl::not_<fusion::traits::is_sequence<T> >
182                   , fusion::traits::is_sequence<Expected> >
183             >::type>
184           : mpl::false_ {};
185     }
186 
187     // main template forwards to detail namespace, this helps older compilers
188     // to disambiguate things
189     template <typename T, typename Expected, typename Enable /*= void*/>
190     struct is_weak_substitute
191       : detail::is_weak_substitute_impl<T, Expected> {};
192 
193     template <typename T, typename Expected>
194     struct is_weak_substitute<optional<T>, optional<Expected> >
195       : is_weak_substitute<T, Expected> {};
196 
197     template <typename T, typename Expected>
198     struct is_weak_substitute<optional<T>, Expected>
199       : is_weak_substitute<T, Expected> {};
200 
201     template <typename T, typename Expected>
202     struct is_weak_substitute<T, optional<Expected> >
203       : is_weak_substitute<T, Expected> {};
204 
205 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
206     template <typename T, typename Expected>
207     struct is_weak_substitute<boost::variant<T>, Expected>
208       : is_weak_substitute<T, Expected>
209     {};
210 
211     template <typename T0, typename T1, typename ...TN, typename Expected>
212     struct is_weak_substitute<boost::variant<T0, T1, TN...>,
213             Expected>
214       : mpl::bool_<is_weak_substitute<T0, Expected>::type::value &&
215             is_weak_substitute<boost::variant<T1, TN...>, Expected>::type::value>
216     {};
217 #else
218 #define BOOST_SPIRIT_IS_WEAK_SUBSTITUTE(z, N, _)                              \
219     is_weak_substitute<BOOST_PP_CAT(T, N), Expected>::type::value &&          \
220     /***/
221 
222     // make sure unused variant parameters do not affect the outcome
223     template <typename Expected>
224     struct is_weak_substitute<boost::detail::variant::void_, Expected>
225       : mpl::true_
226     {};
227 
228     template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Expected>
229     struct is_weak_substitute<
230             boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Expected>
231       : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
232           , BOOST_SPIRIT_IS_WEAK_SUBSTITUTE, _) true>
233     {};
234 
235 #undef BOOST_SPIRIT_IS_WEAK_SUBSTITUTE
236 #endif
237 
238     template <typename T>
239     struct is_weak_substitute<T, T
240           , typename enable_if<
241                 mpl::and_<not_is_optional<T>, not_is_variant<T> >
242             >::type>
243       : mpl::true_ {};
244 
245     ///////////////////////////////////////////////////////////////////////////
246     template <typename T, typename Enable/* = void*/>
247     struct is_proxy : mpl::false_ {};
248 
249     template <typename T>
250     struct is_proxy<T,
251         typename enable_if<
252             mpl::and_<
253                 fusion::traits::is_sequence<T>,
254                 fusion::traits::is_view<T>
255             >
256         >::type>
257       : mpl::true_ {};
258 
259     namespace detail
260     {
261         // By declaring a nested struct in your class/struct, you tell
262         // spirit that it is regarded as a variant type. The minimum
263         // required interface for such a variant is that it has constructors
264         // for various types supported by your variant and a typedef 'types'
265         // which is an mpl sequence of the contained types.
266         //
267         // This is an intrusive interface. For a non-intrusive interface,
268         // use the not_is_variant trait.
269         BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag)
270     }
271 
272     template <typename T, typename Domain, typename Enable/* = void*/>
273     struct not_is_variant
274       : mpl::not_<detail::has_adapted_variant_tag<T> >
275     {};
276 
277     template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain>
278     struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain>
279       : mpl::false_
280     {};
281 
282     template <typename T, typename Domain>
283     struct not_is_variant<boost::optional<T>, Domain>
284       : not_is_variant<T, Domain>
285     {};
286 
287     // we treat every type as if it where the variant (as this meta function is
288     // invoked for variant types only)
289     template <typename T>
290     struct variant_type
291       : mpl::identity<T>
292     {};
293 
294     template <typename T>
295     struct variant_type<boost::optional<T> >
296       : variant_type<T>
297     {};
298 
299     ///////////////////////////////////////////////////////////////////////////
300     // The compute_compatible_component_variant
301     ///////////////////////////////////////////////////////////////////////////
302     namespace detail
303     {
304         //  A component is compatible to a given Attribute type if the
305         //  Attribute is the same as the expected type of the component or if
306         //  it is convertible to the expected type.
307         template <typename Expected, typename Attribute>
308         struct attribute_is_compatible
309           : is_convertible<Attribute, Expected>
310         {};
311 
312         template <typename Expected, typename Attribute>
313         struct attribute_is_compatible<Expected, boost::optional<Attribute> >
314           : is_convertible<Attribute, Expected>
315         {};
316 
317         template <typename Container>
318         struct is_hold_any_container
319           : traits::is_hold_any<typename traits::container_value<Container>::type>
320         {};
321     }
322 
323     template <typename Attribute, typename Expected
324       , typename IsNotVariant = mpl::false_, typename Enable = void>
325     struct compute_compatible_component_variant
326       : mpl::or_<
327             traits::detail::attribute_is_compatible<Expected, Attribute>
328           , traits::is_hold_any<Expected>
329           , mpl::eval_if<
330                 is_container<Expected>
331               , traits::detail::is_hold_any_container<Expected>
332               , mpl::false_> >
333     {};
334 
335     namespace detail
336     {
337         BOOST_MPL_HAS_XXX_TRAIT_DEF(types)
338     }
339 
340     template <typename Variant, typename Expected>
341     struct compute_compatible_component_variant<Variant, Expected, mpl::false_
342       , typename enable_if<detail::has_types<Variant> >::type>
343     {
344         typedef typename traits::variant_type<Variant>::type variant_type;
345         typedef typename variant_type::types types;
346         typedef typename mpl::end<types>::type end;
347 
348         typedef typename
349             mpl::find_if<types, is_same<Expected, mpl::_1> >::type
350         iter;
351 
352         typedef typename mpl::distance<
353             typename mpl::begin<types>::type, iter
354         >::type distance;
355 
356         // true_ if the attribute matches one of the types in the variant
357         typedef typename mpl::not_<is_same<iter, end> >::type type;
358         enum { value = type::value };
359 
360         // return the type in the variant the attribute is compatible with
361         typedef typename
362             mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type
363         compatible_type;
364 
365         // return whether the given type is compatible with the Expected type
is_compatibleboost::spirit::traits::compute_compatible_component_variant366         static bool is_compatible(int which)
367         {
368             return which == distance::value;
369         }
370     };
371 
372     template <typename Expected, typename Attribute, typename Domain>
373     struct compute_compatible_component
374       : compute_compatible_component_variant<Attribute, Expected
375           , typename spirit::traits::not_is_variant<Attribute, Domain>::type> {};
376 
377     template <typename Expected, typename Domain>
378     struct compute_compatible_component<Expected, unused_type, Domain>
379       : mpl::false_ {};
380 
381     template <typename Attribute, typename Domain>
382     struct compute_compatible_component<unused_type, Attribute, Domain>
383       : mpl::false_ {};
384 
385     template <typename Domain>
386     struct compute_compatible_component<unused_type, unused_type, Domain>
387       : mpl::false_ {};
388 
389     ///////////////////////////////////////////////////////////////////////////
390     // return the type currently stored in the given variant
391     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
392     struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
393     {
callboost::spirit::traits::variant_which394         static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
395         {
396             return v.which();
397         }
398     };
399 
400     template <typename T>
which(T const & v)401     int which(T const& v)
402     {
403         return variant_which<T>::call(v);
404     }
405 
406     ///////////////////////////////////////////////////////////////////////////
407     template <typename T, typename Domain, typename Enable/* = void*/>
408     struct not_is_optional
409       : mpl::true_
410     {};
411 
412     template <typename T, typename Domain>
413     struct not_is_optional<boost::optional<T>, Domain>
414       : mpl::false_
415     {};
416 
417     ///////////////////////////////////////////////////////////////////////////
418     // attribute_of
419     //
420     // Get the component's attribute
421     ///////////////////////////////////////////////////////////////////////////
422     template <typename Component
423       , typename Context = unused_type, typename Iterator = unused_type>
424     struct attribute_of
425     {
426         typedef typename Component::template
427             attribute<Context, Iterator>::type type;
428     };
429 
430     ///////////////////////////////////////////////////////////////////////////
431     // attribute_not_unused
432     //
433     // An mpl meta-function class that determines whether a component's
434     // attribute is not unused.
435     ///////////////////////////////////////////////////////////////////////////
436     template <typename Context, typename Iterator = unused_type>
437     struct attribute_not_unused
438     {
439         template <typename Component>
440         struct apply
441           : not_is_unused<typename
442                 attribute_of<Component, Context, Iterator>::type>
443         {};
444     };
445 
446     ///////////////////////////////////////////////////////////////////////////
447     // Retrieve the attribute type to use from the given type
448     //
449     // This is needed to extract the correct attribute type from proxy classes
450     // as utilized in FUSION_ADAPT_ADT et. al.
451     ///////////////////////////////////////////////////////////////////////////
452     template <typename Attribute, typename Enable/* = void*/>
453     struct attribute_type : mpl::identity<Attribute> {};
454 
455     ///////////////////////////////////////////////////////////////////////////
456     // Retrieve the size of a fusion sequence (compile time)
457     ///////////////////////////////////////////////////////////////////////////
458     template <typename T>
459     struct sequence_size
460       : fusion::result_of::size<T>
461     {};
462 
463     template <>
464     struct sequence_size<unused_type>
465       : mpl::int_<0>
466     {};
467 
468     ///////////////////////////////////////////////////////////////////////////
469     // Retrieve the size of an attribute (runtime)
470     ///////////////////////////////////////////////////////////////////////////
471     namespace detail
472     {
473         template <typename Attribute, typename Enable = void>
474         struct attribute_size_impl
475         {
476             typedef std::size_t type;
477 
callboost::spirit::traits::detail::attribute_size_impl478             static type call(Attribute const&)
479             {
480                 return 1;
481             }
482         };
483 
484         template <typename Attribute>
485         struct attribute_size_impl<Attribute
486           , typename enable_if<
487                 mpl::and_<
488                     fusion::traits::is_sequence<Attribute>
489                   , mpl::not_<traits::is_container<Attribute> >
490                 >
491             >::type>
492         {
493             typedef typename fusion::result_of::size<Attribute>::value_type type;
494 
callboost::spirit::traits::detail::attribute_size_impl495             static type call(Attribute const& attr)
496             {
497                 return fusion::size(attr);
498             }
499         };
500 
501         template <typename Attribute>
502         struct attribute_size_impl<Attribute
503           , typename enable_if<
504                 mpl::and_<
505                     traits::is_container<Attribute>
506                   , mpl::not_<traits::is_iterator_range<Attribute> >
507                 >
508             >::type>
509         {
510             typedef typename Attribute::size_type type;
511 
callboost::spirit::traits::detail::attribute_size_impl512             static type call(Attribute const& attr)
513             {
514                 return attr.size();
515             }
516         };
517     }
518 
519     template <typename Attribute, typename Enable/* = void*/>
520     struct attribute_size
521       : detail::attribute_size_impl<Attribute>
522     {};
523 
524     template <typename Attribute>
525     struct attribute_size<optional<Attribute> >
526     {
527         typedef typename attribute_size<Attribute>::type type;
528 
callboost::spirit::traits::attribute_size529         static type call(optional<Attribute> const& val)
530         {
531             if (!val)
532                 return 0;
533             return traits::size(val.get());
534         }
535     };
536 
537     namespace detail
538     {
539         struct attribute_size_visitor : static_visitor<std::size_t>
540         {
541             template <typename T>
operator ()boost::spirit::traits::detail::attribute_size_visitor542             std::size_t operator()(T const& val) const
543             {
544                 return spirit::traits::size(val);
545             }
546         };
547     }
548 
549     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
550     struct attribute_size<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
551     {
552         typedef std::size_t type;
553 
callboost::spirit::traits::attribute_size554         static type call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val)
555         {
556             return apply_visitor(detail::attribute_size_visitor(), val);
557         }
558     };
559 
560     template <typename Iterator>
561     struct attribute_size<iterator_range<Iterator> >
562     {
563         typedef typename boost::detail::iterator_traits<Iterator>::
564             difference_type type;
565 
callboost::spirit::traits::attribute_size566         static type call(iterator_range<Iterator> const& r)
567         {
568             return boost::detail::distance(r.begin(), r.end());
569         }
570     };
571 
572     template <>
573     struct attribute_size<unused_type>
574     {
575         typedef std::size_t type;
576 
callboost::spirit::traits::attribute_size577         static type call(unused_type)
578         {
579             return 0;
580         }
581     };
582 
583     template <typename Attribute>
584     typename attribute_size<Attribute>::type
size(Attribute const & attr)585     size (Attribute const& attr)
586     {
587         return attribute_size<Attribute>::call(attr);
588     }
589 
590     ///////////////////////////////////////////////////////////////////////////
591     // pass_attribute
592     //
593     // Determines how we pass attributes to semantic actions. This
594     // may be specialized. By default, all attributes are wrapped in
595     // a fusion sequence, because the attribute has to be treated as being
596     // a single value in any case (even if it actually already is a fusion
597     // sequence in its own).
598     ///////////////////////////////////////////////////////////////////////////
599     template <typename Component, typename Attribute, typename Enable/* = void*/>
600     struct pass_attribute
601     {
602         typedef fusion::vector1<Attribute&> type;
603     };
604 
605     ///////////////////////////////////////////////////////////////////////////
606     // Subclass a pass_attribute specialization from this to wrap
607     // the attribute in a tuple only IFF it is not already a fusion tuple.
608     ///////////////////////////////////////////////////////////////////////////
609     template <typename Attribute, typename Force = mpl::false_>
610     struct wrap_if_not_tuple
611       : mpl::if_<
612             fusion::traits::is_sequence<Attribute>
613           , Attribute&, fusion::vector1<Attribute&> >
614     {};
615 
616     template <typename Attribute>
617     struct wrap_if_not_tuple<Attribute, mpl::true_>
618     {
619         typedef fusion::vector1<Attribute&> type;
620     };
621 
622     template <>
623     struct wrap_if_not_tuple<unused_type, mpl::false_>
624     {
625         typedef unused_type type;
626     };
627 
628     template <>
629     struct wrap_if_not_tuple<unused_type const, mpl::false_>
630     {
631         typedef unused_type type;
632     };
633 
634     ///////////////////////////////////////////////////////////////////////////
635     // build_optional
636     //
637     // Build a boost::optional from T. Return unused_type if T is unused_type.
638     ///////////////////////////////////////////////////////////////////////////
639     template <typename T>
640     struct build_optional
641     {
642         typedef boost::optional<T> type;
643     };
644 
645     template <typename T>
646     struct build_optional<boost::optional<T> >
647     {
648         typedef boost::optional<T> type;
649     };
650 
651     template <>
652     struct build_optional<unused_type>
653     {
654         typedef unused_type type;
655     };
656 
657     ///////////////////////////////////////////////////////////////////////////
658     // build_std_vector
659     //
660     // Build a std::vector from T. Return unused_type if T is unused_type.
661     ///////////////////////////////////////////////////////////////////////////
662     template <typename T>
663     struct build_std_vector
664     {
665         typedef std::vector<T> type;
666     };
667 
668     template <>
669     struct build_std_vector<unused_type>
670     {
671         typedef unused_type type;
672     };
673 
674     ///////////////////////////////////////////////////////////////////////////
675     // filter_unused_attributes
676     //
677     // Remove unused_types from a sequence
678     ///////////////////////////////////////////////////////////////////////////
679 
680     // Compute the list of all *used* attributes of sub-components
681     // (filter all unused attributes from the list)
682     template <typename Sequence>
683     struct filter_unused_attributes
684       : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> >
685     {};
686 
687     ///////////////////////////////////////////////////////////////////////////
688     // sequence_attribute_transform
689     //
690     // This transform is invoked for every attribute in a sequence allowing
691     // to modify the attribute type exposed by a component to the enclosing
692     // sequence component. By default no transformation is performed.
693     ///////////////////////////////////////////////////////////////////////////
694     template <typename Attribute, typename Domain>
695     struct sequence_attribute_transform
696       : mpl::identity<Attribute>
697     {};
698 
699     ///////////////////////////////////////////////////////////////////////////
700     // permutation_attribute_transform
701     //
702     // This transform is invoked for every attribute in a sequence allowing
703     // to modify the attribute type exposed by a component to the enclosing
704     // permutation component. By default a build_optional transformation is
705     // performed.
706     ///////////////////////////////////////////////////////////////////////////
707     template <typename Attribute, typename Domain>
708     struct permutation_attribute_transform
709       : traits::build_optional<Attribute>
710     {};
711 
712     ///////////////////////////////////////////////////////////////////////////
713     // sequential_or_attribute_transform
714     //
715     // This transform is invoked for every attribute in a sequential_or allowing
716     // to modify the attribute type exposed by a component to the enclosing
717     // sequential_or component. By default a build_optional transformation is
718     // performed.
719     ///////////////////////////////////////////////////////////////////////////
720     template <typename Attribute, typename Domain>
721     struct sequential_or_attribute_transform
722       : traits::build_optional<Attribute>
723     {};
724 
725     ///////////////////////////////////////////////////////////////////////////
726     // build_fusion_vector
727     //
728     // Build a fusion vector from a fusion sequence. All unused attributes
729     // are filtered out. If the result is empty after the removal of unused
730     // types, return unused_type. If the input sequence is an unused_type,
731     // also return unused_type.
732     ///////////////////////////////////////////////////////////////////////////
733     template <typename Sequence>
734     struct build_fusion_vector
735     {
736         // Remove all unused attributes
737         typedef typename
738             filter_unused_attributes<Sequence>::type
739         filtered_attributes;
740 
741         // Build a fusion vector from a fusion sequence (Sequence),
742         // But *only if* the sequence is not empty. i.e. if the
743         // sequence is empty, our result will be unused_type.
744 
745         typedef typename
746             mpl::eval_if<
747                 fusion::result_of::empty<filtered_attributes>
748               , mpl::identity<unused_type>
749               , fusion::result_of::as_vector<filtered_attributes>
750             >::type
751         type;
752     };
753 
754     template <>
755     struct build_fusion_vector<unused_type>
756     {
757         typedef unused_type type;
758     };
759 
760     ///////////////////////////////////////////////////////////////////////////
761     // build_attribute_sequence
762     //
763     // Build a fusion sequence attribute sequence from a sequence of
764     // components. Transform<T>::type is called on each element.
765     ///////////////////////////////////////////////////////////////////////////
766     template <typename Sequence, typename Context
767       , template <typename T, typename D> class Transform
768       , typename Iterator = unused_type, typename Domain = unused_type>
769     struct build_attribute_sequence
770     {
771         struct element_attribute
772         {
773             template <typename T>
774             struct result;
775 
776             template <typename F, typename Element>
777             struct result<F(Element)>
778             {
779                 typedef typename
780                     Transform<
781                         typename attribute_of<Element, Context, Iterator>::type
782                       , Domain
783                     >::type
784                 type;
785             };
786 
787             // never called, but needed for decltype-based result_of (C++0x)
788 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
789             template <typename Element>
790             typename result<element_attribute(Element)>::type
791             operator()(Element&&) const;
792 #endif
793         };
794 
795         // Compute the list of attributes of all sub-components
796         typedef typename
797             fusion::result_of::transform<Sequence, element_attribute>::type
798         type;
799     };
800 
801     ///////////////////////////////////////////////////////////////////////////
802     // has_no_unused
803     //
804     // Test if there are no unused attributes in Sequence
805     ///////////////////////////////////////////////////////////////////////////
806     template <typename Sequence>
807     struct has_no_unused
808       : is_same<
809             typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type
810           , typename mpl::end<Sequence>::type>
811     {};
812 
813     namespace detail
814     {
815         template <typename Sequence, bool no_unused
816             , int size = mpl::size<Sequence>::value>
817         struct build_collapsed_variant;
818 
819         // N element case, no unused
820         template <typename Sequence, int size>
821         struct build_collapsed_variant<Sequence, true, size>
822             : spirit::detail::as_variant<Sequence> {};
823 
824         // N element case with unused
825         template <typename Sequence, int size>
826         struct build_collapsed_variant<Sequence, false, size>
827         {
828             typedef boost::optional<
829                 typename spirit::detail::as_variant<
830                     typename fusion::result_of::pop_front<Sequence>::type
831                 >::type
832             > type;
833         };
834 
835         // 1 element case, no unused
836         template <typename Sequence>
837         struct build_collapsed_variant<Sequence, true, 1>
838             : mpl::front<Sequence> {};
839 
840         // 1 element case, with unused
841         template <typename Sequence>
842         struct build_collapsed_variant<Sequence, false, 1>
843             : mpl::front<Sequence> {};
844 
845         // 2 element case, no unused
846         template <typename Sequence>
847         struct build_collapsed_variant<Sequence, true, 2>
848             : spirit::detail::as_variant<Sequence> {};
849 
850         // 2 element case, with unused
851         template <typename Sequence>
852         struct build_collapsed_variant<Sequence, false, 2>
853         {
854             typedef boost::optional<
855                 typename mpl::deref<
856                     typename mpl::next<
857                         typename mpl::begin<Sequence>::type
858                     >::type
859                 >::type
860             >
861             type;
862         };
863     }
864 
865     ///////////////////////////////////////////////////////////////////////////
866     // alternative_attribute_transform
867     //
868     // This transform is invoked for every attribute in an alternative allowing
869     // to modify the attribute type exposed by a component to the enclosing
870     // alternative component. By default no transformation is performed.
871     ///////////////////////////////////////////////////////////////////////////
872     template <typename Attribute, typename Domain>
873     struct alternative_attribute_transform
874       : mpl::identity<Attribute>
875     {};
876 
877     ///////////////////////////////////////////////////////////////////////////
878     // build_variant
879     //
880     // Build a boost::variant from a fusion sequence. build_variant makes sure
881     // that 1) all attributes in the variant are unique 2) puts the unused
882     // attribute, if there is any, to the front and 3) collapses single element
883     // variants, variant<T> to T.
884     ///////////////////////////////////////////////////////////////////////////
885     template <typename Sequence>
886     struct build_variant
887     {
888         // Remove all unused attributes.
889         typedef typename
890             filter_unused_attributes<Sequence>::type
891         filtered_attributes;
892 
893         typedef has_no_unused<Sequence> no_unused;
894 
895         // If the original attribute list does not contain any unused
896         // attributes, it is used, otherwise a single unused_type is
897         // pushed to the front of the list. This is to make sure that if
898         // there is an unused_type in the list, it is the first one.
899         typedef typename
900             mpl::eval_if<
901                 no_unused,
902                 mpl::identity<Sequence>,
903                 fusion::result_of::push_front<filtered_attributes, unused_type>
904             >::type
905         attribute_sequence;
906 
907         // Make sure each of the types occur only once in the type list
908         typedef typename
909             mpl::fold<
910                 attribute_sequence, mpl::vector<>,
911                 mpl::if_<
912                     mpl::contains<mpl::_1, mpl::_2>,
913                     mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
914                 >
915             >::type
916         no_duplicates;
917 
918         // If there is only one type in the list of types we strip off the
919         // variant. IOTW, collapse single element variants, variant<T> to T.
920         // Take note that this also collapses variant<unused_type, T> to T.
921         typedef typename
922             traits::detail::build_collapsed_variant<
923                 no_duplicates, no_unused::value>::type
924         type;
925     };
926 
927     ///////////////////////////////////////////////////////////////////////////
928     //  transform_attribute
929     //
930     //  Sometimes the user needs to transform the attribute types for certain
931     //  attributes. This template can be used as a customization point, where
932     //  the user is able specify specific transformation rules for any attribute
933     //  type.
934     ///////////////////////////////////////////////////////////////////////////
935     template <typename Exposed, typename Transformed, typename Domain
936       , typename Enable/* = void*/>
937     struct transform_attribute;
938 
939     ///////////////////////////////////////////////////////////////////////////
940     template <typename Domain, typename Transformed, typename Exposed>
941     typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type
pre_transform(Exposed & attr BOOST_PROTO_DISABLE_IF_IS_CONST (Exposed))942     pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed))
943     {
944         return transform_attribute<Exposed, Transformed, Domain>::pre(attr);
945     }
946 
947     template <typename Domain, typename Transformed, typename Exposed>
948     typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type
pre_transform(Exposed const & attr)949     pre_transform(Exposed const& attr)
950     {
951         return transform_attribute<Exposed const, Transformed, Domain>::pre(attr);
952     }
953 
954     ///////////////////////////////////////////////////////////////////////////
955     // make_attribute
956     //
957     // All parsers and generators have specific attribute types.
958     // Spirit parsers and generators are passed an attribute; these are either
959     // references to the expected type, or an unused_type -- to flag that we do
960     // not care about the attribute. For semantic actions, however, we need to
961     // have a real value to pass to the semantic action. If the client did not
962     // provide one, we will have to synthesize the value. This class takes care
963     // of that. *Note that this behavior has changed. From Boost 1.47, semantic
964     // actions always take in the passed attribute as-is if the PP constant:
965     // BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is defined.
966     ///////////////////////////////////////////////////////////////////////////
967     template <typename Attribute, typename ActualAttribute>
968     struct make_attribute
969     {
970         typedef typename remove_const<Attribute>::type attribute_type;
971         typedef typename
972             mpl::if_<
973                 is_same<typename remove_const<ActualAttribute>::type, unused_type>
974               , attribute_type
975               , ActualAttribute&>::type
976         type;
977 
978         typedef typename
979             mpl::if_<
980                 is_same<typename remove_const<ActualAttribute>::type, unused_type>
981               , attribute_type
982               , ActualAttribute>::type
983         value_type;
984 
callboost::spirit::traits::make_attribute985         static Attribute call(unused_type)
986         {
987              // synthesize the attribute/parameter
988             return boost::get(value_initialized<attribute_type>());
989         }
990 
991         template <typename T>
callboost::spirit::traits::make_attribute992         static T& call(T& value)
993         {
994             return value; // just pass the one provided
995         }
996     };
997 
998     template <typename Attribute, typename ActualAttribute>
999     struct make_attribute<Attribute&, ActualAttribute>
1000       : make_attribute<Attribute, ActualAttribute>
1001     {};
1002 
1003     template <typename Attribute, typename ActualAttribute>
1004     struct make_attribute<Attribute const&, ActualAttribute>
1005       : make_attribute<Attribute const, ActualAttribute>
1006     {};
1007 
1008     template <typename ActualAttribute>
1009     struct make_attribute<unused_type, ActualAttribute>
1010     {
1011         typedef unused_type type;
1012         typedef unused_type value_type;
callboost::spirit::traits::make_attribute1013         static unused_type call(unused_type)
1014         {
1015             return unused;
1016         }
1017     };
1018 
1019     ///////////////////////////////////////////////////////////////////////////
1020     // swap_impl
1021     //
1022     // Swap (with proper handling of unused_types)
1023     ///////////////////////////////////////////////////////////////////////////
1024     template <typename A, typename B>
swap_impl(A & a,B & b)1025     void swap_impl(A& a, B& b)
1026     {
1027         A temp = a;
1028         a = b;
1029         b = temp;
1030     }
1031 
1032     template <typename T>
swap_impl(T & a,T & b)1033     void swap_impl(T& a, T& b)
1034     {
1035         using namespace std;
1036         swap(a, b);
1037     }
1038 
1039     template <typename A>
swap_impl(A &,unused_type)1040     void swap_impl(A&, unused_type)
1041     {
1042     }
1043 
1044     template <typename A>
swap_impl(unused_type,A &)1045     void swap_impl(unused_type, A&)
1046     {
1047     }
1048 
swap_impl(unused_type,unused_type)1049     inline void swap_impl(unused_type, unused_type)
1050     {
1051     }
1052 
1053     ///////////////////////////////////////////////////////////////////////////
1054     //  Strips single element fusion vectors into its 'naked'
1055     //  form: vector<T> --> T
1056     ///////////////////////////////////////////////////////////////////////////
1057     template <typename T>
1058     struct strip_single_element_vector
1059     {
1060         typedef T type;
1061     };
1062 
1063     template <typename T>
1064     struct strip_single_element_vector<fusion::vector1<T> >
1065     {
1066         typedef T type;
1067     };
1068 
1069     template <typename T>
1070     struct strip_single_element_vector<fusion::vector<T> >
1071     {
1072         typedef T type;
1073     };
1074 
1075     ///////////////////////////////////////////////////////////////////////////
1076     // meta function to return whether the argument is a one element fusion
1077     // sequence
1078     ///////////////////////////////////////////////////////////////////////////
1079     template <typename T
1080       , bool IsFusionSeq = fusion::traits::is_sequence<T>::value
1081       , bool IsProtoExpr = proto::is_expr<T>::value>
1082     struct one_element_sequence
1083       : mpl::false_
1084     {};
1085 
1086     template <typename T>
1087     struct one_element_sequence<T, true, false>
1088       : mpl::bool_<mpl::size<T>::value == 1>
1089     {};
1090 
1091     ///////////////////////////////////////////////////////////////////////////
1092     // clear
1093     //
1094     // Clear data efficiently
1095     ///////////////////////////////////////////////////////////////////////////
1096     template <typename T>
1097     void clear(T& val);
1098 
1099     namespace detail
1100     {
1101         // this is used by the variant and fusion sequence dispatch
1102         struct clear_visitor : static_visitor<>
1103         {
1104             template <typename T>
operator ()boost::spirit::traits::detail::clear_visitor1105             void operator()(T& val) const
1106             {
1107                 spirit::traits::clear(val);
1108             }
1109         };
1110 
1111         // default
1112         template <typename T>
clear_impl2(T & val,mpl::false_)1113         void clear_impl2(T& val, mpl::false_)
1114         {
1115             val = T();
1116         }
1117 
1118         // for fusion sequences
1119         template <typename T>
clear_impl2(T & val,mpl::true_)1120         void clear_impl2(T& val, mpl::true_)
1121         {
1122             fusion::for_each(val, clear_visitor());
1123         }
1124 
1125         // dispatch default or fusion sequence
1126         template <typename T>
clear_impl(T & val,mpl::false_)1127         void clear_impl(T& val, mpl::false_)
1128         {
1129             clear_impl2(val, fusion::traits::is_sequence<T>());
1130         }
1131 
1132         // STL containers
1133         template <typename T>
clear_impl(T & val,mpl::true_)1134         void clear_impl(T& val, mpl::true_)
1135         {
1136             val.clear();
1137         }
1138     }
1139 
1140     template <typename T, typename Enable/* = void*/>
1141     struct clear_value
1142     {
callboost::spirit::traits::clear_value1143         static void call(T& val)
1144         {
1145             detail::clear_impl(val, typename is_container<T>::type());
1146         }
1147     };
1148 
1149     // optionals
1150     template <typename T>
1151     struct clear_value<boost::optional<T> >
1152     {
callboost::spirit::traits::clear_value1153         static void call(boost::optional<T>& val)
1154         {
1155             if (val)
1156                 val = none_t();   // leave optional uninitialized
1157         }
1158     };
1159 
1160     // variants
1161     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
1162     struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
1163     {
callboost::spirit::traits::clear_value1164         static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val)
1165         {
1166             apply_visitor(detail::clear_visitor(), val);
1167         }
1168     };
1169 
1170     // iterator range
1171     template <typename T>
1172     struct clear_value<iterator_range<T> >
1173     {
callboost::spirit::traits::clear_value1174         static void call(iterator_range<T>& val)
1175         {
1176             val = iterator_range<T>(val.end(), val.end());
1177         }
1178     };
1179 
1180     // main dispatch
1181     template <typename T>
clear(T & val)1182     void clear(T& val)
1183     {
1184         clear_value<T>::call(val);
1185     }
1186 
1187     // for unused
clear(unused_type)1188     inline void clear(unused_type)
1189     {
1190     }
1191 
1192     ///////////////////////////////////////////////////////////////////////////
1193     namespace detail
1194     {
1195         template <typename Out>
1196         struct print_fusion_sequence
1197         {
print_fusion_sequenceboost::spirit::traits::detail::print_fusion_sequence1198             print_fusion_sequence(Out& out_)
1199               : out(out_), is_first(true) {}
1200 
1201             typedef void result_type;
1202 
1203             template <typename T>
operator ()boost::spirit::traits::detail::print_fusion_sequence1204             void operator()(T const& val) const
1205             {
1206                 if (is_first)
1207                     is_first = false;
1208                 else
1209                     out << ", ";
1210                 spirit::traits::print_attribute(out, val);
1211             }
1212 
1213             Out& out;
1214             mutable bool is_first;
1215         };
1216 
1217         // print elements in a variant
1218         template <typename Out>
1219         struct print_visitor : static_visitor<>
1220         {
print_visitorboost::spirit::traits::detail::print_visitor1221             print_visitor(Out& out_) : out(out_) {}
1222 
1223             template <typename T>
operator ()boost::spirit::traits::detail::print_visitor1224             void operator()(T const& val) const
1225             {
1226                 spirit::traits::print_attribute(out, val);
1227             }
1228 
1229             Out& out;
1230         };
1231     }
1232 
1233     template <typename Out, typename T, typename Enable>
1234     struct print_attribute_debug
1235     {
1236         // for plain data types
1237         template <typename T_>
call_impl3boost::spirit::traits::print_attribute_debug1238         static void call_impl3(Out& out, T_ const& val, mpl::false_)
1239         {
1240             out << val;
1241         }
1242 
1243         // for fusion data types
1244         template <typename T_>
call_impl3boost::spirit::traits::print_attribute_debug1245         static void call_impl3(Out& out, T_ const& val, mpl::true_)
1246         {
1247             out << '[';
1248             fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
1249             out << ']';
1250         }
1251 
1252         // non-stl container
1253         template <typename T_>
call_impl2boost::spirit::traits::print_attribute_debug1254         static void call_impl2(Out& out, T_ const& val, mpl::false_)
1255         {
1256             call_impl3(out, val, fusion::traits::is_sequence<T_>());
1257         }
1258 
1259         // stl container
1260         template <typename T_>
call_impl2boost::spirit::traits::print_attribute_debug1261         static void call_impl2(Out& out, T_ const& val, mpl::true_)
1262         {
1263             out << '[';
1264             if (!traits::is_empty(val))
1265             {
1266                 bool first = true;
1267                 typename container_iterator<T_ const>::type iend = traits::end(val);
1268                 for (typename container_iterator<T_ const>::type i = traits::begin(val);
1269                      !traits::compare(i, iend); traits::next(i))
1270                 {
1271                     if (!first)
1272                         out << ", ";
1273                     first = false;
1274                     spirit::traits::print_attribute(out, traits::deref(i));
1275                 }
1276             }
1277             out << ']';
1278         }
1279 
1280         // for variant types
1281         template <typename T_>
call_implboost::spirit::traits::print_attribute_debug1282         static void call_impl(Out& out, T_ const& val, mpl::false_)
1283         {
1284             apply_visitor(detail::print_visitor<Out>(out), val);
1285         }
1286 
1287         // for non-variant types
1288         template <typename T_>
call_implboost::spirit::traits::print_attribute_debug1289         static void call_impl(Out& out, T_ const& val, mpl::true_)
1290         {
1291             call_impl2(out, val, is_container<T_>());
1292         }
1293 
1294         // main entry point
callboost::spirit::traits::print_attribute_debug1295         static void call(Out& out, T const& val)
1296         {
1297             call_impl(out, val, not_is_variant<T>());
1298         }
1299     };
1300 
1301     template <typename Out, typename T>
1302     struct print_attribute_debug<Out, boost::optional<T> >
1303     {
callboost::spirit::traits::print_attribute_debug1304         static void call(Out& out, boost::optional<T> const& val)
1305         {
1306             if (val)
1307                 spirit::traits::print_attribute(out, *val);
1308             else
1309                 out << "[empty]";
1310         }
1311     };
1312 
1313     ///////////////////////////////////////////////////////////////////////////
1314     template <typename Out, typename T>
print_attribute(Out & out,T const & val)1315     inline void print_attribute(Out& out, T const& val)
1316     {
1317         print_attribute_debug<Out, T>::call(out, val);
1318     }
1319 
1320     template <typename Out>
print_attribute(Out &,unused_type)1321     inline void print_attribute(Out&, unused_type)
1322     {
1323     }
1324 
1325     ///////////////////////////////////////////////////////////////////////////
1326     // generate debug output for lookahead token (character) stream
1327     namespace detail
1328     {
1329         struct token_printer_debug_for_chars
1330         {
1331             template<typename Out, typename Char>
printboost::spirit::traits::detail::token_printer_debug_for_chars1332             static void print(Out& o, Char c)
1333             {
1334                 using namespace std;    // allow for ADL to find the proper iscntrl
1335 
1336                 if (c == static_cast<Char>('\a'))
1337                     o << "\\a";
1338                 else if (c == static_cast<Char>('\b'))
1339                     o << "\\b";
1340                 else if (c == static_cast<Char>('\f'))
1341                     o << "\\f";
1342                 else if (c == static_cast<Char>('\n'))
1343                     o << "\\n";
1344                 else if (c == static_cast<Char>('\r'))
1345                     o << "\\r";
1346                 else if (c == static_cast<Char>('\t'))
1347                     o << "\\t";
1348                 else if (c == static_cast<Char>('\v'))
1349                     o << "\\v";
1350                 else if (c >= 0 && c < 127 && iscntrl(c))
1351                     o << "\\" << std::oct << static_cast<int>(c);
1352                 else
1353                     o << static_cast<char>(c);
1354             }
1355         };
1356 
1357         // for token types where the comparison with char constants wouldn't work
1358         struct token_printer_debug
1359         {
1360             template<typename Out, typename T>
printboost::spirit::traits::detail::token_printer_debug1361             static void print(Out& o, T const& val)
1362             {
1363                 o << val;
1364             }
1365         };
1366     }
1367 
1368     template <typename T, typename Enable>
1369     struct token_printer_debug
1370       : mpl::if_<
1371             mpl::and_<
1372                 is_convertible<T, char>, is_convertible<char, T> >
1373           , detail::token_printer_debug_for_chars
1374           , detail::token_printer_debug>::type
1375     {};
1376 
1377     template <typename Out, typename T>
print_token(Out & out,T const & val)1378     inline void print_token(Out& out, T const& val)
1379     {
1380         // allow to customize the token printer routine
1381         token_printer_debug<T>::print(out, val);
1382     }
1383 }}}
1384 
1385 ///////////////////////////////////////////////////////////////////////////////
1386 namespace boost { namespace spirit { namespace result_of
1387 {
1388     template <typename Exposed, typename Transformed, typename Domain>
1389     struct pre_transform
1390       : traits::transform_attribute<Exposed, Transformed, Domain>
1391     {};
1392 }}}
1393 
1394 
1395 #endif
1396