Boost logo

Boost-Commit :

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\" )"));


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