Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Copyright (c) 2001-2011 Joel de Guzman Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(SPIRIT_QI_DETAIL_ATTRIBUTES_APR_18_2010_0458PM) Chris@16: #define SPIRIT_QI_DETAIL_ATTRIBUTES_APR_18_2010_0458PM Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace qi Chris@16: { Chris@16: template Chris@16: struct default_transform_attribute Chris@16: { Chris@16: typedef Transformed type; Chris@16: Chris@16: static Transformed pre(Exposed&) { return Transformed(); } Chris@16: Chris@16: static void post(Exposed& val, Transformed const& attr) Chris@16: { Chris@16: traits::assign_to(attr, val); Chris@16: } Chris@16: Chris@16: // fail() will be called by Qi rule's if the rhs failed parsing Chris@16: static void fail(Exposed&) {} Chris@16: }; Chris@16: Chris@16: // handle case where no transformation is required as the types are the same Chris@16: template Chris@16: struct default_transform_attribute Chris@16: { Chris@16: typedef Attribute& type; Chris@16: static Attribute& pre(Attribute& val) { return val; } Chris@16: static void post(Attribute&, Attribute const&) {} Chris@16: static void fail(Attribute&) {} Chris@16: }; Chris@16: Chris@16: template Chris@16: struct proxy_transform_attribute Chris@16: { Chris@16: typedef Transformed type; Chris@16: Chris@16: static Transformed pre(Exposed& val) { return Transformed(val); } Chris@16: static void post(Exposed&, Transformed const&) { /* no-op */ } Chris@16: Chris@16: // fail() will be called by Qi rule's if the rhs failed parsing Chris@16: static void fail(Exposed&) {} Chris@16: }; Chris@16: Chris@16: // handle case where no transformation is required as the types are the same Chris@16: template Chris@16: struct proxy_transform_attribute Chris@16: { Chris@16: typedef Attribute& type; Chris@16: static Attribute& pre(Attribute& val) { return val; } Chris@16: static void post(Attribute&, Attribute const&) {} Chris@16: static void fail(Attribute&) {} Chris@16: }; Chris@16: Chris@16: // main specialization for Qi Chris@16: template Chris@16: struct transform_attribute Chris@16: : mpl::if_< Chris@16: mpl::and_< Chris@16: mpl::not_ > Chris@16: , mpl::not_ > Chris@16: , traits::is_proxy > Chris@16: , proxy_transform_attribute Chris@16: , default_transform_attribute Chris@16: >::type Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute, Transformed Chris@16: , typename disable_if, Transformed> >::type> Chris@16: { Chris@16: typedef Transformed& type; Chris@16: static Transformed& pre(boost::optional& val) Chris@16: { Chris@16: if (!val) Chris@16: val = Transformed(); Chris@16: return boost::get(val); Chris@16: } Chris@16: static void post(boost::optional&, Transformed const&) {} Chris@16: static void fail(boost::optional& val) Chris@16: { Chris@16: val = none_t(); // leave optional uninitialized if rhs failed Chris@16: } Chris@16: }; Chris@16: Chris@16: // reference types need special handling Chris@16: template Chris@16: struct transform_attribute Chris@16: { Chris@16: typedef Attribute& type; Chris@16: static Attribute& pre(Attribute& val) { return val; } Chris@16: static void post(Attribute&, Attribute const&) {} Chris@16: static void fail(Attribute&) {} Chris@16: }; Chris@16: Chris@16: // unused_type needs some special handling as well Chris@16: template <> Chris@16: struct transform_attribute Chris@16: { Chris@16: typedef unused_type type; Chris@16: static unused_type pre(unused_type) { return unused; } Chris@16: static void post(unused_type, unused_type) {} Chris@16: static void fail(unused_type) {} Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: }}} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: template Chris@16: struct transform_attribute Chris@16: : qi::transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : transform_attribute Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct transform_attribute Chris@16: : qi::transform_attribute Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: void post_transform(Exposed& dest, Transformed const& attr) Chris@16: { Chris@16: return transform_attribute::post(dest, attr); Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: void fail_transform(Exposed& dest, Transformed const&) Chris@16: { Chris@16: return transform_attribute::fail(dest); Chris@16: } Chris@16: }}} Chris@16: Chris@16: #endif