$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r57104 - in trunk/boost/spirit/home: qi/detail support
From: joel_at_[hidden]
Date: 2009-10-23 11:58:32
Author: djowel
Date: 2009-10-23 11:58:31 EDT (Fri, 23 Oct 2009)
New Revision: 57104
URL: http://svn.boost.org/trac/boost/changeset/57104
Log:
alternatives with optional attributes
Text files modified: 
   trunk/boost/spirit/home/qi/detail/alternative_function.hpp |    10 ++++-                                   
   trunk/boost/spirit/home/qi/detail/assign_to.hpp            |     9 +++++                                   
   trunk/boost/spirit/home/support/attributes.hpp             |    61 ++++++++++++++++++++++++++++++++++----- 
   3 files changed, 68 insertions(+), 12 deletions(-)
Modified: trunk/boost/spirit/home/qi/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/alternative_function.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/alternative_function.hpp	2009-10-23 11:58:31 EDT (Fri, 23 Oct 2009)
@@ -42,8 +42,8 @@
         template <typename Component>
         bool call(Component const& component, mpl::false_) const
         {
-            // if Attribute is a variant, then create an attribute for
-            // the Component with its expected type.
+            // if Attribute is a variant or optional, then create an 
+            // attribute for the Component with its expected type.
             typename traits::attribute_of<Component, Context, Iterator>::type val;
             if (component.parse(first, last, context, skipper, val))
             {
@@ -57,7 +57,11 @@
         bool operator()(Component const& component) const
         {
             // return true if the parser succeeds
-            return call(component, spirit::traits::not_is_variant<Attribute>());
+            return call(component, 
+                mpl::and_<
+                    spirit::traits::not_is_variant<Attribute>,
+                    spirit::traits::not_is_optional<Attribute> 
+                >());
         }
 
         Iterator& first;
Modified: trunk/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/assign_to.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/assign_to.hpp	2009-10-23 11:58:31 EDT (Fri, 23 Oct 2009)
@@ -82,6 +82,15 @@
             attr = val;
         }
     };
+    
+    template <typename Attribute>
+    struct assign_to_attribute_from_value<optional<Attribute>, unused_type>
+    {
+        static void 
+        call(unused_type, optional<Attribute> const& attr)
+        {
+        }
+    };
 
     template <typename T, typename Attribute>
     inline void
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes.hpp	2009-10-23 11:58:31 EDT (Fri, 23 Oct 2009)
@@ -51,6 +51,16 @@
     struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
       : mpl::false_ 
     {};
+        
+    template <typename T>
+    struct not_is_optional
+      : mpl::true_ 
+    {};
+
+    template <typename T>
+    struct not_is_variant<boost::optional<T> >
+      : mpl::false_ 
+    {};
 
     ///////////////////////////////////////////////////////////////////////////
     // attribute_of
@@ -255,7 +265,40 @@
             typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type
           , typename mpl::end<Sequence>::type>
     {};
-
+        
+    namespace detail
+    {
+        // default case
+        template <typename Sequence, bool no_unused
+            , int size = mpl::size<Sequence>::value>
+        struct build_collapsed_variant 
+            : spirit::detail::as_variant<Sequence> {};
+                
+        // 1 element case
+        template <typename Sequence, bool no_unused>
+        struct build_collapsed_variant<Sequence, no_unused, 1>
+            : mpl::front<Sequence> {};
+
+        // 2 element case, no unused
+        template <typename Sequence>
+        struct build_collapsed_variant<Sequence, true, 2>
+            : spirit::detail::as_variant<Sequence> {};
+
+        // 2 element case, with unused
+        template <typename Sequence>
+        struct build_collapsed_variant<Sequence, false, 2>
+        {
+            typedef optional<
+                typename mpl::deref<
+                    typename mpl::next<
+                        typename mpl::begin<Sequence>::type
+                    >::type
+                >::type
+            >
+            type;
+        };
+    }
+        
     ///////////////////////////////////////////////////////////////////////////
     // build_variant
     //
@@ -263,7 +306,7 @@
     // that 1) all attributes in the variant are unique 2) puts the unused
     // attribute, if there is any, to the front and 3) collapses single element
     // variants, variant<T> to T.
-    ///////////////////////////////////////////////////////////////////////////
+    ///////////////////////////////////////////////////////////////////////////       
     template <typename Sequence>
     struct build_variant
     {
@@ -271,6 +314,8 @@
         typedef typename
             filter_unused_attributes<Sequence>::type
         filtered_attributes;
+        
+        typedef has_no_unused<Sequence> no_unused;
 
         // If the original attribute list does not contain any unused
         // attributes, it is used, otherwise a single unused_type is
@@ -278,7 +323,7 @@
         // there is an unused_type in the list, it is the first one.
         typedef typename
             mpl::eval_if<
-                has_no_unused<Sequence>,
+                no_unused,
                 mpl::identity<Sequence>,
                 fusion::result_of::push_front<filtered_attributes, unused_type>
             >::type
@@ -293,16 +338,14 @@
                     mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
                 >
             >::type
-        new_sequence;
+        no_duplicates;
 
         // If there is only one type in the list of types we strip off the
         // variant. IOTW, collapse single element variants, variant<T> to T.
+        // Take note that this also collapses variant<unused_type, T> to T.
         typedef typename
-            mpl::eval_if<
-                mpl::equal_to<mpl::size<new_sequence>, mpl::int_<1> >,
-                mpl::deref<mpl::front<attribute_sequence> >,
-                spirit::detail::as_variant<new_sequence>
-            >::type
+            traits::detail::build_collapsed_variant<
+                no_duplicates, no_unused::value>::type
         type;
     };