Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r59342 - in trunk/boost/spirit/home: qi/nonterminal qi/numeric/detail support
From: hartmut.kaiser_at_[hidden]
Date: 2010-01-29 10:40:02


Author: hkaiser
Date: 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
New Revision: 59342
URL: http://svn.boost.org/trac/boost/changeset/59342

Log:
Spirit: added support for fusion_adapt_class in Spirit, added fail_transform handler to attribute_transform
Added:
   trunk/boost/spirit/home/support/adapt_class_attributes.hpp (contents, props changed)
Text files modified:
   trunk/boost/spirit/home/qi/nonterminal/rule.hpp | 6 +++++
   trunk/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp | 6 ++++
   trunk/boost/spirit/home/support/attributes.hpp | 45 ++++++++++++++++++++++++++++++++++++++-
   trunk/boost/spirit/home/support/attributes_fwd.hpp | 9 ++++++++
   4 files changed, 63 insertions(+), 3 deletions(-)

Modified: trunk/boost/spirit/home/qi/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/rule.hpp (original)
+++ trunk/boost/spirit/home/qi/nonterminal/rule.hpp 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
@@ -245,6 +245,9 @@
                     traits::post_transform(attr, attr_);
                     return true;
                 }
+
+ // inform attribute transformation of failed rhs
+ transform::fail(attr);
             }
             return false;
         }
@@ -285,6 +288,9 @@
                     traits::post_transform(attr, attr_);
                     return true;
                 }
+
+ // inform attribute transformation of failed rhs
+ transform::fail(attr);
             }
             return false;
         }

Modified: trunk/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp (original)
+++ trunk/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
@@ -451,7 +451,11 @@
                 }
             }
 
- Attribute val = Accumulate ? attr : Attribute(0);
+ typedef typename
+ traits::attribute_type<Attribute>::type
+ attribute_type;
+
+ attribute_type val = Accumulate ? attr : attribute_type(0);
             char_type ch = *it;
 
             if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val))

Added: trunk/boost/spirit/home/support/adapt_class_attributes.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/adapt_class_attributes.hpp 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
@@ -0,0 +1,123 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_SPIRIT_ADAPT_CLASS_ATTRIBUTES_JAN_27_2010_1219PM)
+#define BOOST_SPIRIT_ADAPT_CLASS_ATTRIBUTES_JAN_27_2010_1219PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/attributes.hpp>
+#include <boost/spirit/home/support/container.hpp>
+#include <boost/fusion/include/adapt_class.hpp>
+#include <boost/utility/enable_if.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// forward declaration only
+namespace boost { namespace fusion { namespace extension
+{
+ template <typename T, int N> struct class_member_proxy;
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// customization points allowing to use adapted classes with spirit
+namespace boost { namespace spirit { namespace traits
+{
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, int N>
+ struct is_container<fusion::extension::class_member_proxy<T, N> >
+ : is_container<typename fusion::extension::class_member_proxy<T, N>::type>
+ {};
+
+ template <typename T, int N>
+ struct container_value<fusion::extension::class_member_proxy<T, N> >
+ : container_value<typename fusion::extension::class_member_proxy<T, N>::type>
+ {};
+
+ template <typename T, int N, typename Val>
+ struct push_back_container<fusion::extension::class_member_proxy<T, N>, Val
+ , typename enable_if<
+ is_reference<typename fusion::extension::class_member_proxy<T, N>::type>
+ >::type>
+ {
+ static bool call(fusion::extension::class_member_proxy<T, N>& p, Val const& val)
+ {
+ typedef typename fusion::extension::class_member_proxy<T, N>::type type;
+ return push_back((type)p, val);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, int N, typename Val>
+ struct assign_to_attribute_from_value<
+ fusion::extension::class_member_proxy<T, N>, Val>
+ {
+ static void
+ call(Val const& val, fusion::extension::class_member_proxy<T, N>& attr)
+ {
+ attr = val;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, int N>
+ struct attribute_type<fusion::extension::class_member_proxy<T, N> >
+ : fusion::extension::class_member_proxy<T, N>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, int N, typename Attribute>
+ struct transform_attribute<
+ fusion::extension::class_member_proxy<T, N>, Attribute
+ , typename disable_if<
+ is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue>
+ >::type>
+ {
+ typedef Attribute type;
+
+ static Attribute
+ pre(fusion::extension::class_member_proxy<T, N>& val)
+ {
+ return val;
+ }
+ static void
+ post(fusion::extension::class_member_proxy<T, N>& val
+ , Attribute const& attr)
+ {
+ val = attr;
+ }
+ static void
+ fail(fusion::extension::class_member_proxy<T, N>&)
+ {
+ }
+ };
+
+ template <typename T, int N, typename Attribute>
+ struct transform_attribute<
+ fusion::extension::class_member_proxy<T, N>, Attribute
+ , typename enable_if<
+ is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue>
+ >::type>
+ {
+ typedef Attribute& type;
+
+ static Attribute&
+ pre(fusion::extension::class_member_proxy<T, N>& val)
+ {
+ return val;
+ }
+ static void
+ post(fusion::extension::class_member_proxy<T, N>&, Attribute const&)
+ {
+ }
+ static void
+ fail(fusion::extension::class_member_proxy<T, N>&)
+ {
+ }
+ };
+}}}
+
+#endif

Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
@@ -31,6 +31,7 @@
 #include <boost/mpl/end.hpp>
 #include <boost/mpl/find_if.hpp>
 #include <boost/mpl/identity.hpp>
+#include <boost/utility/enable_if.hpp>
 #include <boost/variant.hpp>
 #include <vector>
 #include <utility>
@@ -112,6 +113,15 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+ // Retrieve the attribute type to use from the given type
+ //
+ // This is needed to extract the correct attribute type from proxy classes
+ // as utilized in FUSION_ADAPT_CLASS
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Enable/* = void*/>
+ struct attribute_type : mpl::identity<Attribute> {};
+
+ ///////////////////////////////////////////////////////////////////////////
     // pass_attribute
     //
     // Determines how we pass attributes to semantic actions. This
@@ -423,6 +433,9 @@
         {
             post(val, attr, is_convertible<Transformed, Exposed>());
         }
+
+ // fail() will be called by Qi rule's if the rhs failed parsing
+ static void fail(Exposed& val) {}
     };
 
     template <typename Exposed, typename Transformed>
@@ -430,7 +443,25 @@
     {
         typedef Transformed type;
         static Transformed pre(Exposed const& val) { return Transformed(val); }
- // Karma only, no post() required
+ // Karma only, no post() and no fail() required
+ };
+
+ template <typename Exposed, typename Transformed>
+ struct transform_attribute<optional<Exposed>, Transformed,
+ typename disable_if<is_same<optional<Exposed>, Transformed> >::type>
+ {
+ typedef Transformed& type;
+ static Transformed& pre(optional<Exposed>& val)
+ {
+ if (!val)
+ val = Transformed();
+ return boost::get<Transformed>(val);
+ }
+ static void post(optional<Exposed>&, Transformed const&) {}
+ static void fail(Exposed& val)
+ {
+ val = none_t(); // leave optional uninitialized if rhs failed
+ }
     };
 
     // handle case where no transformation is required as the types are the same
@@ -440,6 +471,7 @@
         typedef Attribute& type;
         static Attribute& pre(Attribute& val) { return val; }
         static void post(Attribute&, Attribute const&) {}
+ static void fail(Attribute& val) {}
     };
 
     template <typename Attribute>
@@ -447,7 +479,7 @@
     {
         typedef Attribute const& type;
         static Attribute const& pre(Attribute const& val) { return val; }
- // Karma only, no post() required
+ // Karma only, no post() and no fail() required
     };
 
     // reference types need special handling
@@ -462,6 +494,7 @@
         typedef Attribute& type;
         static Attribute& pre(Attribute& val) { return val; }
         static void post(Attribute&, Attribute const&) {}
+ static void fail(Attribute& val) {}
     };
 
     template <typename Attribute>
@@ -476,6 +509,7 @@
         typedef unused_type type;
         static unused_type pre(unused_type) { return unused; }
         static void post(unused_type, unused_type) {}
+ static void fail(unused_type& val) {}
     };
 
     template <>
@@ -526,6 +560,13 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
+ template <typename Exposed, typename Transformed>
+ void fail_transform(Exposed& dest, Transformed const&)
+ {
+ return transform_attribute<Exposed, Transformed>::fail(dest);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
     // make_attribute
     //
     // All parsers and generators have specific attribute types.

Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp 2010-01-29 10:40:01 EST (Fri, 29 Jan 2010)
@@ -15,6 +15,15 @@
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
+ // Retrieve the attribute type to use from the given type
+ //
+ // This is needed to extract the correct attribute type from proxy classes
+ // as utilized in FUSION_ADAPT_CLASS
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Enable = void>
+ struct attribute_type;
+
+ ///////////////////////////////////////////////////////////////////////////
     // Determines how we pass attributes to semantic actions. This
     // may be specialized. By default, all attributes are wrapped in
     // a fusion sequence, because the attribute has to be treated as being


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk