1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2001-2011 Joel de Guzman
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_SPIRIT_QI_DETAIL_ATTRIBUTES_HPP
8 #define BOOST_SPIRIT_QI_DETAIL_ATTRIBUTES_HPP
10 #include <boost/spirit/home/qi/domain.hpp>
11 #include <boost/spirit/home/support/attributes_fwd.hpp>
12 #include <boost/spirit/home/support/attributes.hpp>
13 #include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
15 ///////////////////////////////////////////////////////////////////////////////
16 namespace boost { namespace spirit { namespace qi
18 template <typename Exposed, typename Transformed>
19 struct default_transform_attribute
21 typedef Transformed type;
23 static Transformed pre(Exposed&) { return Transformed(); }
25 static void post(Exposed& val, Transformed const& attr)
27 traits::assign_to(attr, val);
30 // fail() will be called by Qi rule's if the rhs failed parsing
31 static void fail(Exposed&) {}
34 // handle case where no transformation is required as the types are the same
35 template <typename Attribute>
36 struct default_transform_attribute<Attribute, Attribute>
38 typedef Attribute& type;
39 static Attribute& pre(Attribute& val) { return val; }
40 static void post(Attribute&, Attribute const&) {}
41 static void fail(Attribute&) {}
44 template <typename Exposed, typename Transformed>
45 struct proxy_transform_attribute
47 typedef Transformed type;
49 static Transformed pre(Exposed& val) { return Transformed(val); }
50 static void post(Exposed&, Transformed const&) { /* no-op */ }
52 // fail() will be called by Qi rule's if the rhs failed parsing
53 static void fail(Exposed&) {}
56 // handle case where no transformation is required as the types are the same
57 template <typename Attribute>
58 struct proxy_transform_attribute<Attribute, Attribute>
60 typedef Attribute& type;
61 static Attribute& pre(Attribute& val) { return val; }
62 static void post(Attribute&, Attribute const&) {}
63 static void fail(Attribute&) {}
66 // main specialization for Qi
67 template <typename Exposed, typename Transformed, typename Enable = void>
68 struct transform_attribute
71 mpl::not_<is_const<Exposed> >
72 , mpl::not_<is_reference<Exposed> >
73 , traits::is_proxy<Transformed> >
74 , proxy_transform_attribute<Exposed, Transformed>
75 , default_transform_attribute<Exposed, Transformed>
79 template <typename Exposed, typename Transformed>
80 struct transform_attribute<boost::optional<Exposed>, Transformed
81 , typename disable_if<is_same<boost::optional<Exposed>, Transformed> >::type>
83 typedef Transformed& type;
84 static Transformed& pre(boost::optional<Exposed>& val)
88 return boost::get<Transformed>(val);
90 static void post(boost::optional<Exposed>&, Transformed const&) {}
91 static void fail(boost::optional<Exposed>& val)
93 val = none; // leave optional uninitialized if rhs failed
97 // unused_type needs some special handling as well
99 struct transform_attribute<unused_type, unused_type>
101 typedef unused_type type;
102 static unused_type pre(unused_type) { return unused; }
103 static void post(unused_type, unused_type) {}
104 static void fail(unused_type) {}
108 struct transform_attribute<unused_type const, unused_type>
109 : transform_attribute<unused_type, unused_type>
112 template <typename Attribute>
113 struct transform_attribute<Attribute, unused_type>
114 : transform_attribute<unused_type, unused_type>
117 template <typename Attribute>
118 struct transform_attribute<Attribute const, unused_type>
119 : transform_attribute<unused_type, unused_type>
123 ///////////////////////////////////////////////////////////////////////////////
124 namespace boost { namespace spirit { namespace traits
127 template <typename Exposed, typename Transformed>
128 struct transform_attribute_base<Exposed, Transformed, qi::domain>
129 : qi::transform_attribute<Exposed, Transformed>