$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r68645 - in trunk: boost/spirit/home/karma/auto boost/spirit/home/karma/detail boost/spirit/home/karma/numeric boost/spirit/home/karma/operator boost/spirit/home/karma/stream boost/spirit/home/qi/detail boost/spirit/home/qi/directive boost/spirit/home/qi/numeric boost/spirit/home/qi/operator boost/spirit/home/qi/stream boost/spirit/home/support boost/spirit/home/support/detail boost/spirit/home/support/utree libs/spirit/doc libs/spirit/test libs/spirit/test/karma libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2011-02-04 22:48:58
Author: hkaiser
Date: 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
New Revision: 68645
URL: http://svn.boost.org/trac/boost/changeset/68645
Log:
Spirit: unified handling of sequences and container components for container attributes, modified hold_any to enable streaming with wchar_t, added extract_from_container CP, fixed integral generators for const data types
Added:
   trunk/libs/spirit/test/karma/regression_const_real_policies.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/karma/auto/auto.hpp             |     2                                         
   trunk/boost/spirit/home/karma/detail/attributes.hpp     |     2                                         
   trunk/boost/spirit/home/karma/detail/extract_from.hpp   |   122 ++++++++++++++++++++++++++++++++++++-   
   trunk/boost/spirit/home/karma/detail/pass_container.hpp |    59 ++++++++++++++++-                       
   trunk/boost/spirit/home/karma/numeric/bool.hpp          |     6 +                                       
   trunk/boost/spirit/home/karma/numeric/int.hpp           |     9 +-                                      
   trunk/boost/spirit/home/karma/numeric/real.hpp          |     9 +-                                      
   trunk/boost/spirit/home/karma/numeric/uint.hpp          |     8 +-                                      
   trunk/boost/spirit/home/karma/operator/kleene.hpp       |    67 +++++++++++++------                     
   trunk/boost/spirit/home/karma/operator/list.hpp         |    76 +++++++++++++---------                  
   trunk/boost/spirit/home/karma/operator/optional.hpp     |     4                                         
   trunk/boost/spirit/home/karma/operator/plus.hpp         |    85 +++++++++++++++++--------               
   trunk/boost/spirit/home/karma/operator/sequence.hpp     |    83 +-----------------------                
   trunk/boost/spirit/home/karma/stream/stream.hpp         |     2                                         
   trunk/boost/spirit/home/qi/detail/assign_to.hpp         |    12 +-                                      
   trunk/boost/spirit/home/qi/detail/pass_container.hpp    |    36 +++++++++-                              
   trunk/boost/spirit/home/qi/directive/repeat.hpp         |    90 ++++++--------------------              
   trunk/boost/spirit/home/qi/numeric/int.hpp              |    20 +++---                                  
   trunk/boost/spirit/home/qi/operator/expect.hpp          |     5                                         
   trunk/boost/spirit/home/qi/operator/kleene.hpp          |    37 ++++++----                              
   trunk/boost/spirit/home/qi/operator/list.hpp            |    47 ++++++++-----                           
   trunk/boost/spirit/home/qi/operator/optional.hpp        |    33 ++++++++-                               
   trunk/boost/spirit/home/qi/operator/plus.hpp            |    44 +++++++------                           
   trunk/boost/spirit/home/qi/operator/sequence.hpp        |     5                                         
   trunk/boost/spirit/home/qi/operator/sequence_base.hpp   |     1                                         
   trunk/boost/spirit/home/qi/stream/stream.hpp            |     2                                         
   trunk/boost/spirit/home/support/attributes.hpp          |     5                                         
   trunk/boost/spirit/home/support/attributes_fwd.hpp      |     3                                         
   trunk/boost/spirit/home/support/container.hpp           |     2                                         
   trunk/boost/spirit/home/support/detail/hold_any.hpp     |   130 +++++++++++++++++++++++---------------- 
   trunk/boost/spirit/home/support/utree/operators.hpp     |     1                                         
   trunk/boost/spirit/home/support/utree/utree_traits.hpp  |    44 +++++++++---                            
   trunk/libs/spirit/doc/what_s_new.qbk                    |     4                                         
   trunk/libs/spirit/test/Jamfile                          |     1                                         
   trunk/libs/spirit/test/karma/kleene.cpp                 |    53 ++++++++++++++++                        
   trunk/libs/spirit/test/karma/list.cpp                   |     7 ++                                      
   trunk/libs/spirit/test/karma/lit.cpp                    |     4 +                                       
   trunk/libs/spirit/test/karma/plus.cpp                   |    49 +++++++++++++++                         
   trunk/libs/spirit/test/karma/repeat2.cpp                |     9 ++                                      
   trunk/libs/spirit/test/karma/stream.cpp                 |     2                                         
   trunk/libs/spirit/test/karma/utree2.cpp                 |     4                                         
   trunk/libs/spirit/test/karma/wstream.cpp                |     2                                         
   trunk/libs/spirit/test/qi/alternative.cpp               |     8 ++                                      
   trunk/libs/spirit/test/qi/debug.cpp                     |     2                                         
   trunk/libs/spirit/test/qi/kleene.cpp                    |     8 --                                      
   trunk/libs/spirit/test/qi/list.cpp                      |    15 ++++                                    
   trunk/libs/spirit/test/qi/optional.cpp                  |     6 +                                       
   trunk/libs/spirit/test/qi/plus.cpp                      |     8 --                                      
   trunk/libs/spirit/test/qi/regression_repeat.cpp         |    10 +-                                      
   trunk/libs/spirit/test/qi/repeat.cpp                    |    46 +++++++++++---                          
   trunk/libs/spirit/test/qi/sequence.cpp                  |    33 +++++++++                               
   trunk/libs/spirit/test/qi/utree1.cpp                    |    12 +--                                     
   trunk/libs/spirit/test/qi/utree2.cpp                    |     5                                         
   53 files changed, 882 insertions(+), 457 deletions(-)
Modified: trunk/boost/spirit/home/karma/auto/auto.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auto/auto.hpp	(original)
+++ trunk/boost/spirit/home/karma/auto/auto.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -60,7 +60,7 @@
         template <typename Context, typename Unused>
         struct attribute
         {
-            typedef spirit::hold_any type;
+            typedef spirit::basic_hold_any<char> type;
         };
 
         auto_generator(Modifiers const& modifiers)
Modified: trunk/boost/spirit/home/karma/detail/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/attributes.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/attributes.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -20,7 +20,7 @@
         typedef Transformed type;
         static Transformed pre(Exposed& val) 
         { 
-            return Transformed(traits::extract_from<Exposed>(val, unused));
+            return Transformed(traits::extract_from<Transformed>(val, unused));
         }
         // Karma only, no post() and no fail() required
     };
Modified: trunk/boost/spirit/home/karma/detail/extract_from.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/extract_from.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/extract_from.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -117,8 +117,109 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    template <typename Attribute, typename Exposed, typename Enable>
+    struct extract_from_container
+    {
+        typedef typename traits::container_value<Attribute const>::type 
+            value_type;
+        typedef typename is_convertible<value_type, Exposed>::type 
+            is_convertible_to_value_type;
+
+        typedef typename mpl::if_<
+           mpl::or_<
+                is_same<value_type, Exposed>, is_same<Attribute, Exposed> > 
+          , Exposed const&, Exposed
+        >::type type;
+
+        // handle case where container value type is convertible to result type
+        // we simply return the front element of the container
+        template <typename Context, typename Pred>
+        static type call(Attribute const& attr, Context& ctx, mpl::true_, Pred)
+        {
+            // return first element from container
+            typedef typename traits::container_iterator<Attribute const>::type 
+                iterator_type;
+
+            iterator_type it = boost::begin(attr);
+            type result = *it;
+            ++it;
+            return result;
+        }
+
+        // handle strings
+        template <typename Iterator>
+        static void append_to_string(Exposed& result, Iterator begin, Iterator end)
+        {
+            for (Iterator i = begin; i != end; ++i)
+                push_back(result, *i);
+        }
+
+        template <typename Context>
+        static type call(Attribute const& attr, Context& ctx, mpl::false_, mpl::true_)
+        {
+            typedef typename char_type_of<Attribute>::type char_type;
+
+            Exposed result;
+            append_to_string(result, traits::get_begin<char_type>(attr)
+              , traits::get_end<char_type>(attr));
+            return result;
+        }
+
+        // everything else gets just passed through
+        template <typename Context>
+        static type call(Attribute const& attr, Context& ctx, mpl::false_, mpl::false_)
+        {
+            return type(attr);
+        }
+
+        template <typename Context>
+        static type call(Attribute const& attr, Context& ctx)
+        {
+            typedef typename mpl::and_<
+                traits::is_string<Exposed>, traits::is_string<Attribute> 
+            >::type handle_strings;
+
+            // return first element from container
+            return call(attr, ctx, is_convertible_to_value_type()
+              , handle_strings());
+        }
+    };
+
+    template <typename Attribute>
+    struct extract_from_container<Attribute, Attribute>
+    {
+        typedef Attribute const& type;
+
+        template <typename Context>
+        static type call(Attribute const& attr, Context& ctx)
+        {
+            return attr;
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    namespace detail
+    {
+        // overload for non-container attributes
+        template <typename Exposed, typename Attribute, typename Context>
+        inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
+        extract_from(Attribute const& attr, Context& ctx, mpl::false_)
+        {
+            return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
+        }
+
+        // overload for containers (but not for variants or optionals 
+        // holding containers)
+        template <typename Exposed, typename Attribute, typename Context>
+        inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
+        extract_from(Attribute const& attr, Context& ctx, mpl::true_)
+        {
+            return extract_from_container<Attribute, Exposed>::call(attr, ctx);
+        }
+    }
+
     template <typename Exposed, typename Attribute, typename Context>
-    typename spirit::result_of::extract_from<Exposed, Attribute>::type
+    inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
     extract_from(Attribute const& attr, Context& ctx
 #if (defined(__GNUC__) && (__GNUC__ < 4)) || \
     (defined(__APPLE__) && defined(__INTEL_COMPILER))
@@ -126,11 +227,18 @@
 #endif
     )
     {
-        return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
+        typedef typename mpl::and_<
+            traits::is_container<Attribute>
+          , traits::not_is_variant<Attribute>
+          , traits::not_is_optional<Attribute> 
+        >::type is_not_wrapped_container;
+
+        return detail::extract_from<Exposed>(attr, ctx
+          , is_not_wrapped_container());
     }
 
     template <typename Exposed, typename Context>
-    unused_type extract_from(unused_type, Context&)
+    inline unused_type extract_from(unused_type, Context&)
     {
         return unused;
     }
@@ -141,7 +249,13 @@
 {
     template <typename Exposed, typename Attribute>
     struct extract_from
-      : traits::extract_from_attribute<Attribute, Exposed>
+      : mpl::if_<
+            mpl::and_<
+                traits::is_container<Attribute>
+              , traits::not_is_variant<Attribute>
+              , traits::not_is_optional<Attribute> >
+          , traits::extract_from_container<Attribute, Exposed>
+          , traits::extract_from_attribute<Attribute, Exposed> >::type
     {};
 
     template <typename Exposed>
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -32,18 +32,27 @@
     // to the RHS.
 
     template <typename RHS, typename LHSAttribute
-      , bool IsContainer = traits::is_container<LHSAttribute>::value>
+      , bool IsContainer = traits::is_container<LHSAttribute>::value
+      , bool IsSequence = fusion::traits::is_sequence<LHSAttribute>::value>
     struct has_same_elements : mpl::false_ {};
 
     template <typename RHS, typename LHSAttribute>
-    struct has_same_elements<RHS, LHSAttribute, true>
+    struct has_same_elements<RHS, LHSAttribute, true, false>
       : mpl::or_<
             is_convertible<RHS, typename LHSAttribute::value_type>
-          , is_same<typename LHSAttribute::value_type, hold_any>
+          , traits::is_hold_any<typename LHSAttribute::value_type>
         > {};
 
     template <typename RHS, typename T>
-    struct has_same_elements<RHS, optional<T>, true>
+    struct has_same_elements<RHS, optional<T>, false, false>
+      : has_same_elements<RHS, T> {};
+
+    template <typename RHS, typename T>
+    struct has_same_elements<RHS, optional<T>, true, false>
+      : has_same_elements<RHS, T> {};
+
+    template <typename RHS, typename T>
+    struct has_same_elements<RHS, optional<T>, false, true>
       : has_same_elements<RHS, T> {};
 
 #define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data)                               \
@@ -54,12 +63,26 @@
     //       container (see support/container.hpp).
     template <typename RHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
     struct has_same_elements<
-            RHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true>
+            RHS, 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
 
+    // Specialization for fusion sequences, in this case we check whether the
+    // lhs attribute is convertible to the types in the sequence.
+    // We return false if the rhs attribute itself is a fusion sequence.
+    template <typename RHS, typename LHSAttribute>
+    struct has_same_elements<RHS, LHSAttribute, false, true>
+    {
+        typedef typename mpl::find_if<
+            LHSAttribute, mpl::not_<is_convertible<RHS, mpl::_1> >
+        >::type iter;
+        typedef typename mpl::end<LHSAttribute>::type end;
+
+        typedef typename is_same<iter, end>::type type;
+    };
+
     ///////////////////////////////////////////////////////////////////////////
     // This function handles the case where the attribute (Attr) given
     // to the sequence is an STL container. This is a wrapper around F.
@@ -73,18 +96,34 @@
           : f(f), iter(begin), end(end) 
         {}
 
+        bool is_at_end() const
+        {
+            return traits::compare(iter, end);
+        }
+
+        void next()
+        {
+            traits::next(iter);
+        }
+
         // this is for the case when the current element expects an attribute
         // which is taken from the next entry in the container
         template <typename Component>
         bool dispatch_attribute_element(Component const& component, mpl::false_) const
         {
             // get the next value to generate from container
-            if (!traits::compare(iter, end) && !f(component, traits::deref(iter))) 
+            if (!is_at_end() && !f(component, traits::deref(iter))) 
             {
                 // needs to return false as long as everything is ok
                 traits::next(iter);
                 return false;
             }
+
+//             // in non-strict mode increment iterator if the underlying 
+//             // generator failed
+//             if (!Strict::value && !is_at_end())
+//                 traits::next(iter);
+
             // either no elements available any more or generation failed
             return true;
         }
@@ -180,6 +219,14 @@
         // silence MSVC warning C4512: assignment operator could not be generated
         pass_container& operator= (pass_container const&);
     };
+
+    // Utility function to make a pass_container
+    template <typename Strict, typename F, typename Attr, typename Iterator>
+    pass_container<F, Attr, Iterator, Strict>
+    inline make_pass_container(F const& f, Attr& attr, Iterator b, Iterator e)
+    {
+        return pass_container<F, Attr, Iterator, Strict>(f, attr, b, e);
+    }
 }}}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/numeric/bool.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/bool.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/bool.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -312,7 +312,8 @@
     template <typename T, typename Policies, typename Modifiers>
     struct make_primitive<
             tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
-      : detail::make_bool<Modifiers, T, Policies> {};
+      : detail::make_bool<Modifiers
+          , typename remove_const<T>::type, Policies> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -356,7 +357,8 @@
         terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
           , fusion::vector1<A0> >
           , Modifiers>
-      : detail::make_bool_direct<Modifiers, T, Policies> {};
+      : detail::make_bool_direct<Modifiers
+          , typename remove_const<T>::type, Policies> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
Modified: trunk/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/int.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/int.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -378,7 +378,8 @@
 
     template <typename T, unsigned Radix, bool force_sign, typename Modifiers>
     struct make_primitive<tag::int_generator<T, Radix, force_sign>, Modifiers>
-      : detail::make_int<T, Modifiers, Radix, force_sign> {};
+      : detail::make_int<typename remove_const<T>::type
+          , Modifiers, Radix, force_sign> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -436,7 +437,8 @@
     struct make_primitive<
         terminal_ex<tag::int_generator<T, Radix, force_sign>
           , fusion::vector1<A0> >, Modifiers>
-      : detail::make_int_direct<T, Modifiers, Radix, force_sign> {};
+      : detail::make_int_direct<typename remove_const<T>::type
+          , Modifiers, Radix, force_sign> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -489,7 +491,6 @@
             terminal_ex<tag::lit, fusion::vector1<A0> >
           , Modifiers
           , typename enable_if<traits::is_int<A0> >::type>
-      : detail::basic_int_literal<A0, Modifiers> 
     {
         static bool const lower =
             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -497,7 +498,7 @@
             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
 
         typedef literal_int_generator<
-            A0
+            typename remove_const<A0>::type
           , typename spirit::detail::get_encoding_with_case<
                 Modifiers, unused_type, lower || upper>::type
           , typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -322,7 +322,8 @@
     template <typename T, typename Policies, typename Modifiers>
     struct make_primitive<
             tag::stateful_tag<Policies, tag::double_, T>, Modifiers> 
-      : detail::make_real<T, Modifiers, Policies> {};
+      : detail::make_real<typename remove_const<T>::type
+          , Modifiers, Policies> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -376,7 +377,8 @@
         terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
           , fusion::vector1<A0> >
           , Modifiers>
-      : detail::make_real_direct<T, Modifiers, Policies> {};
+      : detail::make_real_direct<typename remove_const<T>::type
+          , Modifiers, Policies> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -423,7 +425,6 @@
             terminal_ex<tag::lit, fusion::vector1<A0> >
           , Modifiers
           , typename enable_if<traits::is_real<A0> >::type>
-      : detail::basic_real_literal<A0, Modifiers> 
     {
         static bool const lower =
             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -431,7 +432,7 @@
             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
 
         typedef literal_real_generator<
-            A0, real_policies<A0>
+            typename remove_const<A0>::type, real_policies<A0>
           , typename spirit::detail::get_encoding_with_case<
                 Modifiers, unused_type, lower || upper>::type
           , typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/numeric/uint.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/uint.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/uint.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -417,7 +417,7 @@
 
     template <typename T, unsigned Radix, typename Modifiers>
     struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
-      : detail::make_uint<T, Modifiers, Radix> {};
+      : detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -487,7 +487,8 @@
     struct make_primitive<
         terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
           , Modifiers>
-      : detail::make_uint_direct<T, Modifiers, Radix> {};
+      : detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix> 
+    {};
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
@@ -542,7 +543,6 @@
             terminal_ex<tag::lit, fusion::vector1<A0> >
           , Modifiers
           , typename enable_if<traits::is_uint<A0> >::type>
-      : detail::basic_uint_literal<A0, Modifiers> 
     {
         static bool const lower =
             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -550,7 +550,7 @@
             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
 
         typedef literal_uint_generator<
-            A0
+            typename remove_const<A0>::type
           , typename spirit::detail::get_encoding_with_case<
                 Modifiers, unused_type, lower || upper>::type
           , typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/kleene.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/kleene.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,7 +15,10 @@
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/meta_compiler.hpp>
 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -41,29 +44,39 @@
     struct base_kleene : unary_generator<Derived>
     {
     private:
-        template <
-            typename OutputIterator, typename Context, typename Delimiter
-          , typename Attribute>
-        bool generate_subject(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, Attribute const& attr) const
+        // Ignore return value in relaxed mode (failing subject generators 
+        // are just skipped). This allows to selectively generate items in 
+        // the provided attribute.
+        template <typename F, typename Attribute>
+        bool generate_subject(F f, Attribute const&, mpl::false_) const
+        {
+            bool r = !f(subject);
+            if (!r && !f.is_at_end())
+                f.next();
+            return true;
+        }
+
+        template <typename F, typename Attribute>
+        bool generate_subject(F f, Attribute const&, mpl::true_) const
         {
-            // Ignore return value, failing subject generators are just 
-            // skipped. This allows to selectively generate items in the 
-            // provided attribute.
-            bool r = subject.generate(sink, ctx, d, attr);
-            return !Strict::value || r;
+            return !f(subject);
         }
 
-        template <typename OutputIterator, typename Context, typename Delimiter>
-        bool generate_subject(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, unused_type) const
+        // There is no way to distinguish a failed generator from a 
+        // generator to be skipped. We assume the user takes responsibility 
+        // for ending the loop if no attribute is specified.
+        template <typename F>
+        bool generate_subject(F f, unused_type, mpl::false_) const
         {
-            // There is no way to distinguish a failed generator from a 
-            // generator to be skipped. We assume the user takes responsibility
-            // for ending the loop if no attribute is specified.
-            return subject.generate(sink, ctx, d, unused);
+            return !f(subject);
         }
 
+//         template <typename F>
+//         bool generate_subject(F f, unused_type, mpl::true_) const
+//         {
+//             return !f(subject);
+//         }
+
     public:
         typedef Subject subject_type;
         typedef typename subject_type::properties properties;
@@ -87,18 +100,28 @@
         bool generate(OutputIterator& sink, Context& ctx
           , Delimiter const& d, Attribute const& attr) const
         {
+            typedef detail::fail_function<
+                OutputIterator, Context, Delimiter> fail_function;
+
             typedef typename traits::container_iterator<
                 typename add_const<Attribute>::type
             >::type iterator_type;
+            typedef typename detail::make_indirect_iterator<iterator_type>::type 
+                indirect_iterator_type;
+            typedef detail::pass_container<
+                fail_function, Attribute, indirect_iterator_type, Strict>
+            pass_container;
 
             iterator_type it = traits::begin(attr);
             iterator_type end = traits::end(attr);
 
+            pass_container pass(fail_function(sink, ctx, d), 
+                indirect_iterator_type(it), indirect_iterator_type(end));
+
             // kleene fails only if the underlying output fails
-            for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end); 
-                 traits::next(it))
+            while (!pass.is_at_end())
             {
-                if (!generate_subject(sink, ctx, d, traits::deref(it)))
+                if (!generate_subject(pass, attr, Strict()))
                     break;
             }
             return detail::sink_is_good(sink);
@@ -170,13 +193,13 @@
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::kleene<Subject>, Attribute
-      , Context, Iterator> 
+          , Context, Iterator> 
       : mpl::true_ {};
 
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::strict_kleene<Subject>, Attribute
-      , Context, Iterator> 
+          , Context, Iterator> 
       : mpl::true_ {};
 }}}
 
Modified: trunk/boost/spirit/home/karma/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/list.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/list.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,7 +15,10 @@
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/meta_compiler.hpp>
 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -41,39 +44,35 @@
     private:
         // iterate over the given container until its exhausted or the embedded
         // (left) generator succeeds
-        template <
-            typename OutputIterator, typename Context, typename Delimiter
-          , typename Iterator, typename Attribute>
-        bool generate_left(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, Iterator& it, Iterator& end, Attribute const&) const
+        template <typename F, typename Attribute>
+        bool generate_left(F f, Attribute const&, mpl::false_) const
         {
-            if (Strict::value) {
-                if (!traits::compare(it, end))
-                    return left.generate(sink, ctx, d, traits::deref(it));
-            }
-            else {
-                // Failing subject generators are just skipped. This allows to 
-                // selectively generate items in the provided attribute.
-                while (!traits::compare(it, end))
-                {
-                    if (left.generate(sink, ctx, d, traits::deref(it)))
-                        return true;
-                    traits::next(it);
-                }
+            // Failing subject generators are just skipped. This allows to 
+            // selectively generate items in the provided attribute.
+            while (!f.is_at_end())
+            {
+                bool r = !f(left);
+                if (r) 
+                    return true;
+                if (!f.is_at_end())
+                    f.next();
             }
             return false;
         }
 
-        template <
-            typename OutputIterator, typename Context, typename Delimiter
-          , typename Iterator>
-        bool generate_left(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, Iterator&, Iterator&, unused_type) const
+        template <typename F, typename Attribute>
+        bool generate_left(F f, Attribute const&, mpl::true_) const
+        {
+            return !f(left);
+        }
+
+        // There is no way to distinguish a failed generator from a 
+        // generator to be skipped. We assume the user takes responsibility
+        // for ending the loop if no attribute is specified.
+        template <typename F>
+        bool generate_left(F f, unused_type, mpl::false_) const
         {
-            // There is no way to distinguish a failed generator from a 
-            // generator to be skipped. We assume the user takes responsibility
-            // for ending the loop if no attribute is specified.
-            return left.generate(sink, ctx, d, unused);
+            return !f(left);
         }
 
     public:
@@ -106,16 +105,29 @@
         bool generate(OutputIterator& sink, Context& ctx
           , Delimiter const& d, Attribute const& attr) const
         {
+            typedef detail::fail_function<
+                OutputIterator, Context, Delimiter
+            > fail_function;
+
             typedef typename traits::container_iterator<
                 typename add_const<Attribute>::type
             >::type iterator_type;
+            typedef 
+                typename detail::make_indirect_iterator<iterator_type>::type 
+            indirect_iterator_type;
+            typedef detail::pass_container<
+                fail_function, Attribute, indirect_iterator_type, Strict>
+            pass_container;
 
             iterator_type it = traits::begin(attr);
             iterator_type end = traits::end(attr);
 
-            if (generate_left(sink, ctx, d, it, end, attr))
+            pass_container pass(fail_function(sink, ctx, d), 
+                indirect_iterator_type(it), indirect_iterator_type(end));
+
+            if (generate_left(pass, attr, Strict()))
             {
-                for (traits::next(it); !traits::compare(it, end); traits::next(it))
+                while (!pass.is_at_end())
                 {
                     // wrap the given output iterator as generate_left might fail
                     detail::enable_buffering<OutputIterator> buffering(sink);
@@ -125,7 +137,7 @@
                         if (!right.generate(sink, ctx, d, unused))
                             return false;     // shouldn't happen
 
-                        if (!generate_left(sink, ctx, d, it, end, attr))
+                        if (!generate_left(pass, attr, Strict()))
                             break;            // return true as one item succeeded
                     }
                     buffering.buffer_copy();
@@ -203,13 +215,13 @@
     template <typename Left, typename Right, typename Attribute
       , typename Context, typename Iterator>
     struct handles_container<karma::list<Left, Right>, Attribute
-      , Context, Iterator> 
+          , Context, Iterator> 
       : mpl::true_ {};
 
     template <typename Left, typename Right, typename Attribute
       , typename Context, typename Iterator>
     struct handles_container<karma::strict_list<Left, Right>, Attribute
-      , Context, Iterator> 
+          , Context, Iterator> 
       : mpl::true_ {};
 }}}
 
Modified: trunk/boost/spirit/home/karma/operator/optional.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/optional.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/optional.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -98,8 +98,8 @@
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::optional<Subject>, Attribute, Context
-      , Iterator>
-      : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+          , Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/plus.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/plus.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -14,8 +14,11 @@
 #include <boost/spirit/home/karma/domain.hpp>
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/meta_compiler.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -42,36 +45,50 @@
     struct base_plus : unary_generator<Derived>
     {
     private:
-        template <
-            typename OutputIterator, typename Context, typename Delimiter
-          , typename Attribute>
-        bool generate_subject(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, Attribute const& attr, bool& result) const
+        // Ignore return value in relaxed mode (failing subject generators 
+        // are just skipped). This allows to selectively generate items in 
+        // the provided attribute.
+        template <typename F, typename Attribute>
+        bool generate_subject(F f, Attribute const& attr, bool& result, mpl::false_) const
         {
-            // Ignore return value, failing subject generators are just 
-            // skipped. This allows to selectively generate items in the 
-            // provided attribute.
-            if (subject.generate(sink, ctx, d, attr)) {
+            bool r = !f(subject);
+            if (r) 
                 result = true;
-                return true;
-            }
-            return !Strict::value;
+            else if (!f.is_at_end())
+                f.next();
+            return true;
         }
 
-        template <typename OutputIterator, typename Context, typename Delimiter>
-        bool generate_subject(OutputIterator& sink, Context& ctx
-          , Delimiter const& d, unused_type, bool& result) const
+        template <typename F, typename Attribute>
+        bool generate_subject(F f, Attribute const& attr, bool& result, mpl::true_) const
         {
-            // There is no way to distinguish a failed generator from a 
-            // generator to be skipped. We assume the user takes responsibility
-            // for ending the loop if no attribute is specified.
-            if (subject.generate(sink, ctx, d, unused)) {
+            bool r = !f(subject);
+            if (r)
                 result = true;
-                return true;
-            }
-            return false;
+            return r;
+        }
+
+        // There is no way to distinguish a failed generator from a 
+        // generator to be skipped. We assume the user takes responsibility
+        // for ending the loop if no attribute is specified.
+        template <typename F>
+        bool generate_subject(F f, unused_type, bool& result, mpl::false_) const
+        {
+            bool r = f(subject);
+            if (!r)
+                result = true;
+            return !r;
         }
 
+//         template <typename F>
+//         bool generate_subject(F f, unused_type, bool& result, mpl::true_) const
+//         {
+//             bool r = f(subject);
+//             if (!r)
+//                 result = true;
+//             return !r;
+//         }
+
     public:
         typedef Subject subject_type;
         typedef typename subject_type::properties properties;
@@ -95,9 +112,17 @@
         bool generate(OutputIterator& sink, Context& ctx
           , Delimiter const& d, Attribute const& attr) const
         {
+            typedef detail::fail_function<
+                OutputIterator, Context, Delimiter> fail_function;
+
             typedef typename traits::container_iterator<
                 typename add_const<Attribute>::type
             >::type iterator_type;
+            typedef typename detail::make_indirect_iterator<iterator_type>::type 
+                indirect_iterator_type;
+            typedef detail::pass_container<
+                fail_function, Attribute, indirect_iterator_type, Strict>
+            pass_container;
 
             iterator_type it = traits::begin(attr);
             iterator_type end = traits::end(attr);
@@ -106,13 +131,15 @@
             if (traits::compare(it, end))
                 return false;
 
+            pass_container pass(fail_function(sink, ctx, d), 
+                indirect_iterator_type(it), indirect_iterator_type(end));
+
             // from now on plus fails if the underlying output fails or overall
             // no subject generators succeeded
             bool result = false;
-            for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end); 
-                 traits::next(it))
+            while (!pass.is_at_end())
             {
-                if (!generate_subject(sink, ctx, d, traits::deref(it), result))
+                if (!generate_subject(pass, attr, result, Strict()))
                     break;
             }
             return result && detail::sink_is_good(sink);
@@ -184,14 +211,14 @@
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::plus<Subject>, Attribute
-      , Context, Iterator>
-      : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+          , Context, Iterator>
+      : mpl::true_ {};
 
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::strict_plus<Subject>, Attribute
-      , Context, Iterator>
-      : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+          , Context, Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -20,6 +20,7 @@
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/detail/what_function.hpp>
 #include <boost/spirit/home/karma/detail/attributes.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
 #include <boost/spirit/home/support/algorithm/any_if.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/sequence_base_id.hpp>
@@ -83,83 +84,11 @@
           , mpl::bitor_<mpl::_2, mpl::_1>
         >::type type;
     };
-
 }}}
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
-    namespace detail
-    {
-
-        ///////////////////////////////////////////////////////////////////////
-        // This is a wrapper for any iterator allowing to pass a reference of it
-        // to the components of the sequence
-        template <typename Iterator>
-        class indirect_iterator
-          : public boost::iterator_facade<
-                indirect_iterator<Iterator>
-              , typename boost::detail::iterator_traits<Iterator>::value_type
-              , boost::forward_traversal_tag
-              , typename boost::detail::iterator_traits<Iterator>::value_type const&>
-        {
-            typedef typename boost::detail::iterator_traits<Iterator>::value_type
-                base_value_type;
-
-            typedef boost::iterator_facade<
-                indirect_iterator<Iterator>, base_value_type
-              , boost::forward_traversal_tag, base_value_type const&
-            > base_type;
-
-        public:
-            indirect_iterator(Iterator& iter)
-              : iter_(&iter)
-            {}
-            indirect_iterator(indirect_iterator const& iter)
-              : iter_(iter.iter_)
-            {}
-
-        private:
-            friend class boost::iterator_core_access;
-
-            void increment()
-            {
-                ++*iter_;
-            }
-
-            bool equal(indirect_iterator const& other) const
-            {
-                return *iter_ == *other.iter_;
-            }
-
-            typename base_type::reference dereference() const
-            {
-                return **iter_;
-            }
-
-        private:
-            Iterator* iter_;
-        };
-
-        template <typename Iterator>
-        struct make_indirect_iterator
-        {
-            typedef indirect_iterator<Iterator> type;
-        };
-
-        template <typename Iterator>
-        struct make_indirect_iterator<indirect_iterator<Iterator> >
-        {
-            typedef indirect_iterator<Iterator> type;
-        };
-
-        template <>
-        struct make_indirect_iterator<unused_type const*>
-        {
-            typedef unused_type const* type;
-        };
-    }
-
     template <typename Elements, typename Strict, typename Derived>
     struct base_sequence : nary_generator<Derived>
     {
@@ -365,14 +294,14 @@
     template <typename Elements, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::sequence<Elements>, Attribute, Context
-      , Iterator>
-      : nary_handles_container<Elements, Attribute, Context, Iterator> {};
-    
+          , Iterator>
+      : mpl::true_ {};
+
     template <typename Elements, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<karma::strict_sequence<Elements>, Attribute
-      , Context, Iterator>
-      : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+          , Context, Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/stream/stream.hpp	(original)
+++ trunk/boost/spirit/home/karma/stream/stream.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -113,7 +113,7 @@
         template <typename Context, typename Unused = unused_type>
         struct attribute
         {
-            typedef spirit::hold_any type;
+            typedef spirit::basic_hold_any<Char> type;
         };
 
         // any_stream_generator has an attached attribute 
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	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -227,9 +227,9 @@
     namespace detail
     {
         // overload for non-container attributes
-        template <typename T, typename Attribute, typename P1, typename P2>
+        template <typename T, typename Attribute>
         inline void
-        assign_to(T const& val, Attribute& attr, P1, P2)
+        assign_to(T const& val, Attribute& attr, mpl::false_)
         {
             assign_to_attribute_from_value<Attribute, T>::call(val, attr);
         }
@@ -238,7 +238,7 @@
         // holding containers)
         template <typename T, typename Attribute>
         inline void
-        assign_to(T const& val, Attribute& attr, mpl::true_, mpl::true_)
+        assign_to(T const& val, Attribute& attr, mpl::true_)
         {
             assign_to_container_from_value<Attribute, T>::call(val, attr);
         }
@@ -248,13 +248,13 @@
     inline void
     assign_to(T const& val, Attribute& attr)
     {
-        typedef typename traits::is_container<Attribute>::type is_container;
         typedef typename mpl::and_<
-            traits::not_is_variant<Attribute>
+            traits::is_container<Attribute>
+          , traits::not_is_variant<Attribute>
           , traits::not_is_optional<Attribute> 
         >::type is_not_wrapped_container;
 
-        detail::assign_to(val, attr, is_container(), is_not_wrapped_container());
+        detail::assign_to(val, attr, is_not_wrapped_container());
     }
 
     template <typename T>
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -26,15 +26,24 @@
     // to the LHS.
 
     template <typename LHS, typename RHSAttribute
-      , bool IsContainer = traits::is_container<RHSAttribute>::value>
+      , 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>
+    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, optional<T>, true>
+    struct has_same_elements<LHS, optional<T>, false, false>
+      : has_same_elements<LHS, T> {};
+
+    template <typename LHS, typename T>
+    struct has_same_elements<LHS, optional<T>, true, false>
+      : has_same_elements<LHS, T> {};
+
+    template <typename LHS, typename T>
+    struct has_same_elements<LHS, optional<T>, false, true>
       : has_same_elements<LHS, T> {};
 
 #define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data)                               \
@@ -45,12 +54,28 @@
     //       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>
+            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
 
+    // 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>
+    {
+        typedef typename mpl::find_if<
+            RHSAttribute, mpl::not_<is_convertible<mpl::_1, LHS> >
+        >::type iter;
+        typedef typename mpl::end<RHSAttribute>::type end;
+
+        typedef typename mpl::and_<
+            mpl::not_<fusion::traits::is_sequence<LHS> >, is_same<iter, end>
+        >::type type;
+    };
+
     // 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.
@@ -163,6 +188,9 @@
                                         , iterator_type> 
             > predicate;
 
+//             // ensure the attribute is actually a container type
+//             traits::make_container(attr);
+
             return dispatch_main(component, predicate());
         }
 
Modified: trunk/boost/spirit/home/qi/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/directive/repeat.hpp	(original)
+++ trunk/boost/spirit/home/qi/directive/repeat.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -18,11 +19,12 @@
 #include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/support/common_terminals.hpp>
 #include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/has_semantic_action.hpp>
 #include <boost/spirit/home/support/handles_container.hpp>
 #include <boost/fusion/include/at.hpp>
-#include <boost/foreach.hpp>
 #include <vector>
 
 namespace boost { namespace spirit
@@ -152,57 +154,26 @@
         repeat_parser(Subject const& subject, LoopIter const& iter)
           : subject(subject), iter(iter) {}
 
-        template <typename Iterator, typename Context
-          , typename Skipper, typename ValueType, typename Attribute
-          , typename LoopVar>
-        bool parse_minimal(Iterator &first, Iterator const& last
-          , Context& context, Skipper const& skipper
-          , Attribute& attr, ValueType& val, LoopVar& i) const
+        template <typename F>
+        bool parse_container(F f) const
         {
-            // this scope allows save and required_attr to be reclaimed 
-            // immediately after we're done with the required minimum 
-            // iteration.
-            Iterator save = first;
-            std::vector<ValueType> required_attr;
-            for (; !iter.got_min(i); ++i)
+            typename LoopIter::type i = iter.start();
+            for (/**/; !iter.got_min(i); ++i) 
             {
-                if (!subject.parse(save, last, context, skipper, val) ||
-                    !traits::push_back(required_attr, val))
-                {
+                if (f (subject))
                     return false;
-                }
-
-                first = save;
-                traits::clear(val);
             }
 
-            // if we got the required number of items, these are copied 
-            // over (appended) to the 'real' attribute
-            BOOST_FOREACH(ValueType const& v, required_attr)
+            // parse some more up to the maximum specified
+            typename F::iterator_type save = f.f.first;
+            for (/**/; !iter.got_max(i); ++i) 
             {
-                traits::push_back(attr, v);
+                if (f (subject))
+                    break;
+                save = f.f.first;
             }
-            return true;
-        }
 
-        template <typename Iterator, typename Context
-          , typename Skipper, typename LoopVar>
-        bool parse_minimal(Iterator &first, Iterator const& last
-          , Context& context, Skipper const& skipper
-          , unused_type, unused_type, LoopVar& i) const
-        {
-            // this scope allows save and required_attr to be reclaimed 
-            // immediately after we're done with the required minimum 
-            // iteration.
-            Iterator save = first;
-            for (; !iter.got_min(i); ++i)
-            {
-                if (!subject.parse(save, last, context, skipper, unused))
-                {
-                    return false;
-                }
-                first = save;
-            }
+            f.f.first = save;
             return true;
         }
 
@@ -212,35 +183,18 @@
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
-            // create a local value if Attribute is not unused_type
-            typedef typename traits::container_value<Attribute>::type 
-                value_type;
-            value_type val = value_type();
-            typename LoopIter::type i = iter.start();
+            typedef detail::fail_function<Iterator, Context, Skipper>
+                fail_function;
 
             // ensure the attribute is actually a container type
             traits::make_container(attr);
 
-            // parse the minimum required
-            Iterator save = first;
-            if (!iter.got_min(i) &&
-                !parse_minimal(save, last, context, skipper, attr, val, i))
-            {
+            Iterator iter = first;
+            fail_function f(iter, last, context, skipper);
+            if (!parse_container(detail::make_pass_container(f, attr)))
                 return false;
-            }
-
-            // parse some more up to the maximum specified
-            for (/**/; !iter.got_max(i); ++i) {
-                if (!subject.parse(save, last, context, skipper, val) ||
-                    !traits::push_back(attr, val))
-                {
-                    break;
-                }
-                first = save;
-                traits::clear(val);
-            }
 
-            first = save;
+            first = f.first;
             return true;
         }
 
@@ -334,7 +288,7 @@
     template <typename Subject, typename LoopIter, typename Attribute
       , typename Context, typename Iterator>
     struct handles_container<qi::repeat_parser<Subject, LoopIter>
-      , Attribute, Context, Iterator>
+          , Attribute, Context, Iterator>
       : mpl::true_ {};
 }}}
 
Modified: trunk/boost/spirit/home/qi/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/numeric/int.hpp	(original)
+++ trunk/boost/spirit/home/qi/numeric/int.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -56,7 +56,7 @@
         , terminal_ex<tag::lit, fusion::vector1<A0> > 
         , typename enable_if<is_same<A0, signed short> >::type>
       : mpl::true_ {};
-  
+
     template <typename A0> // enables short_(n)
     struct use_terminal<qi::domain
         , terminal_ex<tag::short_, fusion::vector1<A0> > >
@@ -69,7 +69,7 @@
     //[primitive_parsers_enable_int
     template <> // enables int_
     struct use_terminal<qi::domain, tag::int_> : mpl::true_ {};
-    //]   
+    //]
 
     template <typename A0> // enables lit(n)
     struct use_terminal<qi::domain
@@ -84,13 +84,13 @@
 
     template <> // enables *lazy* int_(n)
     struct use_lazy_terminal<qi::domain, tag::int_, 1> : mpl::true_ {};
- 
+
     ///////////////////////////////////////////////////////////////////////////
     //[primitive_parsers_enable_long
     template <> // enables long_
     struct use_terminal<qi::domain, tag::long_> : mpl::true_ {};
-    //]   
-   
+    //]
+
     template <typename A0> // enables lit(n)
     struct use_terminal<qi::domain
         , terminal_ex<tag::lit, fusion::vector1<A0> > 
@@ -104,7 +104,7 @@
 
     template <> // enables *lazy* long_(n)
     struct use_lazy_terminal<qi::domain, tag::long_, 1> : mpl::true_ {};
- 
+
     ///////////////////////////////////////////////////////////////////////////
 #ifdef BOOST_HAS_LONG_LONG
     //[primitive_parsers_enable_long_long
@@ -236,7 +236,7 @@
         {
             typedef extract_int<T, Radix, MinDigits, MaxDigits> extract;
             qi::skip_over(first, last, skipper);
-           
+
             Iterator save = first; 
             T attr_;
 
@@ -277,7 +277,7 @@
         }
     };
     //]
-    
+
     template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
             , int MaxDigits = -1>
     struct make_direct_int
@@ -290,7 +290,7 @@
             return result_type(fusion::at_c<0>(term.args));
         }
     };
-    
+
     template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
             , int MaxDigits = -1>
     struct make_literal_int
@@ -302,7 +302,7 @@
             return result_type(fusion::at_c<0>(term.args));
         }
     };
-    
+
     ///////////////////////////////////////////////////////////////////////////
     template <typename Modifiers, typename A0>
     struct make_primitive<
Modified: trunk/boost/spirit/home/qi/operator/expect.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/expect.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/expect.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -95,8 +96,8 @@
     template <typename Elements, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<qi::expect<Elements>, Attribute, Context
-      , Iterator>
-      : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+          , Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/qi/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/kleene.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/kleene.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -15,6 +16,8 @@
 #include <boost/spirit/home/qi/parser.hpp>
 #include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
 #include <boost/spirit/home/support/has_semantic_action.hpp>
 #include <boost/spirit/home/support/handles_container.hpp>
 #include <boost/spirit/home/support/info.hpp>
@@ -33,7 +36,6 @@
 
 namespace boost { namespace spirit { namespace qi
 {
-
     //[composite_parsers_kleene
     template <typename Subject>
     struct kleene : unary_parser<kleene<Subject> >
@@ -57,28 +59,31 @@
         kleene(Subject const& subject)
           : subject(subject) {}
 
+        template <typename F>
+        bool parse_container(F f) const
+        {
+            while (!f (subject))
+                ;
+            return true;
+        }
+
         template <typename Iterator, typename Context
           , typename Skipper, typename Attribute>
         bool parse(Iterator& first, Iterator const& last
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
-            // create a local value if Attribute is not unused_type
-            typedef typename traits::container_value<Attribute>::type 
-                value_type;
-            value_type val = value_type();
-
             // ensure the attribute is actually a container type
             traits::make_container(attr);
 
-            // Repeat while subject parses ok
-            Iterator save = first;
-            while (subject.parse(save, last, context, skipper, val) &&
-                   traits::push_back(attr, val))    // push the parsed value into our attribute
-            {
-                first = save;
-                traits::clear(val);
-            }
+            typedef detail::fail_function<Iterator, Context, Skipper>
+                fail_function;
+
+            Iterator iter = first;
+            fail_function f(iter, last, context, skipper);
+            parse_container(detail::make_pass_container(f, attr));
+
+            first = f.first;
             return true;
         }
 
@@ -120,9 +125,9 @@
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename Subject, typename Attribute, typename Context
-        , typename Iterator>
+      , typename Iterator>
     struct handles_container<qi::kleene<Subject>, Attribute
-        , Context, Iterator>
+          , Context, Iterator>
       : mpl::true_ {}; 
 }}}
 
Modified: trunk/boost/spirit/home/qi/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/list.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/list.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -15,6 +16,8 @@
 #include <boost/spirit/home/qi/parser.hpp>
 #include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
 #include <boost/spirit/home/support/has_semantic_action.hpp>
 #include <boost/spirit/home/support/handles_container.hpp>
 #include <boost/spirit/home/support/info.hpp>
@@ -55,36 +58,42 @@
         list(Left const& left, Right const& right)
           : left(left), right(right) {}
 
+        template <typename F>
+        bool parse_container(F f) const
+        {
+            // in order to succeed we need to match at least one element 
+            if (f (left))
+                return false;
+
+            typename F::iterator_type save = f.f.first;
+            while (right.parse(f.f.first, f.f.last, f.f.context, f.f.skipper, unused)
+              && !f (left))
+            {
+                save = f.f.first;
+            }
+
+            f.f.first = save;
+            return true;
+        }
+
         template <typename Iterator, typename Context
           , typename Skipper, typename Attribute>
         bool parse(Iterator& first, Iterator const& last
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
-            // create a local value if Attribute is not unused_type
-            typedef typename traits::container_value<Attribute>::type 
-                value_type;
-            value_type val = value_type();
+            typedef detail::fail_function<Iterator, Context, Skipper>
+                fail_function;
 
             // ensure the attribute is actually a container type
             traits::make_container(attr);
 
-            Iterator save = first;
-            if (!left.parse(save, last, context, skipper, val) ||
-                !traits::push_back(attr, val))
-            {
+            Iterator iter = first;
+            fail_function f(iter, last, context, skipper);
+            if (!parse_container(detail::make_pass_container(f, attr)))
                 return false;
-            }
-            first = save;
 
-            while (right.parse(save, last, context, skipper, unused)
-             && (traits::clear(val), true)
-             && left.parse(save, last, context, skipper, val))
-            {
-                if (!traits::push_back(attr, val))
-                    break;
-                first = save;
-            }
+            first = f.first;
             return true;
         }
 
@@ -119,7 +128,7 @@
     template <typename Left, typename Right, typename Attribute
       , typename Context, typename Iterator>
     struct handles_container<qi::list<Left, Right>, Attribute, Context
-      , Iterator> 
+          , Iterator> 
       : mpl::true_ {};
 }}}
 
Modified: trunk/boost/spirit/home/qi/operator/optional.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/optional.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/optional.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -16,6 +17,7 @@
 #include <boost/spirit/home/support/has_semantic_action.hpp>
 #include <boost/spirit/home/support/handles_container.hpp>
 #include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/qi/parser.hpp>
 #include <boost/spirit/home/qi/meta_compiler.hpp>
 #include <boost/spirit/home/qi/detail/assign_to.hpp>
@@ -58,9 +60,9 @@
 
         template <typename Iterator, typename Context
           , typename Skipper, typename Attribute>
-        bool parse(Iterator& first, Iterator const& last
+        bool parse_impl(Iterator& first, Iterator const& last
           , Context& context, Skipper const& skipper
-          , Attribute& attr) const
+          , Attribute& attr, mpl::false_) const
         {
             // create a local value if Attribute is not unused_type
             typename spirit::result_of::optional_value<Attribute>::type val;
@@ -73,6 +75,29 @@
             return true;
         }
 
+        template <typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        bool parse_impl(Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr, mpl::true_) const
+        {
+            subject.parse(first, last, context, skipper, attr);
+            return true;
+        }
+
+        template <typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        bool parse(Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr) const
+        {
+            typedef typename spirit::result_of::optional_value<Attribute>::type 
+                attribute_type;
+
+            return parse_impl(first, last, context, skipper, attr
+              , traits::is_container<attribute_type>());
+        }
+
         template <typename Context>
         info what(Context& context) const
         {
@@ -102,8 +127,8 @@
     template <typename Subject, typename Attribute, typename Context
         , typename Iterator>
     struct handles_container<qi::optional<Subject>, Attribute
-        , Context, Iterator>
-      : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+          , Context, Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/qi/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/plus.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/plus.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -15,6 +16,8 @@
 #include <boost/spirit/home/qi/parser.hpp>
 #include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
 #include <boost/spirit/home/support/has_semantic_action.hpp>
 #include <boost/spirit/home/support/handles_container.hpp>
 #include <boost/spirit/home/support/info.hpp>
@@ -53,37 +56,36 @@
         plus(Subject const& subject)
           : subject(subject) {}
 
+        template <typename F>
+        bool parse_container(F f) const
+        {
+            // in order to succeed we need to match at least one element 
+            if (f (subject))
+                return false;
+
+            while (!f (subject))
+                ;
+            return true;
+        }
+
         template <typename Iterator, typename Context
           , typename Skipper, typename Attribute>
         bool parse(Iterator& first, Iterator const& last
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
-            // create a local value if Attribute is not unused_type
-            typedef typename traits::container_value<Attribute>::type 
-                value_type;
-            value_type val = value_type();
+            typedef detail::fail_function<Iterator, Context, Skipper>
+                fail_function;
 
             // ensure the attribute is actually a container type
             traits::make_container(attr);
 
-            Iterator save = first;
-            if (!subject.parse(save, last, context, skipper, val) ||
-                !traits::push_back(attr, val))
-            {
+            Iterator iter = first;
+            fail_function f(iter, last, context, skipper);
+            if (!parse_container(detail::make_pass_container(f, attr)))
                 return false;
-            }
-            first = save;
-            traits::clear(val);
-
-            while (subject.parse(save, last, context, skipper, val))
-            {
-                if (!traits::push_back(attr, val))
-                    break;
-
-                first = save;
-                traits::clear(val);
-            }
+
+            first = f.first;
             return true;
         }
 
@@ -116,7 +118,7 @@
     template <typename Subject, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<qi::plus<Subject>, Attribute, Context
-      , Iterator>
+          , Iterator>
       : mpl::true_ {}; 
 }}}
 
Modified: trunk/boost/spirit/home/qi/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/sequence.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/sequence.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
@@ -88,8 +89,8 @@
     template <typename Elements, typename Attribute, typename Context
       , typename Iterator>
     struct handles_container<qi::sequence<Elements>, Attribute, Context
-      , Iterator>
-      : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+          , Iterator>
+      : mpl::true_ {};
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/qi/operator/sequence_base.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/sequence_base.hpp	(original)
+++ trunk/boost/spirit/home/qi/operator/sequence_base.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
+    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)
Modified: trunk/boost/spirit/home/qi/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/stream/stream.hpp	(original)
+++ trunk/boost/spirit/home/qi/stream/stream.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -40,7 +40,7 @@
     using spirit::stream;
     using spirit::wstream;
 
-    template <typename Char = char, typename T = spirit::hold_any>
+    template <typename Char = char, typename T = spirit::basic_hold_any<char> >
     struct stream_parser
       : primitive_parser<stream_parser<Char, T> >
     {
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -45,6 +45,7 @@
 #include <boost/range/iterator_range.hpp>
 #include <vector>
 #include <utility>
+#include <ios>
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
@@ -115,7 +116,7 @@
 
         template <typename Container>
         struct is_hold_any_container
-          : is_same<hold_any, typename traits::container_value<Container>::type>
+          : traits::is_hold_any<typename traits::container_value<Container>::type>
         {};
     }
 
@@ -124,7 +125,7 @@
     struct compute_compatible_component_variant
       : mpl::or_<
             traits::detail::attribute_is_compatible<Expected, Attribute>
-          , is_same<hold_any, Expected>
+          , traits::is_hold_any<Expected>
           , mpl::eval_if<
                 is_container<Expected>
               , traits::detail::is_hold_any_container<Expected>
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -132,6 +132,9 @@
     template <typename Attribute, typename Exposed, typename Enable = void>
     struct extract_from_attribute;
 
+    template <typename Attribute, typename Exposed, typename Enable = void>
+    struct extract_from_container;
+
     template <typename Exposed, typename Attribute, typename Context>
     typename spirit::result_of::extract_from<Exposed, Attribute>::type
     extract_from(Attribute const& attr, Context& ctx
Modified: trunk/boost/spirit/home/support/container.hpp
==============================================================================
--- trunk/boost/spirit/home/support/container.hpp	(original)
+++ trunk/boost/spirit/home/support/container.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -70,7 +70,7 @@
     {};
 
 #undef BOOST_SPIRIT_IS_CONTAINER
-    
+
     template <typename T, typename Enable/* = void*/>
     struct is_iterator_range
       : mpl::false_
Modified: trunk/boost/spirit/home/support/detail/hold_any.hpp
==============================================================================
--- trunk/boost/spirit/home/support/detail/hold_any.hpp	(original)
+++ trunk/boost/spirit/home/support/detail/hold_any.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -58,6 +58,7 @@
     namespace detail
     {
         // function pointer table
+        template <typename Char>
         struct fxn_ptr_table
         {
             boost::detail::sp_typeinfo const& (*get_type)();
@@ -65,18 +66,18 @@
             void (*destruct)(void**);
             void (*clone)(void* const*, void**);
             void (*move)(void* const*, void**);
-            std::istream& (*stream_in)(std::istream&, void**);
-            std::ostream& (*stream_out)(std::ostream&, void* const*);
+            std::basic_istream<Char>& (*stream_in)(std::basic_istream<Char>&, void**);
+            std::basic_ostream<Char>& (*stream_out)(std::basic_ostream<Char>&, void* const*);
         };
 
         // static functions for small value-types
-        template<typename Small>
+        template <typename Small>
         struct fxns;
 
-        template<>
+        template <>
         struct fxns<mpl::true_>
         {
-            template<typename T>
+            template<typename T, typename Char>
             struct type
             {
                 static boost::detail::sp_typeinfo const& get_type()
@@ -101,12 +102,14 @@
                     *reinterpret_cast<T*>(dest) =
                         *reinterpret_cast<T const*>(src);
                 }
-                static std::istream& stream_in (std::istream& i, void** obj)
+                static std::basic_istream<Char>& 
+                stream_in (std::basic_istream<Char>& i, void** obj)
                 {
                     i >> *reinterpret_cast<T*>(obj);
                     return i;
                 }
-                static std::ostream& stream_out(std::ostream& o, void* const* obj)
+                static std::basic_ostream<Char>& 
+                stream_out(std::basic_ostream<Char>& o, void* const* obj)
                 {
                     o << *reinterpret_cast<T const*>(obj);
                     return o;
@@ -115,10 +118,10 @@
         };
 
         // static functions for big value-types (bigger than a void*)
-        template<>
+        template <>
         struct fxns<mpl::false_>
         {
-            template<typename T>
+            template<typename T, typename Char>
             struct type
             {
                 static boost::detail::sp_typeinfo const& get_type()
@@ -145,12 +148,14 @@
                     **reinterpret_cast<T**>(dest) =
                         **reinterpret_cast<T* const*>(src);
                 }
-                static std::istream& stream_in(std::istream& i, void** obj)
+                static std::basic_istream<Char>& 
+                stream_in(std::basic_istream<Char>& i, void** obj)
                 {
                     i >> **reinterpret_cast<T**>(obj);
                     return i;
                 }
-                static std::ostream& stream_out(std::ostream& o, void* const* obj)
+                static std::basic_ostream<Char>& 
+                stream_out(std::basic_ostream<Char>& o, void* const* obj)
                 {
                     o << **reinterpret_cast<T* const*>(obj);
                     return o;
@@ -158,22 +163,23 @@
             };
         };
 
-        template<typename T>
+        template <typename T>
         struct get_table
         {
             typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
 
-            static fxn_ptr_table* get()
+            template <typename Char>
+            static fxn_ptr_table<Char>* get()
             {
-                static fxn_ptr_table static_table =
+                static fxn_ptr_table<Char> static_table =
                 {
-                    fxns<is_small>::template type<T>::get_type,
-                    fxns<is_small>::template type<T>::static_delete,
-                    fxns<is_small>::template type<T>::destruct,
-                    fxns<is_small>::template type<T>::clone,
-                    fxns<is_small>::template type<T>::move,
-                    fxns<is_small>::template type<T>::stream_in,
-                    fxns<is_small>::template type<T>::stream_out
+                    fxns<is_small>::template type<T, Char>::get_type,
+                    fxns<is_small>::template type<T, Char>::static_delete,
+                    fxns<is_small>::template type<T, Char>::destruct,
+                    fxns<is_small>::template type<T, Char>::clone,
+                    fxns<is_small>::template type<T, Char>::move,
+                    fxns<is_small>::template type<T, Char>::stream_in,
+                    fxns<is_small>::template type<T, Char>::stream_out
                 };
                 return &static_table;
             }
@@ -207,13 +213,14 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    class hold_any
+    template <typename Char>
+    class basic_hold_any
     {
     public:
         // constructors
         template <typename T>
-        explicit hold_any(T const& x)
-          : table(spirit::detail::get_table<T>::get()), object(0)
+        explicit basic_hold_any(T const& x)
+          : table(spirit::detail::get_table<T>::template get<Char>()), object(0)
         {
             if (spirit::detail::get_table<T>::is_small::value)
                 new (&object) T(x);
@@ -221,26 +228,26 @@
                 object = new T(x);
         }
 
-        hold_any()
-          : table(spirit::detail::get_table<spirit::detail::empty>::get()),
+        basic_hold_any()
+          : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
             object(0)
         {
         }
 
-        hold_any(hold_any const& x)
-          : table(spirit::detail::get_table<spirit::detail::empty>::get()),
+        basic_hold_any(basic_hold_any const& x)
+          : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
             object(0)
         {
             assign(x);
         }
 
-        ~hold_any()
+        ~basic_hold_any()
         {
             table->static_delete(&object);
         }
 
         // assignment
-        hold_any& assign(hold_any const& x)
+        basic_hold_any& assign(basic_hold_any const& x)
         {
             if (&x != this) {
                 // are we copying between the same type?
@@ -258,11 +265,11 @@
         }
 
         template <typename T>
-        hold_any& assign(T const& x)
+        basic_hold_any& assign(T const& x)
         {
             // are we copying between the same type?
-            spirit::detail::fxn_ptr_table* x_table =
-                spirit::detail::get_table<T>::get();
+            spirit::detail::fxn_ptr_table<Char>* x_table =
+                spirit::detail::get_table<T>::template get<Char>();
             if (table == x_table) {
             // if so, we can avoid deallocating and re-use memory
                 table->destruct(&object);    // first destruct the old content
@@ -292,13 +299,13 @@
 
         // assignment operator
         template <typename T>
-        hold_any& operator=(T const& x)
+        basic_hold_any& operator=(T const& x)
         {
             return assign(x);
         }
 
         // utility functions
-        hold_any& swap(hold_any& x)
+        basic_hold_any& swap(basic_hold_any& x)
         {
             std::swap(table, x.table);
             std::swap(object, x.object);
@@ -330,7 +337,7 @@
 
         bool empty() const
         {
-            return table == spirit::detail::get_table<spirit::detail::empty>::get();
+            return table == spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
         }
 
         void reset()
@@ -338,7 +345,7 @@
             if (!empty())
             {
                 table->static_delete(&object);
-                table = spirit::detail::get_table<spirit::detail::empty>::get();
+                table = spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
                 object = 0;
             }
         }
@@ -347,31 +354,35 @@
     // type has a corresponding operator defined, which is completely safe
     // because spirit::hold_any is used only in contexts where these operators
     // do exist
-        friend std::istream& operator>> (std::istream& i, hold_any& obj)
+        template <typename Char_>
+        friend inline std::basic_istream<Char_>& 
+        operator>> (std::basic_istream<Char_>& i, basic_hold_any<Char_>& obj)
         {
             return obj.table->stream_in(i, &obj.object);
         }
 
-        friend std::ostream& operator<< (std::ostream& o, hold_any const& obj)
+        template <typename Char_>
+        friend inline std::basic_ostream<Char_>& 
+        operator<< (std::basic_ostream<Char_>& o, basic_hold_any<Char_> const& obj)
         {
             return obj.table->stream_out(o, &obj.object);
         }
 
 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
     private: // types
-        template<typename T>
-        friend T* any_cast(hold_any *);
+        template <typename T, typename Char_>
+        friend T* any_cast(basic_hold_any<Char_> *);
 #else
     public: // types (public so any_cast can be non-friend)
 #endif
         // fields
-        spirit::detail::fxn_ptr_table* table;
+        spirit::detail::fxn_ptr_table<Char>* table;
         void* object;
     };
 
     // boost::any-like casting
-    template <typename T>
-    inline T* any_cast (hold_any* operand)
+    template <typename T, typename Char>
+    inline T* any_cast (basic_hold_any<Char>* operand)
     {
         if (operand && operand->type() == BOOST_SP_TYPEID(T)) {
             return spirit::detail::get_table<T>::is_small::value ?
@@ -381,14 +392,14 @@
         return 0;
     }
 
-    template <typename T>
-    inline T const* any_cast(hold_any const* operand)
+    template <typename T, typename Char>
+    inline T const* any_cast(basic_hold_any<Char> const* operand)
     {
-        return any_cast<T>(const_cast<hold_any*>(operand));
+        return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
     }
 
-    template <typename T>
-    T any_cast(hold_any& operand)
+    template <typename T, typename Char>
+    T any_cast(basic_hold_any<Char>& operand)
     {
         typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
 
@@ -408,8 +419,8 @@
         return *result;
     }
 
-    template <typename T>
-    T const& any_cast(hold_any const& operand)
+    template <typename T, typename Char>
+    T const& any_cast(basic_hold_any<Char> const& operand)
     {
         typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
 
@@ -419,10 +430,23 @@
         BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
 #endif
 
-        return any_cast<nonref const&>(const_cast<hold_any &>(operand));
+        return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // backwards compatibility
+    typedef basic_hold_any<char> hold_any;
+    typedef basic_hold_any<wchar_t> whold_any;
+
+    namespace traits
+    {
+        template <typename T>
+        struct is_hold_any : mpl::false_ {};
+
+        template <typename Char>
+        struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {};
     }
 
-///////////////////////////////////////////////////////////////////////////////
 }}    // namespace boost::spirit
 
 ///////////////////////////////////////////////////////////////////////////////
Modified: trunk/boost/spirit/home/support/utree/operators.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/operators.hpp	(original)
+++ trunk/boost/spirit/home/support/utree/operators.hpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,6 +15,7 @@
 #endif
 
 #include <exception>
+#include <ios>
 #include <boost/spirit/home/support/utree/utree.hpp>
 #include <boost/preprocessor/cat.hpp>
 #include <boost/throw_exception.hpp>
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -38,6 +38,11 @@
     }
 }
 
+namespace boost { namespace spirit { namespace qi
+{
+    template <typename Subject> struct kleene;
+}}}
+
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
 {
@@ -59,6 +64,11 @@
             }
             return false;
         }
+
+        inline bool is_uninitialized(utree const& ut)
+        {
+            return traits::which(ut) == utree_type::invalid_type;
+        }
     }
 
     // this specialization tells Spirit how to extract the type of the value
@@ -507,8 +517,15 @@
     {
         static void call(utree& ut)
         {
-            if (!detail::is_list(ut))
-                ut = empty_list;
+            if (!detail::is_list(ut)) {
+                if (detail::is_uninitialized(ut))
+                    ut = empty_list;
+                else {
+                    utree retval (empty_list);
+                    retval.push_back(ut);
+                    ut.swap(retval);
+                }
+            }
         }
     };
 
@@ -644,7 +661,7 @@
         // only 'invalid_type' utree nodes are not valid
         static bool is_valid(utree const& val)
         {
-            return traits::which(val) != utree_type::invalid_type;
+          return !detail::is_uninitialized(val);
         }
     };
 
@@ -943,7 +960,7 @@
     }
 
     template <>
-    struct extract_from_attribute<utree, utree::nil_type>
+    struct extract_from_container<utree, utree::nil_type>
     {
         typedef utree::nil_type type;
 
@@ -955,7 +972,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, char>
+    struct extract_from_container<utree, char>
     {
         typedef char type;
 
@@ -968,7 +985,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, bool>
+    struct extract_from_container<utree, bool>
     {
         typedef bool type;
 
@@ -980,7 +997,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, int>
+    struct extract_from_container<utree, int>
     {
         typedef int type;
 
@@ -992,7 +1009,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, double>
+    struct extract_from_container<utree, double>
     {
         typedef double type;
 
@@ -1004,7 +1021,7 @@
     };
 
     template <typename Traits, typename Alloc>
-    struct extract_from_attribute<utree, std::basic_string<char, Traits, Alloc> >
+    struct extract_from_container<utree, std::basic_string<char, Traits, Alloc> >
     {
         typedef std::basic_string<char, Traits, Alloc> type;
 
@@ -1017,7 +1034,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, utf8_symbol_type>
+    struct extract_from_container<utree, utf8_symbol_type>
     {
         typedef std::string type;
 
@@ -1030,7 +1047,7 @@
     };
 
     template <>
-    struct extract_from_attribute<utree, utf8_string_type>
+    struct extract_from_container<utree, utf8_string_type>
     {
         typedef std::string type;
 
@@ -1123,7 +1140,10 @@
         static type pre(iterator_range<Iterator> const& t)
         {
             // return utree the begin iterator points to
-            return utree(boost::ref(t.front()));
+            Iterator it = boost::begin(t);
+            utree result(boost::ref(*it));
+            ++it;
+            return result;
         }
     };
 
Modified: trunk/libs/spirit/doc/what_s_new.qbk
==============================================================================
--- trunk/libs/spirit/doc/what_s_new.qbk	(original)
+++ trunk/libs/spirit/doc/what_s_new.qbk	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -149,8 +149,8 @@
 
 [heading Known Problems]
 
-* Integer literals consume input on failure, which can lead to problems with
-  the alternative operator:
+* Integer literals (like `int_(10)`) consume input on failure, which can lead to 
+  problems with the alternative operator:
 
 [endsect]
 
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile	(original)
+++ trunk/libs/spirit/test/Jamfile	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -194,6 +194,7 @@
      [ run karma/regression_optional_double.cpp            : : : :  karma_regression_optional_double ]
      [ run karma/regression_semantic_action_attribute.cpp  : : : :  karma_regression_semantic_action_attribute ]
      [ run karma/regression_real_scientific.cpp            : : : :  karma_regression_real_scientific ]
+     [ compile karma/regression_const_real_policies.cpp    : :  regression_const_real_policies ]
 
     ;
 
Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp	(original)
+++ trunk/libs/spirit/test/karma/kleene.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -23,6 +23,8 @@
 #include <boost/spirit/include/phoenix_statement.hpp>
 #include <boost/fusion/include/std_pair.hpp>
 
+#include <boost/assign/std/vector.hpp>
+
 #include "test.hpp"
 
 using namespace spirit_test;
@@ -63,6 +65,57 @@
     }
 
     {
+        std::string s1("aaaaa");
+        BOOST_TEST(test("aaaaa", char_ << *(char_ << char_), s1));
+        BOOST_TEST(test_delimited("a a a a a ", 
+            char_ << *(char_ << char_), s1, ' '));
+
+        s1 = "a";
+        BOOST_TEST(test("a", char_ << *(char_ << char_), s1));
+        s1 = "aa";
+        BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
+//         BOOST_TEST(test("aa", char_ << *buffer[char_ << char_] << char_, s1));
+        s1 = "aaaa";
+        BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
+//         BOOST_TEST(test("aaaa", char_ << *buffer[char_ << char_] << char_, s1));
+    }
+
+    {
+        using boost::spirit::karma::strict;
+        using boost::spirit::karma::relaxed;
+        using namespace boost::assign;
+
+        typedef std::pair<char, char> data;
+        std::vector<data> v1;
+        v1 += std::make_pair('a', 'a'), 
+              std::make_pair('b', 'b'), 
+              std::make_pair('c', 'c'), 
+              std::make_pair('d', 'd'), 
+              std::make_pair('e', 'e'), 
+              std::make_pair('f', 'f'), 
+              std::make_pair('g', 'g'); 
+
+        karma::rule<spirit_test::output_iterator<char>::type, data()> r;
+        r = &char_('a') << char_;
+
+        BOOST_TEST(test("a", r << *(r << r), v1));
+        BOOST_TEST(test("a", relaxed[r << *(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+
+         v1 += std::make_pair('a', 'a');
+
+        BOOST_TEST(!test("", r << *(r << r), v1));
+        BOOST_TEST(!test("", relaxed[r << *(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+
+         v1 += std::make_pair('a', 'a');
+
+        BOOST_TEST(test("aaa", r << *(r << r), v1));
+        BOOST_TEST(test("aaa", relaxed[r << *(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+    }
+
+    {
         using namespace boost::assign;
 
         std::vector<char> v;
Modified: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/list.cpp	(original)
+++ trunk/libs/spirit/test/karma/list.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -75,6 +75,13 @@
             char_ % ',', s, space));
     }
 
+    {
+        std::string s ("abcdefg");
+        BOOST_TEST(test("abc,de,fg", char_ << ((char_ << char_) % ','), s));
+        BOOST_TEST(test_delimited("a b c , d e , f g ", 
+            char_ << ((char_ << char_) % ','), s, space));
+    }
+
     { // actions
         namespace phx = boost::phoenix;
 
Modified: trunk/libs/spirit/test/karma/lit.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/lit.cpp	(original)
+++ trunk/libs/spirit/test/karma/lit.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -63,6 +63,10 @@
 
         BOOST_TEST(test("abc", str));
         BOOST_TEST(!test("abcd", str));
+    }
+
+    {
+        using namespace boost::spirit::standard_wide;
 
         std::basic_string<wchar_t> wstr(L"abc");
         BOOST_TEST(test(L"abc", lit(wstr)));
Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp	(original)
+++ trunk/libs/spirit/test/karma/plus.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -67,6 +67,55 @@
     }
 
     {
+        std::string s1("aaaaa");
+        BOOST_TEST(test("aaaaa", char_ << +(char_ << char_), s1));
+        BOOST_TEST(test_delimited("a a a a a ", 
+            char_ << +(char_ << char_), s1, ' '));
+
+        s1 = "a";
+        BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+        s1 = "aa";
+        BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+        s1 = "aaaa";
+        BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+    }
+
+    {
+        using boost::spirit::karma::strict;
+        using boost::spirit::karma::relaxed;
+        using namespace boost::assign;
+
+        typedef std::pair<char, char> data;
+        std::vector<data> v1;
+        v1 += std::make_pair('a', 'a'), 
+              std::make_pair('b', 'b'), 
+              std::make_pair('c', 'c'), 
+              std::make_pair('d', 'd'), 
+              std::make_pair('e', 'e'), 
+              std::make_pair('f', 'f'), 
+              std::make_pair('g', 'g'); 
+
+        karma::rule<spirit_test::output_iterator<char>::type, data()> r;
+        r = &char_('a') << char_;
+
+        BOOST_TEST(!test("", r << +(r << r), v1));
+        BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+
+         v1 += std::make_pair('a', 'a');
+
+        BOOST_TEST(!test("", r << *(r << r), v1));
+        BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+
+         v1 += std::make_pair('a', 'a');
+
+        BOOST_TEST(test("aaa", r << +(r << r), v1));
+        BOOST_TEST(test("aaa", relaxed[r << +(r << r)], v1));
+        BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+    }
+
+    {
         using namespace boost::assign;
 
         std::vector<char> v;
Added: trunk/libs/spirit/test/karma/regression_const_real_policies.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/regression_const_real_policies.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -0,0 +1,25 @@
+//  Copyright (c) 2001-2011 Hartmut Kaiser
+//  Copyright (c) 2011 Jeroen Habraken 
+// 
+//  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)
+
+// compile test verifying it's possible to use const types for real_policies.
+
+#include <boost/spirit/include/karma.hpp>
+
+#include <iterator>
+#include <string>
+
+int main() 
+{
+    using namespace boost::spirit::karma;
+
+    typedef real_generator<double const, real_policies<double const> > 
+        double_const_type;
+
+    std::string generated;
+    generate(std::back_inserter(generated), double_const_type(), 1.0);
+
+    return 0;
+}
Modified: trunk/libs/spirit/test/karma/repeat2.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat2.cpp	(original)
+++ trunk/libs/spirit/test/karma/repeat2.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -49,6 +49,15 @@
         BOOST_TEST(test_delimited("A B C D E F G H ", upper[repeat(8)[char_]], str, space));
     }
 
+//    {
+//        std::string s1 = "aaaaa";
+//        BOOST_TEST(test("aaaaa", char_ << repeat(2)[char_ << char_], s1));
+//        s1 = "aaa";
+//        BOOST_TEST(test("aaa", char_ << repeat(1, 2)[char_ << char_], s1));
+//        s1 = "aa";
+//        BOOST_TEST(!test("", char_ << repeat(1)[char_ << char_], s1));
+//    }
+
     { // actions
         namespace phx = boost::phoenix;
 
Modified: trunk/libs/spirit/test/karma/stream.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/stream.cpp	(original)
+++ trunk/libs/spirit/test/karma/stream.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -3,13 +3,13 @@
 //  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 <stdint.h>
 #include <cwchar>
 #include <streambuf>
 #include <iostream>
 
 #include <boost/config/warning_disable.hpp>
 #include <boost/detail/lightweight_test.hpp>
+#include <boost/cstdint.hpp>
 
 #include <boost/spirit/include/karma_char.hpp>
 #include <boost/spirit/include/karma_string.hpp>
Modified: trunk/libs/spirit/test/karma/utree2.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/utree2.cpp	(original)
+++ trunk/libs/spirit/test/karma/utree2.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -62,8 +62,8 @@
         rule<output_iterator, utree::const_range()> r1list;
 
         r1 = double_ | int_ | r1str | r1list | r1ref;
-  
-        r1ref = r1;
+
+        r1ref = r1.alias();
 
         r1str = string;
 
Modified: trunk/libs/spirit/test/karma/wstream.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/wstream.cpp	(original)
+++ trunk/libs/spirit/test/karma/wstream.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -3,13 +3,13 @@
 //  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 <stdint.h>
 #include <cwchar>
 #include <streambuf>
 #include <iostream>
 
 #include <boost/config/warning_disable.hpp>
 #include <boost/detail/lightweight_test.hpp>
+#include <boost/cstdint.hpp>
 
 #include <boost/spirit/include/karma_char.hpp>
 #include <boost/spirit/include/karma_string.hpp>
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -216,6 +216,14 @@
         BOOST_TEST(s == "abc");
     }
 
+    {
+        using boost::spirit::qi::int_;
+
+        int i = 0;
+        BOOST_TEST( (test_attr("10", int_(5) | int_(10), i)) );
+        BOOST_TEST(i == 10);
+    }
+
     return boost::report_errors();
 }
 
Modified: trunk/libs/spirit/test/qi/debug.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/debug.cpp	(original)
+++ trunk/libs/spirit/test/qi/debug.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -88,7 +88,7 @@
         BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false));
     }
 
-    { // std::contaner attributes
+    { // std::container attributes
 
         typedef boost::fusion::vector<int, char> fs;
         rule<char const*, std::vector<fs>(), space_type> start;
Modified: trunk/libs/spirit/test/qi/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/kleene.cpp	(original)
+++ trunk/libs/spirit/test/qi/kleene.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -87,17 +87,11 @@
         s.clear();
         BOOST_TEST(test_attr("b b b b ", *char_, s, space)  && s == "bbbb");
 
-        // The following 4 tests show that omit does not inhibit explicit attributes
-        s.clear();
-        BOOST_TEST(test_attr("bbbb", *omit[char_('b')], s) && s == "bbbb");
-
+        // The following 2 tests show that omit does not inhibit explicit attributes
         s.clear();
         BOOST_TEST(test_attr("bbbb", omit[*char_('b')], s) && s == "bbbb");
 
         s.clear();
-        BOOST_TEST(test_attr("b b b b", *omit[char_('b')], s, space) && s == "bbbb");
-
-        s.clear();
         BOOST_TEST(test_attr("b b b b", omit[*char_('b')], s, space) && s == "bbbb");
     }
 
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -49,6 +49,21 @@
         std::string s;
         BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', s));
         BOOST_TEST(s == "abcdefgh");
+
+        BOOST_TEST(!test("a,b,c,d,e,f,g,h,", char_ % ','));
+    }
+
+    {
+        std::string s;
+        BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', s));
+        BOOST_TEST(s == "abcdefgh");
+
+        BOOST_TEST(!test("ab,cd,ef,gh,", (char_ >> char_) % ','));
+        BOOST_TEST(!test("ab,cd,ef,g", (char_ >> char_) % ','));
+
+        s.clear();
+        BOOST_TEST(test_attr("ab,cd,efg", (char_ >> char_) % ',' >> char_, s));
+        BOOST_TEST(s == "abcdefg");
     }
 
     {
Modified: trunk/libs/spirit/test/qi/optional.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/optional.cpp	(original)
+++ trunk/libs/spirit/test/qi/optional.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -81,6 +81,12 @@
     }
 
     {
+        std::string s;
+        BOOST_TEST((test_attr("abc", char_ >> -(char_ >> char_), s)));
+        BOOST_TEST(s == "abc");
+    }
+
+    {
         namespace phx = boost::phoenix;
 
         boost::optional<int> n = 0;
Modified: trunk/libs/spirit/test/qi/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/plus.cpp	(original)
+++ trunk/libs/spirit/test/qi/plus.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -94,18 +94,12 @@
     }
 
     {
-        // The following 4 tests show that omit does not inhibit explicit attributes
+        // The following 2 tests show that omit does not inhibit explicit attributes
 
         std::string s;
-        BOOST_TEST(test_attr("bbbb", +omit[char_('b')], s) && s == "bbbb");
-
-        s.clear();
         BOOST_TEST(test_attr("bbbb", omit[+char_('b')], s) && s == "bbbb");
 
         s.clear();
-        BOOST_TEST(test_attr("b b b b ", +omit[char_('b')], s, space) && s == "bbbb");
-
-        s.clear();
         BOOST_TEST(test_attr("b b b b ", omit[+char_('b')], s, space) && s == "bbbb");
     }
 
Modified: trunk/libs/spirit/test/qi/regression_repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/regression_repeat.cpp	(original)
+++ trunk/libs/spirit/test/qi/regression_repeat.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -32,12 +32,12 @@
         omit[-qi::char_(" \t")]; 
     strrule_type correct_year = repeat(4)[qi::digit]; 
  
-    test("1776", correct_year | repeat(2)[qi::digit], "1776");
+    test("1776", qi::hold[correct_year] | repeat(2)[qi::digit], "1776");
     test("76",   obsolete_year, "76");
-    test("76",   obsolete_year | correct_year, "76");
-    test(" 76",  correct_year | obsolete_year, "76");
-    test("76",   correct_year | obsolete_year, "76");
-    test("76",   correct_year | repeat(2)[qi::digit], "76");
+    test("76",   qi::hold[obsolete_year] | correct_year, "76");
+    test(" 76",  qi::hold[correct_year] | obsolete_year, "76");
+    test("76",   qi::hold[correct_year] | obsolete_year, "76");
+    test("76",   qi::hold[correct_year] | repeat(2)[qi::digit], "76");
 
     return boost::report_errors();
 } 
Modified: trunk/libs/spirit/test/qi/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/repeat.cpp	(original)
+++ trunk/libs/spirit/test/qi/repeat.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -77,6 +77,40 @@
         BOOST_TEST(!test("aa", repeat(3, inf)[char_]));
     }
 
+    {
+        std::string s;
+        BOOST_TEST(test_attr("aaaaaaaa", repeat[char_ >> char_], s)); // kleene synonym
+        BOOST_TEST(s == "aaaaaaaa");
+
+        s.clear();
+        BOOST_TEST(test_attr("aaaaaaaa", repeat(4)[char_ >> char_], s));
+        BOOST_TEST(s == "aaaaaaaa");
+
+        BOOST_TEST(!test("aa", repeat(3)[char_ >> char_]));
+        BOOST_TEST(!test("a", repeat(1)[char_ >> char_]));
+
+        s.clear();
+        BOOST_TEST(test_attr("aa", repeat(1, 3)[char_ >> char_], s));
+        BOOST_TEST(s == "aa");
+
+        s.clear();
+        BOOST_TEST(test_attr("aaaaaa", repeat(1, 3)[char_ >> char_], s));
+        BOOST_TEST(s == "aaaaaa");
+
+        BOOST_TEST(!test("aaaaaaa", repeat(1, 3)[char_ >> char_]));
+        BOOST_TEST(!test("a", repeat(1, 3)[char_ >> char_]));
+
+        s.clear();
+        BOOST_TEST(test_attr("aaaa", repeat(2, inf)[char_ >> char_], s));
+        BOOST_TEST(s == "aaaa");
+
+        s.clear();
+        BOOST_TEST(test_attr("aaaaaa", repeat(2, inf)[char_ >> char_], s));
+        BOOST_TEST(s == "aaaaaa");
+
+        BOOST_TEST(!test("aa", repeat(2, inf)[char_ >> char_]));
+    }
+
     { // from classic spirit tests
         BOOST_TEST(test("", repeat(0, inf)['x']));
 
@@ -142,17 +176,11 @@
         s.clear();
         BOOST_TEST(test_attr("b b b b", repeat(4)[char_], s, space) && s == "bbbb");
 
-        // The following 4 tests show that omit does not inhibit explicit attributes
-        s.clear();
-        BOOST_TEST(test_attr("bbbb", repeat(4)[omit[char_('b')]], s) && s == "bbbb");
-
+        // The following 2 tests show that omit does not inhibit explicit attributes
         s.clear();
         BOOST_TEST(test_attr("bbbb", omit[repeat(4)[char_('b')]], s) && s == "bbbb");
 
         s.clear();
-        BOOST_TEST(test_attr("b b b b", repeat(4)[omit[char_('b')]], s, space) && s == "bbbb");
-
-        s.clear();
         BOOST_TEST(test_attr("b b b b", omit[repeat(4)[char_('b')]], s, space) && s == "bbbb");
     }
 
@@ -166,9 +194,7 @@
         BOOST_TEST(test_attr("1 2 3", int_ >> repeat(2)[int_], v, space));
         BOOST_TEST(v.size() == 3 && v[0] == 1 && v[1] == 2 && v[2] == 3);
 
-        v.clear();
-        BOOST_TEST(!test_attr("1 2", int_ >> repeat(2)[int_], v, space));
-        BOOST_TEST(v.size() == 1 && v[0] == 1);
+        BOOST_TEST(!test("1 2", int_ >> repeat(2)[int_], space));
     }
 
     { // actions
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-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -174,6 +174,38 @@
 
     { // alternative forms of attributes. Allow sequences to take in
       // stl containers.
+        using boost::spirit::qi::hold;
+
+        std::vector<char> v;
+        BOOST_TEST(test_attr("abc", char_ >> *(char_ >> char_), v));
+        BOOST_TEST(v.size() == 3);
+        BOOST_TEST(v[0] == 'a');
+        BOOST_TEST(v[1] == 'b');
+        BOOST_TEST(v[2] == 'c');
+
+        v.clear();
+        BOOST_TEST(!test_attr("abcd", char_ >> *(char_ >> char_), v));
+
+        v.clear();
+        BOOST_TEST(test_attr("abcdef", char_ >> *hold[char_ >> char_] >> char_, v));
+        BOOST_TEST(v.size() == 6);
+        BOOST_TEST(v[0] == 'a');
+        BOOST_TEST(v[1] == 'b');
+        BOOST_TEST(v[2] == 'c');
+        BOOST_TEST(v[3] == 'd');
+        BOOST_TEST(v[4] == 'e');
+        BOOST_TEST(v[5] == 'f');
+
+        v.clear();
+        BOOST_TEST(test_attr("abc", char_ >> +(char_ >> char_), v));
+        BOOST_TEST(v.size() == 3);
+        BOOST_TEST(v[0] == 'a');
+        BOOST_TEST(v[1] == 'b');
+        BOOST_TEST(v[2] == 'c');
+    }
+
+    { // alternative forms of attributes. Allow sequences to take in
+      // stl containers.
 
         std::vector<char> v;
         BOOST_TEST(test_attr("abc", char_ >> -(+char_), v));
@@ -248,7 +280,6 @@
     }
 
     {   // testing "what"
-
         print_info(what(alpha | char_('x') >> lit("hello") >> int_));
     }
 
Modified: trunk/libs/spirit/test/qi/utree1.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree1.cpp	(original)
+++ trunk/libs/spirit/test/qi/utree1.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -165,26 +165,22 @@
 
         BOOST_TEST(test_attr("a25.5b", r1 > r2 >> r3, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
-        BOOST_TEST(check(ut, "( \"a\" ( ( 25.5 ) ( \"b\" ) ) )"));
-                  // FIXME:  "( \"a\" ( 25.5 ) ( \"b\" ) )" 
+        BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
         ut.clear();
 
         BOOST_TEST(test_attr("a25.5b", r3 >> r2 > r1, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
-        BOOST_TEST(check(ut, "( ( ( \"a\" ) ( 25.5 ) ) \"b\" )"));
-                  // FIXME:  "( ( \"a\" ) ( 25.5 ) \"b\" )" 
+        BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
         ut.clear();
 
         BOOST_TEST(test_attr("a25.5b", char_ > r2 >> r3, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
-        BOOST_TEST(check(ut, "( \"a\" ( ( 25.5 ) ( \"b\" ) ) )"));
-                  // FIXME:  "( \"a\" ( 25.5 ) ( \"b\" ) )" 
+        BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
         ut.clear();
 
         BOOST_TEST(test_attr("a25.5b", r3 >> r2 > char_, ut));
         BOOST_TEST(ut.which() == utree_type::list_type);
-        BOOST_TEST(check(ut, "( ( ( \"a\" ) ( 25.5 ) ) \"b\" )"));
-                  // FIXME:  "( ( \"a\" ) ( 25.5 ) \"b\" )" 
+        BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
     }
 
     return boost::report_errors();
Modified: trunk/libs/spirit/test/qi/utree2.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree2.cpp	(original)
+++ trunk/libs/spirit/test/qi/utree2.cpp	2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -86,8 +86,9 @@
             ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
         ut.clear();
 
-        rule<char const*, utree(), space_type> r1 = 
-            strict_double | int_ | ~char_("()") | ('(' >> *r1 >> ')');
+        rule<char const*, utree(), space_type> r1;
+        rule<char const*, utree::list_type(), space_type> r2 = '(' >> *r1 >> ')';
+        r1 = strict_double | int_ | ~char_("()") | r2;
 
         BOOST_TEST(test_attr("(x y)", r1, ut, space) &&
             ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));