$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r69405 - in trunk: boost/spirit boost/spirit/home/lex/qi boost/spirit/home/qi/detail boost/spirit/home/support boost/spirit/home/support/utree libs/spirit/test libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2011-02-28 17:43:28
Author: hkaiser
Date: 2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
New Revision: 69405
URL: http://svn.boost.org/trac/boost/changeset/69405
Log:
Spirit: fixing container attribute handling of sequences and container parser components
Added:
   trunk/libs/spirit/test/qi/pass_container.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/lex/qi/state_switcher.hpp          |     4                                         
   trunk/boost/spirit/home/qi/detail/alternative_function.hpp |    19 ++                                      
   trunk/boost/spirit/home/qi/detail/pass_container.hpp       |   258 +++++++++++++++++++++++---------------- 
   trunk/boost/spirit/home/support/attributes.hpp             |    44 ++++++                                  
   trunk/boost/spirit/home/support/attributes_fwd.hpp         |     8 +                                       
   trunk/boost/spirit/home/support/utree/utree_traits.hpp     |    22 +++                                     
   trunk/boost/spirit/version.hpp                             |     4                                         
   trunk/libs/spirit/test/Jamfile                             |     1                                         
   trunk/libs/spirit/test/qi/alternative.cpp                  |    10 -                                       
   trunk/libs/spirit/test/qi/list.cpp                         |    10                                         
   trunk/libs/spirit/test/qi/sequence.cpp                     |    28 ++-                                     
   trunk/libs/spirit/test/qi/utree3.cpp                       |    24 +-                                      
   12 files changed, 286 insertions(+), 146 deletions(-)
Modified: trunk/boost/spirit/home/lex/qi/state_switcher.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/qi/state_switcher.hpp	(original)
+++ trunk/boost/spirit/home/lex/qi/state_switcher.hpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -138,13 +138,13 @@
             template <typename State>
             reset_state_on_exit(Iterator& it_, State state_)
               : it(it_)
-              , state(detail::set_lexer_state(it_, traits::get_c_string(state_))) 
+              , state(set_lexer_state(it_, traits::get_c_string(state_))) 
             {}
 
             ~reset_state_on_exit()
             {
                 // reset the state of the underlying lexer instance
-                detail::set_lexer_state(it, state);
+                set_lexer_state(it, state);
             }
 
             Iterator& it;
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	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -114,7 +114,7 @@
         }
 
         template <typename Component>
-        bool operator()(Component const& component) const
+        bool call_unused(Component const& component, mpl::true_) const
         {
             // return true if the parser succeeds
             return call(component,
@@ -124,6 +124,23 @@
                 >());
         }
 
+        template <typename Component>
+        bool call_unused(Component const& component, mpl::false_) const
+        {
+            return component.parse(first, last, context, skipper, unused);
+        }
+
+        template <typename Component>
+        bool operator()(Component const& component) const
+        {
+            // return true if the parser succeeds
+            typedef typename traits::not_is_unused<
+                typename traits::attribute_of<Component, Context, Iterator>::type
+            >::type predicate;
+
+            return call_unused(component, predicate());
+        }
+
         Iterator& first;
         Iterator const& last;
         Context& context;
Modified: trunk/boost/spirit/home/qi/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/pass_container.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/pass_container.hpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -25,61 +25,139 @@
 
 namespace boost { namespace spirit { namespace qi { namespace detail
 {
-    // has_same_elements: utility to check if the RHS attribute
-    // is an STL container and that its value_type is convertible
-    // to the LHS.
-
-    template <typename LHS, typename RHSAttribute
-      , bool IsContainer = traits::is_container<RHSAttribute>::value
-      , bool IsSequence = fusion::traits::is_sequence<RHSAttribute>::value>
-    struct has_same_elements : mpl::false_ {};
-
-    template <typename LHS, typename RHSAttribute>
-    struct has_same_elements<LHS, RHSAttribute, true, false>
-      : is_convertible<typename RHSAttribute::value_type, LHS> {};
-
-    template <typename LHS, typename T>
-    struct has_same_elements<LHS, boost::optional<T>, false, false>
-      : has_same_elements<LHS, T> {};
-
-    template <typename LHS, typename T>
-    struct has_same_elements<LHS, boost::optional<T>, true, false>
-      : has_same_elements<LHS, T> {};
-
-    template <typename LHS, typename T>
-    struct has_same_elements<LHS, boost::optional<T>, false, true>
-      : has_same_elements<LHS, T> {};
-
-#define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data)                               \
-        has_same_elements<LHS, BOOST_PP_CAT(T, N)>::value ||                  \
-    /***/
-
-    // Note: variants are treated as containers if one of the held types is a
-    //       container (see support/container.hpp).
-    template <typename LHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-    struct has_same_elements<
-            LHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true, false>
-      : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
-          , BOOST_SPIRIT_IS_CONVERTIBLE, _) false> {};
-
-#undef BOOST_SPIRIT_IS_CONVERTIBLE
+    // pass_through_container: utility to check decide whether a provided 
+    // container attribute needs to be passed through to the current component 
+    // or of we need to split the container by passing along instances of its
+    // value type
+
+    // if the expected attribute of the current component is neither a Fusion 
+    // sequence nor a container, we will pass through the provided container 
+    // only if its value type is not compatible with the component
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Enable = void>
+    struct pass_through_container_base
+      : mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >
+    {};
 
     // Specialization for fusion sequences, in this case we check whether all
     // the types in the sequence are convertible to the lhs attribute.
-    // We return false if the lhs attribute itself is a fusion sequence.
-    template <typename LHS, typename RHSAttribute>
-    struct has_same_elements<LHS, RHSAttribute, false, true>
+    // 
+    // We return false if the rhs attribute itself is a fusion sequence, which
+    // is compatible with the LHS sequence (we want to pass through this 
+    // attribute without it being split apart).
+    template <typename Container, typename ValueType, typename Attribute>
+    struct not_compatible_element
+      : mpl::and_<
+            mpl::not_<traits::is_weak_substitute<Attribute, Container> >
+          , mpl::not_<traits::is_weak_substitute<Attribute, ValueType> > >
+    {};
+
+    // If the value type of the container is not a Fusion sequence, we pass
+    // through the container if each of the elements of the Attribute 
+    // sequence is compatible with either the container or its value type.
+    template <typename Container, typename ValueType, typename Attribute
+      , bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
+    struct pass_through_container_fusion_sequence
     {
         typedef typename mpl::find_if<
-            RHSAttribute, mpl::not_<is_convertible<mpl::_1, LHS> >
+            Attribute, not_compatible_element<Container, ValueType, mpl::_1>
         >::type iter;
-        typedef typename mpl::end<RHSAttribute>::type end;
+        typedef typename mpl::end<Attribute>::type end;
 
-        typedef typename mpl::and_<
-            mpl::not_<fusion::traits::is_sequence<LHS> >, is_same<iter, end>
-        >::type type;
+        typedef typename is_same<iter, end>::type type;
     };
 
+    // If both, the Attribute and the value type of the provided container
+    // are Fusion sequences, we pass the container only if the two 
+    // sequences are not compatible.
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container_fusion_sequence<
+            Container, ValueType, Attribute, true>
+      : mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >
+    {};
+
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container_base<Container, ValueType, Attribute
+          , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
+      : detail::pass_through_container_fusion_sequence<Container, ValueType, Attribute>
+    {};
+
+    // Specialization for containers
+    //
+    // If the value type of the attribute of the current component is not
+    // a Fusion sequence, we have to pass through the provided container if 
+    // both are compatible.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename AttributeValueType
+      , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
+    struct pass_through_container_container
+      : mpl::or_<
+          traits::is_weak_substitute<Attribute, Container> 
+        , traits::is_weak_substitute<AttributeValueType, Container> >
+    {};
+
+    // If the value type of the exposed container attribute is a Fusion
+    // sequence, we use the already existing logic for those.
+    template <typename Container, typename ValueType
+      , typename Attribute, typename AttributeValueType>
+    struct pass_through_container_container<
+            Container, ValueType, Attribute, AttributeValueType, true>
+      : pass_through_container_fusion_sequence<
+            Container, ValueType, AttributeValueType>
+    {};
+
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container_base<Container, ValueType, Attribute
+          , typename enable_if<traits::is_container<Attribute> >::type>
+      : detail::pass_through_container_container<
+          Container, ValueType
+        , Attribute, typename traits::container_value<Attribute>::type>
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container
+      : pass_through_container_base<Container, ValueType, Attribute> 
+    {};
+
+    // Specialization for exposed optional attributes
+    //
+    // If the type embedded in the exposed optional is not a Fusion 
+    // sequence we pass through the container attribute if it is compatible
+    // either to the optionals embedded type or to the containrs value 
+    // type.
+    template <typename Container, typename ValueType, typename Attribute
+      , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
+    struct pass_through_container_optional
+      : mpl::or_<
+          traits::is_weak_substitute<Attribute, Container> 
+        , traits::is_weak_substitute<Attribute, ValueType> >
+    {};
+
+    // If the embedded type of the exposed optional attribute is a Fusion
+    // sequence, we use the already existing logic for those.
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container_optional<
+            Container, ValueType, Attribute, true>
+      : pass_through_container_fusion_sequence<
+            Container, ValueType, Attribute>
+    {};
+
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container<Container, ValueType, boost::optional<Attribute> >
+      : detail::pass_through_container_optional<Container, ValueType, Attribute> 
+    {};
+
+    // If both, the containers value type and the exposed attribute type are
+    // optionals we are allowed to pass through the the container only if the
+    // embedded types of those optionals are not compatible.
+    template <typename Container, typename ValueType, typename Attribute>
+    struct pass_through_container<
+            Container, boost::optional<ValueType>, boost::optional<Attribute> >
+      : mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
     // This function handles the case where the attribute (Attr) given
     // the sequence is an STL container. This is a wrapper around F.
     // The function F does the actual parsing.
@@ -95,7 +173,7 @@
         // this is for the case when the current element exposes an attribute
         // which is pushed back onto the container
         template <typename Component>
-        bool dispatch_attribute_element(Component const& component, mpl::false_) const
+        bool dispatch_container(Component const& component, mpl::false_) const
         {
             // synthesized attribute needs to be default constructed
             typename traits::container_value<Attr>::type val =
@@ -113,34 +191,16 @@
             return r;
         }
 
-        // this is for the case when the current element expects an attribute
-        // which is a container itself, this element will push its data 
-        // directly into the attribute container
+        // this is for the case when the current element is able to handle an 
+        // attribute which is a container itself, this element will push its 
+        // data directly into the attribute container
         template <typename Component>
-        bool dispatch_attribute_element(Component const& component, mpl::true_) const
+        bool dispatch_container(Component const& component, mpl::true_) const
         {
             return f(component, attr);
         }
 
-        // This handles the distinction between elements in a sequence expecting
-        // containers themselves and elements expecting non-containers as their 
-        // attribute. Note: is_container treats optional<T>, where T is a 
-        // container as a container as well.
-        template <typename Component>
-        bool dispatch_attribute(Component const& component, mpl::true_) const
-        {
-            typedef typename traits::attribute_of<
-                Component, context_type, iterator_type>::type attribute_type;
-
-            typedef mpl::and_<
-                traits::is_container<attribute_type>
-              , traits::handles_container<Component, Attr, context_type
-                                        , iterator_type> 
-            > predicate;
-
-            return dispatch_attribute_element(component, predicate());
-        }
-
+        ///////////////////////////////////////////////////////////////////////
         // this is for the case when the current element doesn't expect an 
         // attribute
         template <typename Component>
@@ -149,31 +209,25 @@
             return f(component, unused);
         }
 
-        // This handles the case where the attribute of the component
-        // is not an STL container or its element is not convertible
-        // to the target attribute's (Attr) value_type.
+        // the current element expects an attribute
         template <typename Component>
-        bool dispatch_main(Component const& component, mpl::false_) const
+        bool dispatch_attribute(Component const& component, mpl::true_) const
         {
-            // we need to dispatch again depending on the type of the attribute
-            // of the current element (component). If this is has no attribute
-            // we shouldn't push an element into the container.
-            typedef traits::not_is_unused<
-                typename traits::attribute_of<
-                    Component, context_type, iterator_type
-                >::type
-            > predicate;
+            typedef typename traits::container_value<Attr>::type value_type;
+            typedef typename traits::attribute_of<
+                Component, context_type, iterator_type>::type
+            rhs_attribute;
 
-            return dispatch_attribute(component, predicate());
-        }
+            // this predicate detects, whether the attribute of the current 
+            // element is a substitute for the value type of the container
+            // attribute 
+            typedef mpl::and_<
+                pass_through_container<Attr, value_type, rhs_attribute>
+              , traits::handles_container<
+                    Component, Attr, context_type, iterator_type> 
+            > predicate;
 
-        // This handles the case where the attribute of the component is
-        // an STL container *and* its value_type is convertible to the
-        // target's attribute (Attr) value_type.
-        template <typename Component>
-        bool dispatch_main(Component const& component, mpl::true_) const
-        {
-            return f(component, attr);
+            return dispatch_container(component, predicate());
         }
 
         // Dispatches to dispatch_main depending on the attribute type
@@ -181,23 +235,19 @@
         template <typename Component>
         bool operator()(Component const& component) const
         {
-            typedef typename traits::container_value<Attr>::type lhs;
-            typedef typename traits::attribute_of<
-                Component, context_type, iterator_type>::type
-            rhs_attribute;
-
-            typedef mpl::and_<
-                mpl::or_<
-                    has_same_elements<lhs, rhs_attribute>
-                  , has_same_elements<Attr, rhs_attribute> >
-              , traits::handles_container<Component, Attr, context_type
-                                        , iterator_type> 
-            > predicate;
+            // we need to dispatch depending on the type of the attribute
+            // of the current element (component). If this is has no attribute
+            // we shouldn't pass an attribute at all.
+            typedef typename traits::not_is_unused<
+                typename traits::attribute_of<
+                    Component, context_type, iterator_type
+                >::type
+            >::type predicate;
 
             // ensure the attribute is actually a container type
             traits::make_container(attr);
 
-            return dispatch_main(component, predicate());
+            return dispatch_attribute(component, predicate());
         }
 
         F f;
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes.hpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -58,7 +58,8 @@
     // components.
     ///////////////////////////////////////////////////////////////////////////
 
-    // Find out if T can be a substitute for Expected attribute
+    ///////////////////////////////////////////////////////////////////////////
+    // Find out if T can be a (strong) substitute for Expected attribute
     template <typename T, typename Expected, typename Enable /*= void*/>
     struct is_substitute : is_same<T, Expected> {};
 
@@ -96,6 +97,46 @@
         >::type>
       : mpl::true_ {};
 
+    ///////////////////////////////////////////////////////////////////////////
+    // Find out if T can be a weak substitute for Expected attribute
+    template <typename T, typename Expected, typename Enable /*= void*/>
+    struct is_weak_substitute : is_convertible<T, Expected> {};
+
+    template <typename T, typename Expected>
+    struct is_weak_substitute<optional<T>, optional<Expected> >
+      : is_weak_substitute<T, Expected> {};
+
+    template <typename T, typename Expected>
+    struct is_weak_substitute<T, Expected,
+        typename enable_if<
+            mpl::and_<
+                fusion::traits::is_sequence<T>,
+                fusion::traits::is_sequence<Expected>,
+                mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> >
+            >
+        >::type>
+      : mpl::true_ {};
+
+    namespace detail
+    {
+        template <typename T, typename Expected>
+        struct value_type_is_weak_substitute
+          : is_weak_substitute<typename T::value_type, typename Expected::value_type>
+        {};
+    }
+
+    template <typename T, typename Expected>
+    struct is_weak_substitute<T, Expected,
+        typename enable_if<
+            mpl::and_<
+                is_container<T>,
+                is_container<Expected>,
+                detail::value_type_is_weak_substitute<T, Expected>
+            >
+        >::type>
+      : mpl::true_ {};
+
+    ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Enable/* = void*/>
     struct is_proxy : mpl::false_ {};
 
@@ -292,7 +333,6 @@
     template <typename Attribute, typename Enable/* = void*/>
     struct attribute_type : mpl::identity<Attribute> {};
 
-
     ///////////////////////////////////////////////////////////////////////////
     // Retrieve the size of a fusion sequence (compile time)
     ///////////////////////////////////////////////////////////////////////////
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	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -50,12 +50,18 @@
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
-    // Find out if T can be a substitute for Expected attribute
+    // Find out if T can be a strong substitute for Expected attribute
     ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Expected, typename Enable = void>
     struct is_substitute;
 
     ///////////////////////////////////////////////////////////////////////////
+    // Find out if T can be a weak substitute for Expected attribute
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename T, typename Expected, typename Enable = void>
+    struct is_weak_substitute;
+
+    ///////////////////////////////////////////////////////////////////////////
     // Determine if T is a proxy
     ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Enable = void>
Modified: trunk/boost/spirit/home/support/utree/utree_traits.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/utree_traits.hpp	(original)
+++ trunk/boost/spirit/home/support/utree/utree_traits.hpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -164,6 +164,28 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    // these specializations are needed because utree::value_type == utree
+    template <> 
+    struct is_substitute<utree, utree> 
+      : mpl::true_ 
+    {};
+
+    template <> 
+    struct is_weak_substitute<utree, utree> 
+      : mpl::true_ 
+    {};
+
+    template <> 
+    struct is_substitute<utree::list_type, utree::list_type> 
+      : mpl::true_ 
+    {};
+
+    template <> 
+    struct is_weak_substitute<utree::list_type, utree::list_type> 
+      : mpl::true_ 
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
     // this specialization tells Spirit.Qi to allow assignment to an utree from
     // a variant
     namespace detail
Modified: trunk/boost/spirit/version.hpp
==============================================================================
--- trunk/boost/spirit/version.hpp	(original)
+++ trunk/boost/spirit/version.hpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -1,6 +1,6 @@
 /*=============================================================================
-  Copyright (c) 2001-2010 Joel de Guzman
-  Copyright (c) 2001-2010 Hartmut Kaiser
+  Copyright (c) 2001-2011 Joel de Guzman
+  Copyright (c) 2001-2011 Hartmut Kaiser
   http://spirit.sourceforge.net/
 
   Distributed under the Boost Software License, Version 1.0. (See accompanying
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile	(original)
+++ trunk/libs/spirit/test/Jamfile	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -66,6 +66,7 @@
      [ run qi/not_predicate.cpp    : : : : qi_not_predicate ]
      [ run qi/optional.cpp         : : : : qi_optional ]
      [ run qi/parse_attr.cpp       : : : : qi_parse_attr ]
+     [ run qi/pass_container.cpp   : : : : qi_pass_container ]
      [ run qi/permutation.cpp      : : : : qi_permutation ]
      [ run qi/plus.cpp             : : : : qi_plus ]
      [ run qi/range_run.cpp        : : : : qi_range_run ]
Modified: trunk/libs/spirit/test/qi/alternative.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/alternative.cpp	(original)
+++ trunk/libs/spirit/test/qi/alternative.cpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -50,13 +50,8 @@
       , boost::spirit::unused_type
       , boost::spirit::unused_type) const
     {
-        using boost::get;
-
         BOOST_TEST(v.size() == 5 &&
-            v[1] == 'a' &&
-            v[2] == 'b' &&
-            v[3] == '1' &&
-            v[4] == '2');
+            !v[0] && v[1] == 'a' && v[2] == 'b' && v[3] == '1' && v[4] == '2');
     }
 };
 
@@ -91,8 +86,7 @@
         BOOST_TEST(boost::get<int>(v) == 12345);
 
         BOOST_TEST((test_attr("rock", lit("rock") | int_ | char_, v)));
-        BOOST_TEST(boost::get<int>(&v) == 0);
-        BOOST_TEST(boost::get<char>(&v) == 0);
+        BOOST_TEST(v.which() == 1);
 
         BOOST_TEST((test_attr("x", lit("rock") | int_ | char_, v)));
         BOOST_TEST(boost::get<char>(v) == 'x');
Modified: trunk/libs/spirit/test/qi/list.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/list.cpp	(original)
+++ trunk/libs/spirit/test/qi/list.cpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -90,12 +90,14 @@
     }
 
     {
-        std::vector<boost::optional<std::string> > v;
+        std::vector<boost::optional<char> > v;
         BOOST_TEST(test_attr("#a,#", ('#' >> -alpha) % ',', v)); 
         BOOST_TEST(2 == v.size() && 
-            !!v[0] && "a" == boost::get<std::string>(v[0]) && 
-            !!v[1] && boost::get<std::string>(v[1]).size() == 1 && 
-                    boost::get<std::string>(v[1])[0] == '\0');
+            !!v[0] && 'a' == boost::get<char>(v[0]) && !v[1]);
+
+        std::vector<char> v2;
+        BOOST_TEST(test_attr("#a,#", ('#' >> -alpha) % ',', v2)); 
+        BOOST_TEST(1 == v2.size() && 'a' == v2[0]);
     }
 
     {
Added: trunk/libs/spirit/test/qi/pass_container.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/pass_container.cpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -0,0 +1,291 @@
+//  Copyright (c) 2001-2011 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)
+
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+inline bool compare(std::vector<char> const& v, std::string const& s)
+{
+    return v.size() == s.size() && std::equal(v.begin(), v.end(), s.begin());
+}
+
+int main()
+{
+    using boost::spirit::qi::char_;
+    using boost::spirit::qi::omit;
+
+    {
+        std::vector<char> v;
+        BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', v) &&
+            compare(v, "abcdefgh"));
+
+        std::string s;
+        BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', s) && 
+            s == "abcdefgh");
+
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ','));
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", omit[char_] % ','));
+    }
+
+    {
+        std::vector<char> v1;
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', v1) &&
+            compare(v1, "abcdefgh"));
+        v1.clear();
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> omit[char_]) % ',', v1) &&
+            compare(v1, "aceg"));
+
+        std::string s;
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', s) && 
+            s == "abcdefgh");
+        s.clear();
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> omit[char_]) % ',', s) && 
+            s == "aceg");
+
+        std::vector<std::pair<char, char> > v2;
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', v2) &&
+            v2.size() == 4 && 
+            v2[0] == std::make_pair('a', 'b') && 
+            v2[1] == std::make_pair('c', 'd') &&
+            v2[2] == std::make_pair('e', 'f') &&
+            v2[3] == std::make_pair('g', 'h'));
+
+        s.clear();
+        BOOST_TEST(test_attr("ab,cd,efg", (char_ >> char_) % ',' >> char_, s) &&
+            s == "abcdefg");
+
+        BOOST_TEST(test("ab,cd,ef,gh", (char_ >> char_) % ','));
+        BOOST_TEST(test("ab,cd,ef,gh", (omit[char_ >> char_]) % ','));
+    }
+
+    {
+        std::vector<char> v1;
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> *~char_(',')) % ',', v1) &&
+            compare(v1, "abcdefgh"));
+        v1.clear();
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> omit[*~char_(',')]) % ',', v1) &&
+            compare(v1, "adg"));
+        v1.clear();
+        BOOST_TEST(test_attr("abc,def,gh", (omit[char_] >> *~char_(',')) % ',', v1) &&
+            compare(v1, "bcefh"));
+
+        std::string s1;
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> *~char_(',')) % ',', s1) && 
+            s1 == "abcdefgh");
+        s1.clear();
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> omit[*~char_(',')]) % ',', s1) && 
+            s1 == "adg");
+        s1.clear();
+        BOOST_TEST(test_attr("abc,def,gh", (omit[char_] >> *~char_(',')) % ',', s1) && 
+            s1 == "bcefh");
+
+        std::vector<std::pair<char, std::vector<char> > > v2;
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> *~char_(',')) % ',', v2) &&
+            v2.size() == 3 && 
+            v2[0].first == 'a' && compare(v2[0].second, "bc") && 
+            v2[1].first == 'd' && compare(v2[1].second, "ef") &&
+            v2[2].first == 'g' && compare(v2[2].second, "h"));
+
+        std::vector<std::vector<char> > v3;
+        BOOST_TEST(test_attr("abc,def,gh", (omit[char_] >> *~char_(',')) % ',', v3) &&
+            v3.size() == 3 && 
+            compare(v3[0], "bc") && compare(v3[1], "ef") &&
+            compare(v3[2], "h"));
+
+        std::vector<char> v4;
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> omit[*~char_(',')]) % ',', v4) &&
+            v4.size() == 3 && 
+            v4[0] == 'a' &&  v4[1] == 'd' && v4[2] == 'g');
+
+        std::vector<std::string> v5;
+        BOOST_TEST(test_attr("abc,def,gh", (omit[char_] >> *~char_(',')) % ',', v5) &&
+            v5.size() == 3 && 
+            v5[0] == "bc" && v5[1] == "ef" && v5[2] == "h");
+
+        std::string s2;
+        BOOST_TEST(test_attr("abc,def,gh", (char_ >> omit[*~char_(',')]) % ',', s2) &&
+            s2.size() == 3 && 
+            s2 == "adg");
+
+        BOOST_TEST(test("abc,def,gh", (char_ >> *~char_(',')) % ','));
+        BOOST_TEST(test("abc,def,gh", (omit[char_ >> *~char_(',')]) % ','));
+    }
+
+    {
+        using boost::spirit::qi::alpha;
+        using boost::spirit::qi::digit;
+
+        std::vector<char> v1;
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> *digit) % ',', v1) &&
+            compare(v1, "ab12cd34ef56"));
+        v1.clear();
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (omit[*alpha] >> *digit) % ',', v1) &&
+            compare(v1, "123456"));
+        v1.clear();
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> omit[*digit]) % ',', v1) &&
+            compare(v1, "abcdef"));
+
+        std::string s1;
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> *digit) % ',', s1) &&
+            s1 == "ab12cd34ef56");
+        s1.clear();
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (omit[*alpha] >> *digit) % ',', s1) &&
+            s1 == "123456");
+        s1.clear();
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> omit[*digit]) % ',', s1) &&
+            s1 == "abcdef");
+
+        std::vector<std::pair<std::vector<char>, std::vector<char> > > v2;
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> *digit) % ',', v2) &&
+            v2.size() == 3 && 
+            compare(v2[0].first, "ab") && compare(v2[0].second, "12") &&
+            compare(v2[1].first, "cd") && compare(v2[1].second, "34") &&
+            compare(v2[2].first, "ef") && compare(v2[2].second, "56"));
+
+        std::vector<std::pair<std::string, std::string> > v3;
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (*alpha >> *digit) % ',', v3) &&
+            v3.size() == 3 && 
+            v3[0].first == "ab" && v3[0].second == "12" &&
+            v3[1].first == "cd" && v3[1].second == "34" &&
+            v3[2].first == "ef" && v3[2].second == "56");
+
+        std::vector<std::vector<char> > v4;
+        BOOST_TEST(test_attr("ab12,cd34,ef56", (omit[*alpha] >> *digit) % ',', v4) &&
+            v4.size() == 3 && 
+            compare(v4[0], "12") &&
+            compare(v4[1], "34") &&
+            compare(v4[2], "56"));
+
+        BOOST_TEST(test("ab12,cd34,ef56", (*alpha >> *digit) % ','));
+        BOOST_TEST(test("ab12,cd34,ef56", omit[*alpha >> *digit] % ','));
+    }
+
+    {
+        std::vector<std::vector<char> > v1;
+        BOOST_TEST(test_attr("abc,def,gh", *~char_(',') % ',', v1) &&
+            v1.size() == 3 && 
+            compare(v1[0], "abc") && 
+            compare(v1[1], "def") && 
+            compare(v1[2], "gh"));
+
+        std::vector<std::string> v2;
+        BOOST_TEST(test_attr("abc,def,gh", *~char_(',') % ',', v2) && 
+            v2.size() == 3 && v2[0] == "abc" && v2[1] == "def" && v2[2] == "gh");
+
+        BOOST_TEST(test("abc,def,gh", *~char_(',') % ','));
+        BOOST_TEST(test("abc,def,gh", omit[*~char_(',')] % ','));
+    }
+
+    {
+        std::vector<char> v1;
+        BOOST_TEST(test_attr("a", char_ >> -(char_ % ','), v1) &&
+            compare(v1, "a"));
+        v1.clear();
+        BOOST_TEST(test_attr("ab,c", char_ >> -(char_ % ','), v1) &&
+            compare(v1, "abc"));
+        v1.clear();
+        BOOST_TEST(test_attr("a", char_ >> -char_, v1) &&
+            compare(v1, "a"));
+        v1.clear();
+        BOOST_TEST(test_attr("ab", char_ >> -char_, v1) &&
+            compare(v1, "ab"));
+
+        std::vector<boost::optional<char> > v2;
+        BOOST_TEST(test_attr("a", char_ >> -char_, v2) &&
+            v2.size() == 2 && 
+            boost::get<char>(v2[0]) == 'a' && 
+            !v2[1]);
+        v2.clear();
+        BOOST_TEST(test_attr("ab", char_ >> -char_, v2) &&
+            v2.size() == 2 && 
+            boost::get<char>(v2[0]) == 'a' && 
+            boost::get<char>(v2[1]) == 'b');
+
+        std::string s;
+        BOOST_TEST(test_attr("a", char_ >> -(char_ % ','), s) &&
+            s == "a");
+        s.clear();
+        BOOST_TEST(test_attr("ab,c", char_ >> -(char_ % ','), s) &&
+            s == "abc");
+        s.clear();
+        BOOST_TEST(test_attr("ab", char_ >> -char_, s) &&
+            s == "ab");
+        s.clear();
+        BOOST_TEST(test_attr("a", char_ >> -char_, s) &&
+            s ==  "a");
+
+        BOOST_TEST(test("a", char_ >> -(char_ % ',')));
+        BOOST_TEST(test("ab,c", char_ >> -(char_ % ',')));
+        BOOST_TEST(test("a", char_ >> -char_));
+        BOOST_TEST(test("ab", char_ >> -char_));
+    }
+
+    {
+        using boost::spirit::qi::eps;
+
+        std::vector<char> v;
+        BOOST_TEST(test_attr("a", char_ >> ((char_ % ',') | eps), v) &&
+            compare(v, "a"));
+        v.clear();
+        BOOST_TEST(test_attr("ab,c", char_ >> ((char_ % ',') | eps), v) &&
+            compare(v, "abc"));
+
+        std::string s;
+        BOOST_TEST(test_attr("a", char_ >> ((char_ % ',') | eps), s) &&
+            s == "a");
+        s.clear();
+        BOOST_TEST(test_attr("ab,c", char_ >> ((char_ % ',') | eps), s) &&
+            s == "abc");
+
+        BOOST_TEST(test("a", char_ >> ((char_ % ',') | eps)));
+        BOOST_TEST(test("ab,c", char_ >> ((char_ % ',') | eps)));
+    }
+
+    {
+        std::vector<char> v1;
+        BOOST_TEST(test_attr("abc1,abc2", 
+                *~char_(',') >> *(',' >> *~char_(',')), v1) &&
+            compare(v1, "abc1abc2"));
+
+        std::vector<std::string> v2;
+        BOOST_TEST(test_attr("abc1,abc2", 
+                *~char_(',') >> *(',' >> *~char_(',')), v2) &&
+            v2.size() == 2 && 
+            v2[0] == "abc1" &&
+            v2[1] == "abc2");
+
+        std::string s;
+        BOOST_TEST(test_attr("abc1,abc2", 
+                *~char_(',') >> *(',' >> *~char_(',')), s) &&
+            s == "abc1abc2");
+    }
+
+    return boost::report_errors();
+}
+
Modified: trunk/libs/spirit/test/qi/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/sequence.cpp	(original)
+++ trunk/libs/spirit/test/qi/sequence.cpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -234,15 +234,10 @@
     // alternative forms of attributes. Allow sequences to take in
     // stl containers of stl containers.
     {
-        // this use case seem1 to verify wrong behavior, but it is correct,
-        // think about it!
-
         std::vector<std::string> v;
         BOOST_TEST(test_attr("abc1,abc2", 
             *~char_(',') >> *(',' >> *~char_(',')), v));
-        BOOST_TEST(v.size() == 8 &&
-            v[0] == "a" && v[1] == "b" && v[2] == "c" && v[3] == "1" &&
-            v[4] == "a" && v[5] == "b" && v[6] == "c" && v[7] == "2");
+        BOOST_TEST(v.size() == 2 && v[0] == "abc1" && v[1] == "abc2");
     }
 
     {
@@ -279,10 +274,23 @@
         BOOST_TEST(test_attr("ab", char_ >> -char_, v));
         BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b');
 
-//  this is still failing
-//         v.clear();
-//         BOOST_TEST(test_attr("a", char_ >> -char_, v));
-//         BOOST_TEST(v.size() == 1 && v[0] == 'a');
+        v.clear();
+        BOOST_TEST(test_attr("a", char_ >> -char_, v));
+        BOOST_TEST(v.size() == 1 && v[0] == 'a');
+
+        v.clear();
+        BOOST_TEST(test_attr("a", char_, v));
+        BOOST_TEST(v.size() == 1 && v[0] == 'a');
+    }
+
+    {
+        std::vector<boost::optional<char> > v;
+        BOOST_TEST(test_attr("ab", char_ >> -char_, v));
+        BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b');
+
+        v.clear();
+        BOOST_TEST(test_attr("a", char_ >> -char_, v));
+        BOOST_TEST(v.size() == 2 && v[0] == 'a' && !v[1]);
 
         v.clear();
         BOOST_TEST(test_attr("a", char_, v));
Modified: trunk/libs/spirit/test/qi/utree3.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree3.cpp	(original)
+++ trunk/libs/spirit/test/qi/utree3.cpp	2011-02-28 17:43:13 EST (Mon, 28 Feb 2011)
@@ -78,7 +78,7 @@
         ut.clear();
         BOOST_TEST(test_attr("10.2", r2, ut) &&
             ut.which() == utree_type::double_type && check(ut, "10.2"));
-        
+
         rule<char const*, utree::list_type()> r3 = strict_double | int_;
         ut.clear();
         BOOST_TEST(test_attr("10", r3, ut) &&
@@ -109,9 +109,9 @@
 
         BOOST_TEST(test_attr("1", int_ >> -char_, ut));
         BOOST_TEST(ut.which() == utree_type::list_type); 
-        BOOST_TEST(check(ut, "( 1 <invalid> )"));
+        BOOST_TEST(check(ut, "( 1 )"));
         ut.clear();
-        
+
         BOOST_TEST(test_attr("1x", -int_ >> char_, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
         BOOST_TEST(check(ut, "( 1 \"x\" )"));
@@ -119,23 +119,23 @@
 
         BOOST_TEST(test_attr("x", -int_ >> char_, ut));
         BOOST_TEST(ut.which() == utree_type::list_type); 
-        BOOST_TEST(check(ut, "( <invalid> \"x\" )"));
+        BOOST_TEST(check(ut, "( \"x\" )"));
         ut.clear();
 
         rule<char const*, utree::list_type()> r1 = int_ >> -char_;
-        
+
         BOOST_TEST(test_attr("1x", r1, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
         BOOST_TEST(check(ut, "( 1 \"x\" )"));
         ut.clear();
-        
+
         BOOST_TEST(test_attr("1", r1, ut));
         BOOST_TEST(ut.which() == utree_type::list_type); 
-        BOOST_TEST(check(ut, "( 1 <invalid> )"));
+        BOOST_TEST(check(ut, "( 1 )"));
         ut.clear();
-        
+
         rule<char const*, utree::list_type()> r2 = -int_ >> char_;
-        
+
         BOOST_TEST(test_attr("1x", r2, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
         BOOST_TEST(check(ut, "( 1 \"x\" )"));
@@ -143,11 +143,11 @@
 
         BOOST_TEST(test_attr("x", r2, ut));
         BOOST_TEST(ut.which() == utree_type::list_type); 
-        BOOST_TEST(check(ut, "( <invalid> \"x\" )"));
+        BOOST_TEST(check(ut, "( \"x\" )"));
         ut.clear();
-        
+
         rule<char const*, utree()> r3 = int_;
-        
+
         BOOST_TEST(test_attr("1", -r3, ut));
         BOOST_TEST(ut.which() == utree_type::int_type);
         BOOST_TEST(check(ut, "1"));