Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:53

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2001-2011 Hartmut Kaiser
0004     Copyright (c) 2010-2011 Bryce Lelbach
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #if !defined(BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM)
0010 #define BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM
0011 
0012 #include <boost/spirit/home/support/attributes.hpp>
0013 #include <boost/spirit/home/support/container.hpp>
0014 #include <boost/spirit/home/support/utree.hpp>
0015 #include <boost/spirit/home/qi/domain.hpp>
0016 #include <boost/spirit/home/karma/domain.hpp>
0017 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
0018 #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp>
0019 
0020 #include <string>
0021 
0022 #include <boost/cstdint.hpp>
0023 #include <boost/variant.hpp>
0024 #include <boost/mpl/bool.hpp>
0025 #include <boost/mpl/identity.hpp>
0026 #include <boost/mpl/or.hpp>
0027 #include <boost/range/iterator_range_core.hpp>
0028 #include <boost/type_traits/is_same.hpp>
0029 #include <boost/utility/enable_if.hpp>
0030 
0031 ///////////////////////////////////////////////////////////////////////////////
0032 namespace boost
0033 {
0034     template <typename T>
0035     inline T get(boost::spirit::utree const& x)
0036     {
0037         return x.get<T>();
0038     }
0039 }
0040 
0041 ///////////////////////////////////////////////////////////////////////////////
0042 namespace boost { namespace spirit { namespace traits
0043 {
0044     namespace detail
0045     {
0046         inline bool is_list(utree const& ut)
0047         {
0048             switch (traits::which(ut))
0049             {
0050             case utree_type::reference_type:
0051                 return is_list(ut.deref());
0052 
0053             case utree_type::list_type:
0054             case utree_type::range_type:
0055                 return true;
0056 
0057             default:
0058                 break;
0059             }
0060             return false;
0061         }
0062 
0063         inline bool is_uninitialized(utree const& ut)
0064         {
0065             return traits::which(ut) == utree_type::invalid_type;
0066         }
0067     }
0068 
0069     // this specialization tells Spirit how to extract the type of the value
0070     // stored in the given utree node
0071     template <>
0072     struct variant_which<utree>
0073     {
0074         static int call(utree const& u) { return u.which(); }
0075     };
0076     
0077     template <>
0078     struct variant_which<utree::list_type>
0079     {
0080         static int call(utree::list_type const& u) { return u.which(); }
0081     };
0082 
0083     ///////////////////////////////////////////////////////////////////////////
0084     // Make sure all components of an alternative expose utree, even if they
0085     // actually expose a utree::list_type
0086     template <typename Domain> 
0087     struct alternative_attribute_transform<utree::list_type, Domain>
0088       : mpl::identity<utree>
0089     {};
0090 
0091     ///////////////////////////////////////////////////////////////////////////
0092     // Make sure all components of a sequence expose utree, even if they
0093     // actually expose a utree::list_type
0094     template <typename Domain> 
0095     struct sequence_attribute_transform<utree::list_type, Domain>
0096       : mpl::identity<utree>
0097     {};
0098 
0099     ///////////////////////////////////////////////////////////////////////////
0100     // this specialization lets Spirit know that typed basic_strings
0101     // are strings
0102     template <typename Base, utree_type::info I>
0103     struct is_string<spirit::basic_string<Base, I> > 
0104       : mpl::true_ 
0105     {};
0106 
0107     ///////////////////////////////////////////////////////////////////////////
0108     // these specializations extract the character type of a utree typed string 
0109     template <typename T, utree_type::info I>
0110     struct char_type_of<spirit::basic_string<iterator_range<T>, I> >
0111       : char_type_of<T> 
0112     {};
0113 
0114     template <utree_type::info I>
0115     struct char_type_of<spirit::basic_string<std::string, I> > 
0116       : mpl::identity<char>
0117     {};
0118 
0119     ///////////////////////////////////////////////////////////////////////////
0120     // these specializations extract a c string from a utree typed string
0121     template <typename String>
0122     struct extract_c_string;
0123 
0124     template <typename T, utree_type::info I>
0125     struct extract_c_string<
0126         spirit::basic_string<iterator_range<T const*>, I>
0127     > {
0128         typedef T char_type;
0129 
0130         typedef spirit::basic_string<iterator_range<T const*>, I> string;
0131 
0132         static T const* call (string& s)
0133         {
0134             return s.begin();
0135         }
0136 
0137         static T const* call (string const& s)
0138         {
0139             return s.begin();
0140         }
0141     };
0142     
0143     template <utree_type::info I>
0144     struct extract_c_string<spirit::basic_string<std::string, I> >
0145     {
0146         typedef char char_type;
0147 
0148         typedef spirit::basic_string<std::string, I> string;
0149 
0150         static char const* call (string& s)
0151         {
0152             return s.c_str();
0153         }
0154 
0155         static char const* call (string const& s)
0156         {
0157             return s.c_str();
0158         }
0159     };
0160 
0161     ///////////////////////////////////////////////////////////////////////////
0162     // these specializations are needed because utree::value_type == utree
0163     template <> 
0164     struct is_substitute<utree, utree> 
0165       : mpl::true_ 
0166     {};
0167 
0168     template <> 
0169     struct is_weak_substitute<utree, utree> 
0170       : mpl::true_ 
0171     {};
0172 
0173     template <> 
0174     struct is_substitute<utree::list_type, utree::list_type> 
0175       : mpl::true_ 
0176     {};
0177 
0178     template <> 
0179     struct is_weak_substitute<utree::list_type, utree::list_type> 
0180       : mpl::true_ 
0181     {};
0182 
0183     ///////////////////////////////////////////////////////////////////////////
0184     // this specialization tells Spirit.Qi to allow assignment to an utree from
0185     // a variant
0186     namespace detail
0187     {
0188         struct assign_to_utree_visitor : static_visitor<>
0189         {
0190             assign_to_utree_visitor(utree& ut) : ut_(ut) {}
0191 
0192             template <typename T>
0193             void operator()(T& val) const
0194             {
0195                 ut_ = val;
0196             }
0197 
0198             utree& ut_;
0199         };
0200     }
0201 
0202     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0203     struct assign_to_container_from_value<
0204         utree, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0205     {
0206         static void
0207         call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val, utree& attr)
0208         {
0209             apply_visitor(detail::assign_to_utree_visitor(attr), val);
0210         }
0211     };
0212 
0213     ///////////////////////////////////////////////////////////////////////////
0214     // this specialization tells Spirit.Qi to allow assignment to an utree from
0215     // a STL container
0216     template <typename Attribute>
0217     struct assign_to_container_from_value<utree, Attribute>
0218     {
0219         // any non-container type will be either directly assigned or appended
0220         static void call(Attribute const& val, utree& attr, mpl::false_)
0221         {
0222             if (attr.empty())
0223                 attr = val;
0224             else
0225                 push_back(attr, val);
0226         }
0227 
0228         // any container type will be converted into a list_type utree
0229         static void call(Attribute const& val, utree& attr, mpl::true_)
0230         {
0231             typedef typename traits::container_iterator<Attribute const>::type 
0232                 iterator_type;
0233 
0234             // make sure the attribute is a list, at least an empty one
0235             if (attr.empty())
0236                 attr = empty_list;
0237 
0238             iterator_type end = traits::end(val);
0239             for (iterator_type i = traits::begin(val); i != end; traits::next(i))
0240                 push_back(attr, traits::deref(i));
0241         }
0242 
0243         static void call(Attribute const& val, utree& attr)
0244         {
0245             call(val, attr, is_container<Attribute>());
0246         }
0247     };
0248 
0249     ///////////////////////////////////////////////////////////////////////////
0250     // this specialization is required to disambiguate the specializations
0251     // related to utree
0252     template <>
0253     struct assign_to_container_from_value<utree, utree>
0254     {
0255         static void call(utree const& val, utree& attr)
0256         {
0257             if (attr.empty()) {
0258                 attr = val;
0259             }
0260             else if (detail::is_list(val)) {
0261                 typedef utree::const_iterator iterator_type;
0262 
0263                 iterator_type end = traits::end(val);
0264                 for (iterator_type i = traits::begin(val); i != end; traits::next(i))
0265                     push_back(attr, traits::deref(i));
0266             }
0267             else {
0268                 push_back(attr, val);
0269             }
0270         }
0271     };
0272 
0273     template <>
0274     struct assign_to_container_from_value<utree, utree::list_type>
0275       : assign_to_container_from_value<utree, utree>
0276     {};
0277 
0278     // If the destination is a utree_list, we need to force the right hand side
0279     // value into a new sub-node, always, no questions asked.
0280     template <>
0281     struct assign_to_container_from_value<utree::list_type, utree>
0282     {
0283         static void call(utree const& val, utree& attr)
0284         {
0285             push_back(attr, val);
0286         }
0287     };
0288 
0289     // If both, the right hand side and the left hand side are utree_lists
0290     // we have a lhs rule which has a single rule exposing a utree_list as its
0291     // rhs (optionally wrapped into a directive or other unary parser). In this
0292     // case we do not create a new sub-node.
0293     template <>
0294     struct assign_to_container_from_value<utree::list_type, utree::list_type>
0295       : assign_to_container_from_value<utree, utree>
0296     {};
0297 
0298     ///////////////////////////////////////////////////////////////////////////
0299     // this specialization makes sure strings get assigned as a whole and are 
0300     // not converted into a utree list
0301     template <>
0302     struct assign_to_container_from_value<utree, utf8_string_type>
0303     {
0304         static void call(utf8_string_type const& val, utree& attr)
0305         {
0306             if (attr.empty())
0307                 attr = val;
0308             else
0309                 push_back(attr, val);
0310         }
0311     };
0312 
0313     // this specialization keeps symbols from being transformed into strings  
0314     template<>
0315     struct assign_to_container_from_value<utree, utf8_symbol_type> 
0316     {
0317         static void call (utf8_symbol_type const& val, utree& attr) 
0318         {
0319             if (attr.empty())
0320                 attr = val;
0321             else
0322                 push_back(attr, val);
0323         }
0324     };
0325     
0326     template <>
0327     struct assign_to_container_from_value<utree, binary_string_type>
0328     {
0329         static void call(binary_string_type const& val, utree& attr)
0330         {
0331             if (attr.empty())
0332                 attr = val;
0333             else
0334                 push_back(attr, val);
0335         }
0336     };
0337 
0338     template<>
0339     struct assign_to_container_from_value<utree, utf8_symbol_range_type> 
0340     {
0341         static void call (utf8_symbol_range_type const& val, utree& attr) 
0342         {
0343             if (attr.empty())
0344                 attr = val;
0345             else
0346                 push_back(attr, val);
0347         }
0348     };
0349     
0350     template <>
0351     struct assign_to_container_from_value<utree, binary_range_type>
0352     {
0353         static void call(binary_range_type const& val, utree& attr)
0354         {
0355             if (attr.empty())
0356                 attr = val;
0357             else
0358                 push_back(attr, val);
0359         }
0360     };
0361 
0362     template <>
0363     struct assign_to_container_from_value<utree, std::string>
0364     {
0365         static void call(std::string const& val, utree& attr)
0366         {
0367             if (attr.empty())
0368                 attr = val;
0369             else
0370                 push_back(attr, val);
0371         }
0372     };
0373 
0374     ///////////////////////////////////////////////////////////////////////////
0375     // this specialization tells Spirit.Qi to allow assignment to an utree from
0376     // generic iterators
0377     template <typename Iterator>
0378     struct assign_to_attribute_from_iterators<utree, Iterator>
0379     {
0380         static void
0381         call(Iterator const& first, Iterator const& last, utree& attr)
0382         {
0383             if (attr.empty())
0384                 attr.assign(first, last);
0385             else {
0386                 for (Iterator i = first; i != last; ++i)
0387                     push_back(attr, traits::deref(i));
0388             }
0389         }
0390     };
0391 
0392     ///////////////////////////////////////////////////////////////////////////
0393     // Karma only: convert utree node to string
0394     namespace detail
0395     {
0396         struct attribute_as_string_type
0397         {
0398             typedef utf8_string_range_type type; 
0399 
0400             static type call(utree const& attr)
0401             {
0402                 return boost::get<utf8_string_range_type>(attr);
0403             }
0404 
0405             static bool is_valid(utree const& attr)
0406             {
0407                 switch (traits::which(attr))
0408                 {
0409                 case utree_type::reference_type:
0410                     return is_valid(attr.deref());
0411 
0412                 case utree_type::string_range_type:
0413                 case utree_type::string_type:
0414                     return true;
0415 
0416                 default:
0417                     return false;
0418                 }
0419             }
0420         };
0421     }
0422 
0423     template <>
0424     struct attribute_as<std::string, utree>
0425       : detail::attribute_as_string_type 
0426     {};
0427 
0428     template <>
0429     struct attribute_as<utf8_string_type, utree>
0430       : detail::attribute_as_string_type 
0431     {};
0432 
0433     template <>
0434     struct attribute_as<utf8_string_range_type, utree>
0435       : detail::attribute_as_string_type 
0436     {};
0437 
0438     ///////////////////////////////////////////////////////////////////////////
0439     namespace detail
0440     {
0441         struct attribute_as_symbol_type
0442         {
0443             typedef utf8_symbol_range_type type; 
0444 
0445             static type call(utree const& attr)
0446             {
0447                 return boost::get<utf8_symbol_range_type>(attr);
0448             }
0449 
0450             static bool is_valid(utree const& attr)
0451             {
0452                 switch (traits::which(attr))
0453                 {
0454                 case utree_type::reference_type:
0455                     return is_valid(attr.deref());
0456 
0457                 case utree_type::symbol_type:
0458                     return true;
0459 
0460                 default:
0461                     return false;
0462                 }
0463             }
0464         };
0465     }
0466 
0467     template <>
0468     struct attribute_as<utf8_symbol_type, utree>
0469       : detail::attribute_as_symbol_type 
0470     {};
0471 
0472     template <>
0473     struct attribute_as<utf8_symbol_range_type, utree>
0474       : detail::attribute_as_symbol_type 
0475     {};
0476     
0477     template <typename Attribute>
0478     struct attribute_as<Attribute, utree::list_type>
0479       : attribute_as<Attribute, utree>
0480     {};
0481 
0482     ///////////////////////////////////////////////////////////////////////////
0483     namespace detail
0484     {
0485         struct attribute_as_binary_string_type
0486         {
0487             typedef binary_range_type type; 
0488 
0489             static type call(utree const& attr)
0490             {
0491                 return boost::get<binary_range_type>(attr);
0492             }
0493 
0494             static bool is_valid(utree const& attr)
0495             {
0496                 switch (traits::which(attr))
0497                 {
0498                 case utree_type::reference_type:
0499                     return is_valid(attr.deref());
0500 
0501                 case utree_type::binary_type:
0502                     return true;
0503 
0504                 default:
0505                     return false;
0506                 }
0507             }
0508         };
0509     }
0510 
0511     template <>
0512     struct attribute_as<binary_string_type, utree>
0513       : detail::attribute_as_binary_string_type 
0514     {};
0515 
0516     template <>
0517     struct attribute_as<binary_range_type, utree>
0518       : detail::attribute_as_binary_string_type 
0519     {};
0520 
0521     ///////////////////////////////////////////////////////////////////////////
0522     // push_back support for utree 
0523     template <typename T>
0524     struct push_back_container<utree, T>
0525     {
0526         static bool call(utree& c, T const& val)
0527         {
0528             switch (traits::which(c))
0529             {
0530                 case utree_type::invalid_type:
0531                 case utree_type::nil_type:
0532                 case utree_type::list_type:
0533                     c.push_back(val);
0534                     break;
0535 
0536                 default:
0537                 {
0538                     utree ut;
0539                     ut.push_back(c);
0540                     ut.push_back(val);
0541                     c.swap(ut);
0542                 }
0543                 break;
0544             }
0545             return true;
0546         }
0547     };
0548 
0549     template <typename T>
0550     struct push_back_container<utree::list_type, T>
0551       : push_back_container<utree, T>
0552     {};
0553 
0554     ///////////////////////////////////////////////////////////////////////////
0555     // ensure the utree attribute is an empty list
0556     template <>
0557     struct make_container_attribute<utree>
0558     {
0559         static void call(utree& ut)
0560         {
0561             if (!detail::is_list(ut)) {
0562                 if (detail::is_uninitialized(ut))
0563                     ut = empty_list;
0564                 else {
0565                     utree retval (empty_list);
0566                     retval.push_back(ut);
0567                     ut.swap(retval);
0568                 }
0569             }
0570         }
0571     };
0572 
0573     template <>
0574     struct make_container_attribute<utree::list_type>
0575       : make_container_attribute<utree>
0576     {};
0577 
0578     ///////////////////////////////////////////////////////////////////////////
0579     // an utree is a container on its own
0580     template <>
0581     struct build_std_vector<utree>
0582     {
0583         typedef utree type;
0584     };
0585 
0586     template <>
0587     struct build_std_vector<utree::list_type>
0588     {
0589         typedef utree::list_type type;
0590     };
0591 
0592     ///////////////////////////////////////////////////////////////////////////
0593     // debug support for utree
0594     template <typename Out>
0595     struct print_attribute_debug<Out, utree>
0596     {
0597         static void call(Out& out, utree const& val)
0598         {
0599             out << val;
0600         }
0601     };
0602 
0603     ///////////////////////////////////////////////////////////////////////////
0604     // force utree list attribute in a sequence to be dereferenced if a rule
0605     // or a grammar exposes an utree as it's attribute
0606     namespace detail
0607     {
0608         // Checks whether the exposed Attribute allows to handle utree or 
0609         // utree::list_type directly. Returning mpl::false_ from this meta 
0610         // function will force a new utree instance to be created for each
0611         // invocation of the embedded parser.
0612 
0613         // The purpose of using utree::list_type as an attribute is to force a 
0614         // new sub-node in the result.
0615         template <typename Attribute, typename Enable = void>
0616         struct handles_utree_list_container 
0617           : mpl::and_<
0618                 mpl::not_<is_same<utree::list_type, Attribute> >,
0619                 traits::is_container<Attribute> >
0620         {};
0621 
0622         // The following specializations make sure that the actual handling of
0623         // an utree (or utree::list_type) attribute is deferred to the embedded
0624         // parsers of a sequence, alternative or optional component.
0625         template <typename Attribute>
0626         struct handles_utree_list_container<Attribute
0627               , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
0628           : mpl::true_
0629         {};
0630 
0631         template <typename Attribute>
0632         struct handles_utree_list_container<boost::optional<Attribute> >
0633           : mpl::true_
0634         {};
0635 
0636         template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0637         struct handles_utree_list_container<
0638                 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0639           : mpl::true_
0640         {};
0641     }
0642 
0643     template <
0644         typename IteratorA, typename IteratorB, typename Context
0645       , typename T1, typename T2, typename T3, typename T4>
0646     struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4>
0647           , utree, Context, IteratorB>
0648       : detail::handles_utree_list_container<typename attribute_of<
0649             qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0650         >::type>
0651     {};
0652 
0653     template <
0654         typename IteratorA, typename IteratorB, typename Context
0655       , typename T1, typename T2, typename T3, typename T4>
0656     struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4>
0657           , utree, Context, IteratorB>
0658       : detail::handles_utree_list_container<typename attribute_of<
0659             qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0660         >::type>
0661     {};
0662 
0663     template <
0664         typename IteratorA, typename IteratorB, typename Context
0665       , typename T1, typename T2, typename T3, typename T4>
0666     struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4>
0667           , utree::list_type, Context, IteratorB>
0668       : detail::handles_utree_list_container<typename attribute_of<
0669             qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0670         >::type>
0671     {};
0672 
0673     template <
0674         typename IteratorA, typename IteratorB, typename Context
0675       , typename T1, typename T2, typename T3, typename T4>
0676     struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4>
0677           , utree::list_type, Context, IteratorB>
0678       : detail::handles_utree_list_container<typename attribute_of<
0679             qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0680         >::type>
0681     {};
0682 
0683     ///////////////////////////////////////////////////////////////////////////
0684     template <typename Attribute, typename Sequence>
0685     struct pass_through_container<
0686             utree, utree, Attribute, Sequence, qi::domain>
0687       : detail::handles_utree_list_container<Attribute>
0688     {};
0689 
0690     template <typename Attribute, typename Sequence>
0691     struct pass_through_container<
0692             utree::list_type, utree, Attribute, Sequence, qi::domain>
0693       : detail::handles_utree_list_container<Attribute>
0694     {};
0695 
0696     ///////////////////////////////////////////////////////////////////////////
0697     namespace detail
0698     {
0699         // Checks whether the exposed Attribute allows to handle utree or 
0700         // utree::list_type directly. Returning mpl::false_ from this meta 
0701         // function will force a new utree instance to be created for each
0702         // invocation of the embedded parser.
0703 
0704         // The purpose of using utree::list_type as an attribute is to force a 
0705         // new sub-node in the result.
0706         template <typename Attribute, typename Enable = void>
0707         struct handles_utree_container 
0708           : mpl::and_<
0709                 mpl::not_<is_same<utree, Attribute> >,
0710                 traits::is_container<Attribute> >
0711         {};
0712 
0713         // The following specializations make sure that the actual handling of
0714         // an utree (or utree::list_type) attribute is deferred to the embedded
0715         // parsers of a sequence, alternative or optional component.
0716         template <typename Attribute>
0717         struct handles_utree_container<Attribute
0718               , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
0719           : mpl::true_
0720         {};
0721 
0722         template <typename Attribute>
0723         struct handles_utree_container<boost::optional<Attribute> >
0724           : mpl::true_
0725         {};
0726 
0727         template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0728         struct handles_utree_container<
0729                 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0730           : mpl::true_
0731         {};
0732     }
0733 
0734     template <
0735         typename IteratorA, typename IteratorB, typename Context
0736       , typename T1, typename T2, typename T3, typename T4>
0737     struct handles_container<karma::rule<IteratorA, T1, T2, T3, T4>
0738           , utree, Context, IteratorB>
0739       : detail::handles_utree_container<typename attribute_of<
0740             karma::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0741         >::type>
0742     {};
0743 
0744     template <
0745         typename IteratorA, typename IteratorB, typename Context
0746       , typename T1, typename T2, typename T3, typename T4>
0747     struct handles_container<karma::grammar<IteratorA, T1, T2, T3, T4>
0748           , utree, Context, IteratorB>
0749       : detail::handles_utree_container<typename attribute_of<
0750             karma::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0751         >::type>
0752     {};
0753 
0754     ///////////////////////////////////////////////////////////////////////////
0755     template <typename Attribute, typename Sequence>
0756     struct pass_through_container<
0757             utree, utree, Attribute, Sequence, karma::domain>
0758       : detail::handles_utree_container<Attribute>
0759     {};
0760 
0761     ///////////////////////////////////////////////////////////////////////////
0762     // the specialization below tells Spirit how to handle utree if it is used
0763     // with an optional component
0764     template <>
0765     struct optional_attribute<utree>
0766     {
0767         typedef utree const& type;
0768 
0769         static type call(utree const& val)
0770         {
0771             return val;
0772         }
0773 
0774         // only 'invalid_type' utree nodes are not valid
0775         static bool is_valid(utree const& val)
0776         {
0777           return !detail::is_uninitialized(val);
0778         }
0779     };
0780 
0781     template <>
0782     struct build_optional<utree>
0783     {
0784         typedef utree type;
0785     };
0786 
0787     template <>
0788     struct build_optional<utree::list_type>
0789     {
0790         typedef utree::list_type type;
0791     };
0792 
0793     // an utree is an optional (in any domain)
0794     template <>
0795     struct not_is_optional<utree, qi::domain>
0796       : mpl::false_
0797     {};
0798 
0799     template <>
0800     struct not_is_optional<utree::list_type, qi::domain>
0801       : mpl::false_
0802     {};
0803 
0804     template <>
0805     struct not_is_optional<utree, karma::domain>
0806       : mpl::false_
0807     {};
0808 
0809     template <>
0810     struct not_is_optional<utree::list_type, karma::domain>
0811       : mpl::false_
0812     {};
0813 
0814     ///////////////////////////////////////////////////////////////////////////
0815     // the specialization below tells Spirit to handle utree as if it
0816     // where a 'real' variant (in the context of karma)
0817     template <>
0818     struct not_is_variant<utree, karma::domain>
0819       : mpl::false_ 
0820     {};
0821 
0822     template <>
0823     struct not_is_variant<utree::list_type, karma::domain>
0824       : mpl::false_ 
0825     {};
0826 
0827     // The specializations below tell Spirit to verify whether an attribute
0828     // type is compatible with a given variant type
0829     template <>
0830     struct compute_compatible_component_variant<
0831             utree, iterator_range<utree::iterator> >
0832       : mpl::true_
0833     {
0834         typedef iterator_range<utree::iterator> compatible_type;
0835 
0836         static bool is_compatible(int d)
0837         {
0838             return d == utree_type::list_type;
0839         }
0840     };
0841 
0842     template <>
0843     struct compute_compatible_component_variant<
0844             utree, iterator_range<utree::const_iterator> >
0845       : mpl::true_
0846     {
0847         typedef iterator_range<utree::const_iterator> compatible_type;
0848 
0849         static bool is_compatible(int d)
0850         {
0851             return d == utree_type::list_type;
0852         }
0853     };
0854 
0855     template <>
0856     struct compute_compatible_component_variant<utree, utree::invalid_type>
0857       : mpl::true_
0858     {
0859         typedef utree::invalid_type compatible_type;
0860 
0861         static bool is_compatible(int d)
0862         {
0863             return d == utree_type::invalid_type;
0864         }
0865     };
0866 
0867     template <>
0868     struct compute_compatible_component_variant<utree, utree::nil_type>
0869       : mpl::true_
0870     {
0871         typedef utree::nil_type compatible_type;
0872 
0873         static bool is_compatible(int d)
0874         {
0875             return d == utree_type::nil_type;
0876         }
0877     };
0878 
0879     template <>
0880     struct compute_compatible_component_variant<utree, bool>
0881       : mpl::true_
0882     {
0883         typedef bool compatible_type;
0884 
0885         static bool is_compatible(int d)
0886         {
0887             return d == utree_type::bool_type;
0888         }
0889     };
0890 
0891     template <>
0892     struct compute_compatible_component_variant<utree, int>
0893       : mpl::true_
0894     {
0895         typedef int compatible_type;
0896 
0897         static bool is_compatible(int d)
0898         {
0899             return d == utree_type::int_type;
0900         }
0901     };
0902 
0903     template <>
0904     struct compute_compatible_component_variant<utree, double>
0905       : mpl::true_
0906     {
0907         typedef double compatible_type;
0908 
0909         static bool is_compatible(int d)
0910         {
0911             return d == utree_type::double_type;
0912         }
0913     };
0914 
0915     template <>
0916     struct compute_compatible_component_variant<
0917             utree, utf8_string_range_type>
0918       : mpl::true_
0919     {
0920         typedef utf8_string_range_type compatible_type;
0921 
0922         static bool is_compatible(int d)
0923         {
0924             return d == utree_type::string_type;
0925         }
0926     };
0927 
0928     template <>
0929     struct compute_compatible_component_variant<
0930             utree, utf8_string_type>
0931       : mpl::true_
0932     {
0933         typedef utf8_string_type compatible_type;
0934 
0935         static bool is_compatible(int d)
0936         {
0937             return d == utree_type::string_type;
0938         }
0939     };
0940 
0941     template <>
0942     struct compute_compatible_component_variant<
0943             utree, utf8_symbol_range_type>
0944       : mpl::true_
0945     {
0946         typedef utf8_symbol_range_type compatible_type;
0947 
0948         static bool is_compatible(int d)
0949         {
0950             return d == utree_type::symbol_type;
0951         }
0952     };
0953 
0954     template <>
0955     struct compute_compatible_component_variant<
0956             utree, utf8_symbol_type>
0957       : mpl::true_
0958     {
0959         typedef utf8_symbol_type compatible_type;
0960 
0961         static bool is_compatible(int d)
0962         {
0963             return d == utree_type::symbol_type;
0964         }
0965     };
0966 
0967     template <>
0968     struct compute_compatible_component_variant<
0969             utree, binary_range_type>
0970       : mpl::true_
0971     {
0972         typedef binary_range_type compatible_type;
0973 
0974         static bool is_compatible(int d)
0975         {
0976             return d == utree_type::binary_type;
0977         }
0978     };
0979 
0980     template <>
0981     struct compute_compatible_component_variant<
0982             utree, binary_string_type>
0983       : mpl::true_
0984     {
0985         typedef binary_string_type compatible_type;
0986 
0987         static bool is_compatible(int d)
0988         {
0989             return d == utree_type::binary_type;
0990         }
0991     };
0992 
0993     template <>
0994     struct compute_compatible_component_variant<utree, utree>
0995       : mpl::true_
0996     {
0997         typedef utree compatible_type;
0998 
0999         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 utf8_symbol_type 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 type(traits::begin(r), traits::end(r));
1159         }
1160     };
1161 
1162     template <>
1163     struct extract_from_container<utree, utf8_string_type>
1164     {
1165         typedef utf8_string_type 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 type(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 = t.begin();
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 utf8_string_type 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 type(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 utf8_symbol_type 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 type(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