| 1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
| 2 | // Copyright (c) 2001-2011 Joel de Guzman |
| 3 | // |
| 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) |
| 6 | |
| 7 | #ifndef BOOST_SPIRIT_QI_DETAIL_ATTRIBUTES_HPP |
| 8 | #define BOOST_SPIRIT_QI_DETAIL_ATTRIBUTES_HPP |
| 9 | |
| 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> |
| 14 | |
| 15 | /////////////////////////////////////////////////////////////////////////////// |
| 16 | namespace boost { namespace spirit { namespace qi |
| 17 | { |
| 18 | template <typename Exposed, typename Transformed> |
| 19 | struct default_transform_attribute |
| 20 | { |
| 21 | typedef Transformed type; |
| 22 | |
| 23 | static Transformed pre(Exposed&) { return Transformed(); } |
| 24 | |
| 25 | static void post(Exposed& val, Transformed const& attr) |
| 26 | { |
| 27 | traits::assign_to(attr, val); |
| 28 | } |
| 29 | |
| 30 | // fail() will be called by Qi rule's if the rhs failed parsing |
| 31 | static void fail(Exposed&) {} |
| 32 | }; |
| 33 | |
| 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> |
| 37 | { |
| 38 | typedef Attribute& type; |
| 39 | static Attribute& pre(Attribute& val) { return val; } |
| 40 | static void post(Attribute&, Attribute const&) {} |
| 41 | static void fail(Attribute&) {} |
| 42 | }; |
| 43 | |
| 44 | template <typename Exposed, typename Transformed> |
| 45 | struct proxy_transform_attribute |
| 46 | { |
| 47 | typedef Transformed type; |
| 48 | |
| 49 | static Transformed pre(Exposed& val) { return Transformed(val); } |
| 50 | static void post(Exposed&, Transformed const&) { /* no-op */ } |
| 51 | |
| 52 | // fail() will be called by Qi rule's if the rhs failed parsing |
| 53 | static void fail(Exposed&) {} |
| 54 | }; |
| 55 | |
| 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> |
| 59 | { |
| 60 | typedef Attribute& type; |
| 61 | static Attribute& pre(Attribute& val) { return val; } |
| 62 | static void post(Attribute&, Attribute const&) {} |
| 63 | static void fail(Attribute&) {} |
| 64 | }; |
| 65 | |
| 66 | // main specialization for Qi |
| 67 | template <typename Exposed, typename Transformed, typename Enable = void> |
| 68 | struct transform_attribute |
| 69 | : mpl::if_< |
| 70 | mpl::and_< |
| 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> |
| 76 | >::type |
| 77 | {}; |
| 78 | |
| 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> |
| 82 | { |
| 83 | typedef Transformed& type; |
| 84 | static Transformed& pre(boost::optional<Exposed>& val) |
| 85 | { |
| 86 | if (!val) |
| 87 | val = Transformed(); |
| 88 | return boost::get<Transformed>(val); |
| 89 | } |
| 90 | static void post(boost::optional<Exposed>&, Transformed const&) {} |
| 91 | static void fail(boost::optional<Exposed>& val) |
| 92 | { |
| 93 | val = none; // leave optional uninitialized if rhs failed |
| 94 | } |
| 95 | }; |
| 96 | |
| 97 | // unused_type needs some special handling as well |
| 98 | template <> |
| 99 | struct transform_attribute<unused_type, unused_type> |
| 100 | { |
| 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) {} |
| 105 | }; |
| 106 | |
| 107 | template <> |
| 108 | struct transform_attribute<unused_type const, unused_type> |
| 109 | : transform_attribute<unused_type, unused_type> |
| 110 | {}; |
| 111 | |
| 112 | template <typename Attribute> |
| 113 | struct transform_attribute<Attribute, unused_type> |
| 114 | : transform_attribute<unused_type, unused_type> |
| 115 | {}; |
| 116 | |
| 117 | template <typename Attribute> |
| 118 | struct transform_attribute<Attribute const, unused_type> |
| 119 | : transform_attribute<unused_type, unused_type> |
| 120 | {}; |
| 121 | }}} |
| 122 | |
| 123 | /////////////////////////////////////////////////////////////////////////////// |
| 124 | namespace boost { namespace spirit { namespace traits |
| 125 | { |
| 126 | namespace detail { |
| 127 | template <typename Exposed, typename Transformed> |
| 128 | struct transform_attribute_base<Exposed, Transformed, qi::domain> |
| 129 | : qi::transform_attribute<Exposed, Transformed> |
| 130 | {}; |
| 131 | } |
| 132 | }}} |
| 133 | |
| 134 | #endif |
| 135 | |