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 #if !defined(SPIRIT_QI_DETAIL_ATTRIBUTES_APR_18_2010_0458PM)
8 #define SPIRIT_QI_DETAIL_ATTRIBUTES_APR_18_2010_0458PM
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 // reference types need special handling
98 template <typename Attribute>
99 struct transform_attribute<Attribute&, Attribute>
101 typedef Attribute& type;
102 static Attribute& pre(Attribute& val) { return val; }
103 static void post(Attribute&, Attribute const&) {}
104 static void fail(Attribute&) {}
107 // unused_type needs some special handling as well
109 struct transform_attribute<unused_type, unused_type>
111 typedef unused_type type;
112 static unused_type pre(unused_type) { return unused; }
113 static void post(unused_type, unused_type) {}
114 static void fail(unused_type) {}
118 struct transform_attribute<unused_type const, unused_type>
119 : transform_attribute<unused_type, unused_type>
122 template <typename Attribute>
123 struct transform_attribute<unused_type, Attribute>
124 : transform_attribute<unused_type, unused_type>
127 template <typename Attribute>
128 struct transform_attribute<unused_type const, Attribute>
129 : transform_attribute<unused_type, unused_type>
132 template <typename Attribute>
133 struct transform_attribute<Attribute, unused_type>
134 : transform_attribute<unused_type, unused_type>
137 template <typename Attribute>
138 struct transform_attribute<Attribute const, unused_type>
139 : transform_attribute<unused_type, unused_type>
143 ///////////////////////////////////////////////////////////////////////////////
144 namespace boost { namespace spirit { namespace traits
146 template <typename Exposed, typename Transformed>
147 struct transform_attribute<Exposed, Transformed, qi::domain>
148 : qi::transform_attribute<Exposed, Transformed>
151 template <typename Exposed, typename Transformed>
152 struct transform_attribute<Exposed&, Transformed, qi::domain>
153 : transform_attribute<Exposed, Transformed, qi::domain>
156 template <typename Attribute>
157 struct transform_attribute<Attribute&, Attribute, qi::domain>
158 : qi::transform_attribute<Attribute&, Attribute>
161 ///////////////////////////////////////////////////////////////////////////
162 template <typename Exposed, typename Transformed>
163 void post_transform(Exposed& dest, Transformed const& attr)
165 return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr);
168 ///////////////////////////////////////////////////////////////////////////
169 template <typename Exposed, typename Transformed>
170 void fail_transform(Exposed& dest, Transformed const&)
172 return transform_attribute<Exposed, Transformed, qi::domain>::fail(dest);