Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r57164 - in branches/release: boost/spirit boost/spirit/home boost/spirit/home/karma boost/spirit/home/karma/binary boost/spirit/home/karma/char boost/spirit/home/karma/detail boost/spirit/home/karma/directive boost/spirit/home/karma/numeric boost/spirit/home/karma/operator boost/spirit/home/karma/stream boost/spirit/home/karma/string boost/spirit/home/qi/detail boost/spirit/home/qi/nonterminal boost/spirit/home/qi/numeric/detail boost/spirit/home/support boost/spirit/repository/home/qi/nonterminal libs/spirit libs/spirit/classic/example libs/spirit/doc libs/spirit/doc/html/spirit/abstracts/customize libs/spirit/doc/html/spirit/abstracts/indepth libs/spirit/example libs/spirit/phoenix libs/spirit/test libs/spirit/test/karma libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2009-10-26 20:42:00


Author: hkaiser
Date: 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
New Revision: 57164
URL: http://svn.boost.org/trac/boost/changeset/57164

Log:
Spirit: merging latest bug fixes from trunk
Properties modified:
   branches/release/boost/spirit/ (props changed)
   branches/release/boost/spirit/home/ (props changed)
   branches/release/boost/spirit/home/karma/ (props changed)
   branches/release/boost/spirit/home/qi/nonterminal/rule.hpp (props changed)
   branches/release/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp (props changed)
   branches/release/boost/spirit/home/support/attributes.hpp (contents, props changed)
   branches/release/boost/spirit/repository/home/qi/nonterminal/subrule.hpp (props changed)
   branches/release/libs/spirit/ (props changed)
   branches/release/libs/spirit/classic/example/ (props changed)
   branches/release/libs/spirit/doc/ (props changed)
   branches/release/libs/spirit/doc/html/spirit/abstracts/customize/ (props changed)
   branches/release/libs/spirit/doc/html/spirit/abstracts/indepth/ (props changed)
   branches/release/libs/spirit/example/ (props changed)
   branches/release/libs/spirit/phoenix/ (props changed)
   branches/release/libs/spirit/test/ (props changed)
   branches/release/libs/spirit/test/qi/optional.cpp (props changed)
Text files modified:
   branches/release/boost/spirit/home/karma/binary/binary.hpp | 10 ++-
   branches/release/boost/spirit/home/karma/char/char.hpp | 10 +++
   branches/release/boost/spirit/home/karma/char/char_class.hpp | 4 +
   branches/release/boost/spirit/home/karma/char/char_generator.hpp | 2
   branches/release/boost/spirit/home/karma/detail/alternative_function.hpp | 13 ++++-
   branches/release/boost/spirit/home/karma/detail/extract_from.hpp | 25 ++++++---
   branches/release/boost/spirit/home/karma/detail/output_iterator.hpp | 35 ++++++++-----
   branches/release/boost/spirit/home/karma/directive/maxwidth.hpp | 69 +++++++++++++--------------
   branches/release/boost/spirit/home/karma/numeric/bool.hpp | 12 +++-
   branches/release/boost/spirit/home/karma/numeric/int.hpp | 14 +++--
   branches/release/boost/spirit/home/karma/numeric/real.hpp | 19 ++++---
   branches/release/boost/spirit/home/karma/numeric/uint.hpp | 14 +++--
   branches/release/boost/spirit/home/karma/operator/alternative.hpp | 51 +++++++++++++++++++-
   branches/release/boost/spirit/home/karma/stream/stream.hpp | 16 ++++--
   branches/release/boost/spirit/home/karma/string/lit.hpp | 10 ++--
   branches/release/boost/spirit/home/qi/detail/alternative_function.hpp | 10 ++-
   branches/release/boost/spirit/home/qi/detail/assign_to.hpp | 19 +++++++
   branches/release/boost/spirit/home/support/attributes.hpp | 98 ++++++++++++++++++++++++++++++++++++---
   branches/release/boost/spirit/home/support/container.hpp | 28 +++++------
   branches/release/libs/spirit/test/karma/alternative.cpp | 76 +++++++++++++++++++++++++++++++
   branches/release/libs/spirit/test/qi/alternative.cpp | 39 ++++++++++-----
   21 files changed, 434 insertions(+), 140 deletions(-)

Modified: branches/release/boost/spirit/home/karma/binary/binary.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/binary/binary.hpp (original)
+++ branches/release/boost/spirit/home/karma/binary/binary.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -180,8 +180,8 @@
         template <
             typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- static bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr)
+ static bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr)
         {
             if (!traits::has_optional_value(attr))
                 return false;
@@ -192,7 +192,7 @@
             boost::integer::endian<
                 endian, typename karma::detail::integer<bits>::type, bits
> p;
- p = traits::extract_from(attr);
+ p = traits::extract_from(attr, context);
             unsigned char const* bytes =
                 reinterpret_cast<unsigned char const*>(&p);
 
@@ -211,6 +211,10 @@
         static bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , unused_type)
         {
+ // It is not possible (doesn't make sense) to use binary generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false,
                 binary_generator_not_usable_without_attribute, ());
             return false;

Modified: branches/release/boost/spirit/home/karma/char/char.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/char/char.hpp (original)
+++ branches/release/boost/spirit/home/karma/char/char.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -219,6 +219,10 @@
         template <typename CharParam, typename Context>
         bool test(unused_type, CharParam&, Context&) const
         {
+ // It is not possible (doesn't make sense) to use char_ generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false
               , char_range_not_usable_without_attribute, ());
             return false;
@@ -295,8 +299,12 @@
         template <typename CharParam, typename Context>
         bool test(unused_type, CharParam&, Context&) const
         {
+ // It is not possible (doesn't make sense) to use char_ generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false
- , char_set_not_usable_without_attribute, ());
+ , char_set_not_usable_without_attribute, ());
             return false;
         }
 

Modified: branches/release/boost/spirit/home/karma/char/char_class.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/char/char_class.hpp (original)
+++ branches/release/boost/spirit/home/karma/char/char_class.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -89,6 +89,10 @@
         template <typename CharParam, typename Context>
         bool test(unused_type, CharParam& ch, Context&) const
         {
+ // It is not possible (doesn't make sense) to use char_ generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false
               , char_class_not_usable_without_attribute, ());
             return false;

Modified: branches/release/boost/spirit/home/karma/char/char_generator.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/char/char_generator.hpp (original)
+++ branches/release/boost/spirit/home/karma/char/char_generator.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -75,7 +75,7 @@
                 return false;
 
             Attr ch = Attr();
- if (!this->derived().test(traits::extract_from(attr), ch, context))
+ if (!this->derived().test(traits::extract_from(attr, context), ch, context))
                 return false;
 
             return karma::detail::generate_to(sink, ch, char_encoding(), tag()) &&

Modified: branches/release/boost/spirit/home/karma/detail/alternative_function.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/detail/alternative_function.hpp (original)
+++ branches/release/boost/spirit/home/karma/detail/alternative_function.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -49,7 +49,8 @@
     template <typename Expected, typename Attribute>
     struct compute_compatible_component_variant<Expected, Attribute, mpl::false_>
     {
- typedef typename Attribute::types types;
+ typedef typename traits::variant_type<Attribute>::type variant_type;
+ typedef typename variant_type::types types;
         typedef typename mpl::end<types>::type end;
 
         typedef typename
@@ -160,9 +161,15 @@
 
             typedef typename component_type::distance distance_type;
 
+ // if we got passed an empty optional, just fail generation
+ if (!traits::has_optional_value(attr))
+ return false;
+
             // make sure, the content of the passed variant matches our
             // expectations
- if (attr.which() != distance_type::value)
+ typename traits::optional_attribute<Attribute>::type attr_ =
+ traits::optional_value(attr);
+ if (attr_.which() != distance_type::value)
                 return false;
 
             // returns true if any of the generators succeed
@@ -170,7 +177,7 @@
                 typename mpl::deref<typename component_type::iter>::type
             compatible_type;
 
- return component.generate(sink, ctx, d, get<compatible_type>(attr));
+ return component.generate(sink, ctx, d, get<compatible_type>(attr_));
         }
     };
 

Modified: branches/release/boost/spirit/home/karma/detail/extract_from.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/detail/extract_from.hpp (original)
+++ branches/release/boost/spirit/home/karma/detail/extract_from.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -32,7 +32,9 @@
     struct extract_from_attribute
     {
         typedef Attribute const& type;
- static type call(Attribute const& attr)
+
+ template <typename Context>
+ static type call(Attribute const& attr, Context&)
         {
             return attr;
         }
@@ -43,7 +45,9 @@
     struct extract_from_attribute<optional<Attribute> >
     {
         typedef Attribute const& type;
- static type call(optional<Attribute> const& attr)
+
+ template <typename Context>
+ static type call(optional<Attribute> const& attr, Context&)
         {
             return boost::get<Attribute>(attr);
         }
@@ -53,7 +57,9 @@
     struct extract_from_attribute<optional<Attribute const> >
     {
         typedef Attribute const& type;
- static type call(optional<Attribute const> const& attr)
+
+ template <typename Context>
+ static type call(optional<Attribute const> const& attr, Context&)
         {
             return boost::get<Attribute const>(attr);
         }
@@ -64,21 +70,24 @@
     struct extract_from_attribute<reference_wrapper<Attribute> >
     {
         typedef Attribute const& type;
- static type call(reference_wrapper<Attribute> const& attr)
+
+ template <typename Context>
+ static type call(reference_wrapper<Attribute> const& attr, Context&)
         {
             return attr.get();
         }
     };
 
     ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute>
+ template <typename Attribute, typename Context>
     typename spirit::result_of::extract_from<Attribute>::type
- extract_from(Attribute const& attr)
+ extract_from(Attribute const& attr, Context& context)
     {
- return extract_from_attribute<Attribute>::call(attr);
+ return extract_from_attribute<Attribute>::call(attr, context);
     };
 
- unused_type extract_from(unused_type)
+ template <typename Context>
+ unused_type extract_from(unused_type, Context&)
     {
         return unused;
     };

Modified: branches/release/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/detail/output_iterator.hpp (original)
+++ branches/release/boost/spirit/home/karma/detail/output_iterator.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -217,15 +217,22 @@
             std::copy(buffer.begin(), end, sink);
             return true;
         }
-// template <typename RestIterator>
-// bool copy_rest(RestIterator& sink, std::size_t start_at) const
-// {
-// typename std::basic_string<T>::const_iterator begin =
-// buffer.begin() + (std::min)(buffer.size(), start_at);
-//
-// std::copy(begin, buffer.end(), restsink);
-// return true;
-// }
+ template <typename RestIterator>
+ bool copy_rest(RestIterator& sink, std::size_t start_at) const
+ {
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4267)
+#endif
+ typename std::basic_string<wchar_t>::const_iterator begin =
+ buffer.begin() + (std::min)(buffer.size(), start_at);
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+ std::copy(begin, buffer.end(), sink);
+ return true;
+ }
 
         std::size_t buffer_size() const
         {
@@ -524,10 +531,12 @@
             return buffer_data.buffer_size();
         }
 
-// bool buffer_copy_rest(std::size_t start_at = 0)
-// {
-// return buffer_data.copy_rest(sink, start_at);
-// }
+ // copy to the remaining characters to the specified sink
+ template <typename RestIterator>
+ bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0)
+ {
+ return buffer_data.copy_rest(sink, start_at);
+ }
 
     private:
         OutputIterator& sink;

Modified: branches/release/boost/spirit/home/karma/directive/maxwidth.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/directive/maxwidth.hpp (original)
+++ branches/release/boost/spirit/home/karma/directive/maxwidth.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -49,20 +49,20 @@
     struct use_lazy_directive<karma::domain, tag::maxwidth, 1>
       : mpl::true_ {};
 
-// // enables maxwidth(w, r)[g], where w provides a maxwidth and r is a output
-// // iterator used to receive the rest of the output not fitting into the
-// // maxwidth limit
-// template <typename T, typename RestIter>
-// struct use_directive<karma::domain
-// , terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > >
-// : mpl::true_ {};
-//
-// // enables *lazy* maxwidth(w, r)[g], where w provides a maxwidth and r is
-// // a output iterator used to receive the rest of the output not fitting
-// // into the maxwidth limit
-// template <>
-// struct use_lazy_directive<karma::domain, tag::maxwidth, 2>
-// : mpl::true_ {};
+ // enables maxwidth(w, r)[g], where w provides a maxwidth and r is an output
+ // iterator used to receive the rest of the output not fitting into the
+ // maxwidth limit
+ template <typename T, typename RestIter>
+ struct use_directive<karma::domain
+ , terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > >
+ : mpl::true_ {};
+
+ // enables *lazy* maxwidth(w, r)[g], where w provides a maxwidth and r is
+ // an output iterator used to receive the rest of the output not fitting
+ // into the maxwidth limit
+ template <>
+ struct use_lazy_directive<karma::domain, tag::maxwidth, 2>
+ : mpl::true_ {};
 
 }}
 
@@ -75,12 +75,11 @@
     namespace detail
     {
         ///////////////////////////////////////////////////////////////////////
- template <typename OutputIterator, typename T>
+ template <typename OutputIterator, typename RestIterator>
         bool buffer_copy_rest(detail::enable_buffering<OutputIterator>& buff
- , std::size_t start_at, T& dest)
+ , std::size_t start_at, RestIterator& dest)
         {
- // not implemented yet
- return true; // buff.buffer_copy_rest(start_at);
+ return buff.buffer_copy_rest(dest, start_at);
         }
 
         template <typename OutputIterator>
@@ -199,23 +198,23 @@
         }
     };
 
-// // creates maxwidth(width, restiter)[] directive generator
-// template <
-// typename T, typename RestIter, typename Subject, typename Modifiers>
-// struct make_directive<
-// terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> >
-// , Subject, Modifiers>
-// {
-// typedef maxwidth_width<Subject, T, RestIter> result_type;
-//
-// template <typename Terminal>
-// result_type operator()(Terminal const& term, Subject const& subject
-// , unused_type) const
-// {
-// return result_type(subject, fusion::at_c<0>(term.args)
-// , fusion::at_c<1>(term.args));
-// }
-// };
+ // creates maxwidth(width, restiter)[] directive generator
+ template <
+ typename T, typename RestIter, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> >
+ , Subject, Modifiers>
+ {
+ typedef maxwidth_width<Subject, T, RestIter> result_type;
+
+ template <typename Terminal>
+ result_type operator()(Terminal const& term, Subject const& subject
+ , unused_type) const
+ {
+ return result_type(subject, fusion::at_c<0>(term.args)
+ , fusion::at_c<1>(term.args));
+ }
+ };
 
 }}} // namespace boost::spirit::karma
 

Modified: branches/release/boost/spirit/home/karma/numeric/bool.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/numeric/bool.hpp (original)
+++ branches/release/boost/spirit/home/karma/numeric/bool.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -137,14 +137,14 @@
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
         bool
- generate(OutputIterator& sink, Context&, Delimiter const& d
+ generate(OutputIterator& sink, Context& context, Delimiter const& d
           , Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr))
                 return false; // fail if it's an uninitialized optional
 
             return bool_inserter<T, Policies, CharEncoding, Tag>::call(
- sink, traits::extract_from(attr), p_) &&
+ sink, traits::extract_from(attr, context), p_) &&
                    delimit_out(sink, d); // always do post-delimiting
         }
 
@@ -154,6 +154,10 @@
         static bool
         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
         {
+ // It is not possible (doesn't make sense) to use boolean generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false, bool_not_usable_without_attribute, ());
             return false;
         }
@@ -194,11 +198,11 @@
         // it fails.
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&
+ bool generate(OutputIterator& sink, Context& context
           , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr) ||
- bool(n_) != bool(traits::extract_from(attr)))
+ bool(n_) != bool(traits::extract_from(attr, context)))
             {
                 return false;
             }

Modified: branches/release/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/numeric/int.hpp (original)
+++ branches/release/boost/spirit/home/karma/numeric/int.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -210,13 +210,13 @@
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
         static bool
- generate(OutputIterator& sink, Context&, Delimiter const& d
+ generate(OutputIterator& sink, Context& context, Delimiter const& d
           , Attribute const& attr)
         {
             if (!traits::has_optional_value(attr))
                 return false; // fail if it's an uninitialized optional
 
- return insert_int(sink, traits::extract_from(attr)) &&
+ return insert_int(sink, traits::extract_from(attr, context)) &&
                    delimit_out(sink, d); // always do post-delimiting
         }
 
@@ -226,6 +226,10 @@
         static bool
         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
         {
+ // It is not possible (doesn't make sense) to use numeric generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false, int_not_usable_without_attribute, ());
             return false;
         }
@@ -280,11 +284,11 @@
         // it fails.
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr) const
+ bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr))
+ n_ != traits::extract_from(attr, context))
             {
                 return false;
             }

Modified: branches/release/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/numeric/real.hpp (original)
+++ branches/release/boost/spirit/home/karma/numeric/real.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -168,14 +168,14 @@
         // double_/float_/etc. has an attached attribute
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr) const
+ bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr))
                 return false; // fail if it's an uninitialized optional
 
             typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
- return inserter_type::call(sink, traits::extract_from(attr), p_) &&
+ return inserter_type::call(sink, traits::extract_from(attr, context), p_) &&
                    karma::delimit_out(sink, d); // always do post-delimiting
         }
 
@@ -185,8 +185,11 @@
         static bool generate(OutputIterator&, Context&, Delimiter const&
           , unused_type)
         {
- BOOST_SPIRIT_ASSERT_MSG(false, real_not_usable_without_attribute, ());
- return false;
+ // It is not possible (doesn't make sense) to use numeric generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
+ BOOST_SPIRIT_ASSERT_MSG(false, real_not_usable_without_attribute, ()); return false;
         }
 
         template <typename Context>
@@ -225,11 +228,11 @@
         // it fails.
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr) const
+ bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr))
+ n_ != traits::extract_from(attr, context))
             {
                 return false;
             }

Modified: branches/release/boost/spirit/home/karma/numeric/uint.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/numeric/uint.hpp (original)
+++ branches/release/boost/spirit/home/karma/numeric/uint.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -243,14 +243,14 @@
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
         static bool
- generate(OutputIterator& sink, Context&, Delimiter const& d
+ generate(OutputIterator& sink, Context& context, Delimiter const& d
           , Attribute const& attr)
         {
             if (!traits::has_optional_value(attr))
                 return false; // fail if it's an uninitialized optional
 
             return int_inserter<Radix, CharEncoding, Tag>::
- call(sink, traits::extract_from(attr)) &&
+ call(sink, traits::extract_from(attr, context)) &&
                    delimit_out(sink, d); // always do post-delimiting
         }
 
@@ -260,6 +260,10 @@
         static bool
         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
         {
+ // It is not possible (doesn't make sense) to use numeric generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
             BOOST_SPIRIT_ASSERT_MSG(false, uint_not_usable_without_attribute, ());
             return false;
         }
@@ -303,11 +307,11 @@
         // it fails.
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr) const
+ bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr))
+ n_ != traits::extract_from(attr, context))
             {
                 return false;
             }

Modified: branches/release/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/operator/alternative.hpp (original)
+++ branches/release/boost/spirit/home/karma/operator/alternative.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -12,6 +12,7 @@
 #endif
 
 #include <boost/spirit/home/karma/detail/alternative_function.hpp>
+#include <boost/spirit/home/karma/detail/extract_from.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/meta_compiler.hpp>
@@ -100,14 +101,37 @@
         alternative(Elements const& elements)
           : elements(elements) {}
 
+ // this is the implementation for non-optional and non-empty optional
+ // attributes
         template <
             typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Attribute const& attr) const
+ bool generate_dispatch(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Attribute const& attr, mpl::true_) const
         {
+ typedef typename
+ traits::extract_from_attribute<Attribute>::type attr_type;
             typedef detail::alternative_generate_functor<
- OutputIterator, Context, Delimiter, Attribute
+ OutputIterator, Context, Delimiter
+ , typename remove_const<
+ typename remove_reference<attr_type>::type>::type
+ > functor;
+
+ // f return true if *any* of the parser succeeds
+ functor f (sink, ctx, d, traits::extract_from(attr, ctx));
+ return fusion::any(elements, f);
+ }
+
+ // this is the implementation for empty optional attributes, the empty
+ // optional is passed through to the embedded generators
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Optional>
+ bool generate_optional(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Optional const& attr) const
+ {
+ typedef detail::alternative_generate_functor<
+ OutputIterator, Context, Delimiter, Optional
> functor;
 
             // f return true if *any* of the parser succeeds
@@ -115,6 +139,27 @@
             return fusion::any(elements, f);
         }
 
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Attribute>
+ bool generate_dispatch(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Attribute const& attr, mpl::false_) const
+ {
+ if (!traits::has_optional_value(attr))
+ return generate_optional(sink, ctx, d, attr);
+ return generate_dispatch(sink, ctx, d, attr, mpl::true_());
+ }
+
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Attribute>
+ bool generate(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Attribute const& attr) const
+ {
+ return generate_dispatch(sink, ctx, d, attr
+ , traits::not_is_optional<Attribute>());
+ }
+
         template <typename Context>
         info what(Context& context) const
         {

Modified: branches/release/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/stream/stream.hpp (original)
+++ branches/release/boost/spirit/home/karma/stream/stream.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -121,7 +121,7 @@
             typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute
>
- static bool generate(OutputIterator& sink, Context&
+ static bool generate(OutputIterator& sink, Context& context
           , Delimiter const& d, Attribute const& attr)
         {
             typedef karma::detail::iterator_sink<
@@ -133,7 +133,7 @@
 
             // use existing operator<<()
             boost::iostreams::stream<sink_device> ostr(sink);
- ostr << traits::extract_from(attr) << std::flush;
+ ostr << traits::extract_from(attr, context) << std::flush;
 
             if (ostr.good())
                 return karma::delimit_out(sink, d); // always do post-delimiting
@@ -149,7 +149,8 @@
         static bool generate(
             karma::detail::output_iterator<
                 karma::ostream_iterator<T, Char, Traits>, Properties
- >& sink, Context&, Delimiter const& d, Attribute const& attr)
+ >& sink, Context& context, Delimiter const& d
+ , Attribute const& attr)
         {
             typedef karma::detail::output_iterator<
                 karma::ostream_iterator<T, Char, Traits>, Properties
@@ -164,7 +165,7 @@
             // use existing operator<<()
             boost::iostreams::stream<sink_device> ostr(sink);
             ostr.imbue(sink.get_ostream().getloc());
- ostr << traits::extract_from(attr) << std::flush;
+ ostr << traits::extract_from(attr, context) << std::flush;
 
             if (ostr.good())
                 return karma::delimit_out(sink, d); // always do post-delimiting
@@ -178,8 +179,11 @@
         static bool
         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
         {
- BOOST_SPIRIT_ASSERT_MSG(false, stream_not_usable_without_attribute,
- (OutputIterator, Delimiter));
+ // It is not possible (doesn't make sense) to use stream generators
+ // without providing any attribute, as the generator doesn't 'know'
+ // what to output. The following assertion fires if this situation
+ // is detected in your code.
+ BOOST_SPIRIT_ASSERT_MSG(false, stream_not_usable_without_attribute, ());
             return false;
         }
 

Modified: branches/release/boost/spirit/home/karma/string/lit.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/string/lit.hpp (original)
+++ branches/release/boost/spirit/home/karma/string/lit.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -88,7 +88,7 @@
         template <typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
         static bool
- generate(OutputIterator& sink, Context& /*ctx*/, Delimiter const& d,
+ generate(OutputIterator& sink, Context& context, Delimiter const& d,
             Attribute const& attr)
         {
             if (!traits::has_optional_value(attr))
@@ -96,7 +96,7 @@
 
             return
                 karma::detail::string_generate(sink
- , traits::extract_from(attr), char_encoding(), Tag()) &&
+ , traits::extract_from(attr, context), char_encoding(), Tag()) &&
                 karma::delimit_out(sink, d); // always do post-delimiting
         }
 
@@ -149,8 +149,8 @@
         template <
             typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const& attr) const
+ bool generate(OutputIterator& sink, Context& context
+ , Delimiter const& d, Attribute const& attr) const
         {
             if (!traits::has_optional_value(attr))
                 return false;
@@ -158,7 +158,7 @@
             // fail if attribute isn't matched by immediate literal
             using spirit::traits::get_c_string;
             if (!detail::string_compare(
- get_c_string(traits::extract_from(attr))
+ get_c_string(traits::extract_from(attr, context))
                   , get_c_string(str_), char_encoding(), Tag()))
             {
                 return false;

Modified: branches/release/boost/spirit/home/qi/detail/alternative_function.hpp
==============================================================================
--- branches/release/boost/spirit/home/qi/detail/alternative_function.hpp (original)
+++ branches/release/boost/spirit/home/qi/detail/alternative_function.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -42,8 +42,8 @@
         template <typename Component>
         bool call(Component const& component, mpl::false_) const
         {
- // if Attribute is a variant, then create an attribute for
- // the Component with its expected type.
+ // if Attribute is a variant or optional, then create an
+ // attribute for the Component with its expected type.
             typename traits::attribute_of<Component, Context, Iterator>::type val;
             if (component.parse(first, last, context, skipper, val))
             {
@@ -57,7 +57,11 @@
         bool operator()(Component const& component) const
         {
             // return true if the parser succeeds
- return call(component, spirit::traits::not_is_variant<Attribute>());
+ return call(component,
+ mpl::and_<
+ spirit::traits::not_is_variant<Attribute>,
+ spirit::traits::not_is_optional<Attribute>
+ >());
         }
 
         Iterator& first;

Modified: branches/release/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- branches/release/boost/spirit/home/qi/detail/assign_to.hpp (original)
+++ branches/release/boost/spirit/home/qi/detail/assign_to.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -73,6 +73,25 @@
         }
     };
 
+ template <typename Attribute, typename T>
+ struct assign_to_attribute_from_value<reference_wrapper<Attribute>, T>
+ {
+ static void
+ call(T const& val, reference_wrapper<Attribute> attr)
+ {
+ attr = val;
+ }
+ };
+
+ template <typename Attribute>
+ struct assign_to_attribute_from_value<optional<Attribute>, unused_type>
+ {
+ static void
+ call(unused_type, optional<Attribute> const& attr)
+ {
+ }
+ };
+
     template <typename T, typename Attribute>
     inline void
     assign_to(T const& val, Attribute& attr)

Modified: branches/release/boost/spirit/home/support/attributes.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/attributes.hpp (original)
+++ branches/release/boost/spirit/home/support/attributes.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -21,6 +21,7 @@
 #include <boost/fusion/include/filter_if.hpp>
 #include <boost/fusion/include/as_vector.hpp>
 #include <boost/fusion/include/push_front.hpp>
+#include <boost/fusion/include/pop_front.hpp>
 #include <boost/fusion/include/is_sequence.hpp>
 #include <boost/fusion/include/for_each.hpp>
 #include <boost/utility/value_init.hpp>
@@ -53,6 +54,34 @@
       : mpl::false_
     {};
 
+ template <typename T>
+ struct not_is_variant<boost::optional<T> >
+ : not_is_variant<T>
+ {};
+
+ // we treat every type as if it where the variant (as this meta function is
+ // invoked for variant types only)
+ template <typename T>
+ struct variant_type
+ : mpl::identity<T>
+ {};
+
+ template <typename T>
+ struct variant_type<boost::optional<T> >
+ : variant_type<T>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct not_is_optional
+ : mpl::true_
+ {};
+
+ template <typename T>
+ struct not_is_optional<boost::optional<T> >
+ : mpl::false_
+ {};
+
     ///////////////////////////////////////////////////////////////////////////
     // attribute_of
     //
@@ -256,7 +285,59 @@
             typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type
           , typename mpl::end<Sequence>::type>
     {};
+
+ namespace detail
+ {
+ template <typename Sequence, bool no_unused
+ , int size = mpl::size<Sequence>::value>
+ struct build_collapsed_variant;
+
+ // N element case, no unused
+ template <typename Sequence, int size>
+ struct build_collapsed_variant<Sequence, true, size>
+ : spirit::detail::as_variant<Sequence> {};
+
+ // N element case with unused
+ template <typename Sequence, int size>
+ struct build_collapsed_variant<Sequence, false, size>
+ {
+ typedef optional<
+ typename spirit::detail::as_variant<
+ typename fusion::result_of::pop_front<Sequence>::type
+ >::type
+ > type;
+ };
 
+ // 1 element case, no unused
+ template <typename Sequence>
+ struct build_collapsed_variant<Sequence, true, 1>
+ : mpl::front<Sequence> {};
+
+ // 1 element case, with unused
+ template <typename Sequence>
+ struct build_collapsed_variant<Sequence, false, 1>
+ : mpl::front<Sequence> {};
+
+ // 2 element case, no unused
+ template <typename Sequence>
+ struct build_collapsed_variant<Sequence, true, 2>
+ : spirit::detail::as_variant<Sequence> {};
+
+ // 2 element case, with unused
+ template <typename Sequence>
+ struct build_collapsed_variant<Sequence, false, 2>
+ {
+ typedef optional<
+ typename mpl::deref<
+ typename mpl::next<
+ typename mpl::begin<Sequence>::type
+ >::type
+ >::type
+ >
+ type;
+ };
+ }
+
     ///////////////////////////////////////////////////////////////////////////
     // build_variant
     //
@@ -264,7 +345,7 @@
     // that 1) all attributes in the variant are unique 2) puts the unused
     // attribute, if there is any, to the front and 3) collapses single element
     // variants, variant<T> to T.
- ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
     template <typename Sequence>
     struct build_variant
     {
@@ -272,6 +353,8 @@
         typedef typename
             filter_unused_attributes<Sequence>::type
         filtered_attributes;
+
+ typedef has_no_unused<Sequence> no_unused;
 
         // If the original attribute list does not contain any unused
         // attributes, it is used, otherwise a single unused_type is
@@ -279,7 +362,7 @@
         // there is an unused_type in the list, it is the first one.
         typedef typename
             mpl::eval_if<
- has_no_unused<Sequence>,
+ no_unused,
                 mpl::identity<Sequence>,
                 fusion::result_of::push_front<filtered_attributes, unused_type>
>::type
@@ -294,16 +377,14 @@
                     mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
>
>::type
- new_sequence;
+ no_duplicates;
 
         // If there is only one type in the list of types we strip off the
         // variant. IOTW, collapse single element variants, variant<T> to T.
+ // Take note that this also collapses variant<unused_type, T> to T.
         typedef typename
- mpl::eval_if<
- mpl::equal_to<mpl::size<new_sequence>, mpl::int_<1> >,
- mpl::deref<mpl::front<attribute_sequence> >,
- spirit::detail::as_variant<new_sequence>
- >::type
+ traits::detail::build_collapsed_variant<
+ no_duplicates, no_unused::value>::type
         type;
     };
 
@@ -682,4 +763,5 @@
     {};
 }}}
 
+
 #endif

Modified: branches/release/boost/spirit/home/support/container.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/container.hpp (original)
+++ branches/release/boost/spirit/home/support/container.hpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -340,7 +340,7 @@
         }
     };
 
- template <typename Container>
+ template <typename Container>
     typename spirit::result_of::begin<Container>::type
     begin(Container& c)
     {
@@ -404,23 +404,21 @@
     template <typename Iterator, typename Enable/* = void*/>
     struct next_iterator
     {
- static Iterator call(Iterator& it)
+ static void call(Iterator& it)
         {
- return ++it;
+ ++it;
         }
     };
 
     template <typename Iterator>
- typename spirit::result_of::next<Iterator>::type
- next(Iterator& it)
+ void next(Iterator& it)
     {
- return next_iterator<Iterator>::call(it);
+ next_iterator<Iterator>::call(it);
     }
 
- inline unused_type const*
- next(unused_type const*)
+ inline void next(unused_type const*)
     {
- return &unused;
+ // do nothing
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -491,16 +489,16 @@
     {};
 
     template <typename Iterator>
- struct next
- {
- typedef Iterator type;
- };
-
- template <typename Iterator>
     struct deref
       : traits::deref_iterator<Iterator>
     {};
 
+ template <>
+ struct deref<unused_type const*>
+ {
+ typedef unused_type type;
+ };
+
 }}}
 
 #endif

Modified: branches/release/libs/spirit/test/karma/alternative.cpp
==============================================================================
--- branches/release/libs/spirit/test/karma/alternative.cpp (original)
+++ branches/release/libs/spirit/test/karma/alternative.cpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -15,6 +15,7 @@
 #include <boost/spirit/include/karma_generate.hpp>
 #include <boost/spirit/include/karma_operator.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
 
 #include "test.hpp"
 
@@ -51,6 +52,49 @@
     // testing for alignment/truncation problems on little endian systems
     // (big endian systems will fail one of the other tests below)
     {
+ // test optional attribute
+ optional<variant<int, char> > v;
+ BOOST_TEST(!test("", char_ | int_, v));
+ BOOST_TEST(!test("", int_ | char_, v));
+ BOOST_TEST(test("a", lit('a') | char_ | int_, v));
+ BOOST_TEST(test("a", char_ | lit('a') | int_, v));
+ BOOST_TEST(test("a", int_ | lit('a') | char_, v));
+
+ v = 10;
+ BOOST_TEST(test("10", char_ | int_, v));
+ BOOST_TEST(test("10", int_ | char_, v));
+ BOOST_TEST(test("a", lit('a') | char_ | int_, v));
+ BOOST_TEST(test("a", char_ | lit('a') | int_, v));
+ BOOST_TEST(test("10", int_ | lit('a') | char_, v));
+
+ v = 'c';
+ BOOST_TEST(test("c", char_ | int_, v));
+ BOOST_TEST(test("a", lit('a') | char_ | int_, v));
+ BOOST_TEST(test("c", char_ | lit('a') | int_, v));
+ BOOST_TEST(test("a", int_ | lit('a') | char_, v));
+ BOOST_TEST(test("c", int_ | char_ | lit('a'), v));
+ }
+
+ {
+ // more tests for optional attribute
+ optional<int> o;
+ BOOST_TEST(test("a", lit('a') | int_, o));
+ BOOST_TEST(test("a", int_ | lit('a'), o));
+
+ o = 10;
+ BOOST_TEST(test("a", lit('a') | int_, o));
+ BOOST_TEST(test("10", int_ | lit('a'), o));
+ }
+
+ {
+ int i = 10;
+ BOOST_TEST(test("a", lit('a') | int_, i));
+ BOOST_TEST(test("10", int_ | lit('a'), i));
+ }
+
+ {
+ // testing for alignment/truncation problems on little endian systems
+ // (big endian systems will fail one of the other tests below)
         std::basic_string<wchar_t> generated;
         std::back_insert_iterator<std::basic_string<wchar_t> > outit(generated);
         boost::variant<int, char> v(10);
@@ -90,6 +134,7 @@
         BOOST_TEST(test_delimited("c ", int_ | char_ | lit('a'), v, char_(' ')));
     }
 
+// this leads to infinite loops
 // {
 // variant<int, std::string> v(10);
 // BOOST_TEST(test("10", int_ | +char_, v));
@@ -129,6 +174,22 @@
     }
 
     {
+ // if nothing matches, the first explicit alternative will be chosen,
+ // optionals need to be accepted
+ optional<variant<double, char const*> > v (10.0);
+ BOOST_TEST(test_delimited("11 ", char_ | lit(11), v, char_(' ')));
+ BOOST_TEST(test_delimited("11 ", lit(11) | char_ , v, char_(' ')));
+ BOOST_TEST(test_delimited("10.0 ", double_ | lit(11), v, char_(' ')));
+ BOOST_TEST(test_delimited("11 ", lit(11) | double_, v, char_(' ')));
+ BOOST_TEST(!test_delimited("", char_ | int_, v, char_(' ')));
+
+ v = "c";
+ BOOST_TEST(test_delimited("11 ", char_ | lit(11), v, char_(' ')));
+ BOOST_TEST(test_delimited("11 ", double_ | lit(11), v, char_(' ')));
+ BOOST_TEST(!test_delimited("", char_ | int_, v, char_(' ')));
+ }
+
+ {
         std::vector<int> v;
         BOOST_TEST(test("[]", '[' << (int_ % ", ") << ']' | "[]", v));
         BOOST_TEST(test("[]", '[' << -(int_ % ", ") << ']', v));
@@ -149,6 +210,21 @@
         BOOST_TEST(test("1", int_ | "error" << omit[int_], v));
     }
 
+ {
+ typedef spirit_test::output_iterator<char>::type outiter_type;
+ namespace karma = boost::spirit::karma;
+
+ karma::rule<outiter_type, int()> r = int_;
+ std::vector<int> v;
+ BOOST_TEST(test("", '>' << r % ',' | karma::eps, v));
+
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(3);
+ v.push_back(4);
+ BOOST_TEST(test(">1,2,3,4", '>' << r % ',' | karma::eps, v));
+ }
+
     return boost::report_errors();
 }
 

Modified: branches/release/libs/spirit/test/qi/alternative.cpp
==============================================================================
--- branches/release/libs/spirit/test/qi/alternative.cpp (original)
+++ branches/release/libs/spirit/test/qi/alternative.cpp 2009-10-26 20:41:58 EDT (Mon, 26 Oct 2009)
@@ -43,8 +43,7 @@
 
 struct test_action_2
 {
- typedef std::vector<boost::variant<boost::spirit::unused_type, char> >
- result_type;
+ typedef std::vector<boost::optional<char> > result_type;
 
     void operator()(result_type const& v
       , boost::spirit::unused_type
@@ -53,11 +52,10 @@
         using boost::get;
 
         BOOST_TEST(v.size() == 5 &&
- v[0].which() == 0 &&
- v[1].which() == 1 && get<char>(v[1]) == 'a' &&
- v[2].which() == 1 && get<char>(v[2]) == 'b' &&
- v[3].which() == 1 && get<char>(v[3]) == '1' &&
- v[4].which() == 1 && get<char>(v[4]) == '2');
+ v[1] == 'a' &&
+ v[2] == 'b' &&
+ v[3] == '1' &&
+ v[4] == '2');
     }
 };
 
@@ -101,11 +99,13 @@
 
     { // test action
 
- namespace phoenix = boost::phoenix;
- boost::variant<unused_type, int, char> v;
+ namespace phx = boost::phoenix;
+ boost::optional<boost::variant<int, char> > v;
 
- BOOST_TEST((test("12345", (lit("rock") | int_ | char_)[phoenix::ref(v) = _1])));
- BOOST_TEST(boost::get<int>(v) == 12345);
+ BOOST_TEST((test("12345", (lit("rock") | int_ | char_)[phx::ref(v) = _1])));
+ BOOST_TEST(boost::get<int>(boost::get(v)) == 12345);
+ BOOST_TEST((test("rock", (lit("rock") | int_ | char_)[phx::ref(v) = _1])));
+ BOOST_TEST(!v);
     }
 
     {
@@ -158,11 +158,22 @@
         using boost::spirit::ascii::alnum;
         using boost::spirit::ascii::alpha;
         using boost::spirit::ascii::digit;
+ using boost::spirit::ascii::string;
+ namespace phx = boost::phoenix;
+
+
+ BOOST_TEST( (test("ab1_", (*(alnum | char_('_')))[test_action('_')])) );
+ BOOST_TEST( (test("ab12", (*(alpha | digit))[test_action('2')])) );
 
- BOOST_TEST( (test("ab1_", lexeme[*(alnum | char_('_'))][test_action('_')])) );
- BOOST_TEST( (test("ab12", lexeme[*(alpha | digit)][test_action('2')])) );
+ BOOST_TEST( (test("abcab12", (*("abc" | alnum))[test_action_2()])) );
 
- BOOST_TEST( (test("abcab12", lexeme[*("abc" | alnum)][test_action_2()])) );
+ std::vector<boost::optional<char> > v;
+ BOOST_TEST( (test("x,y,z", (*(',' | char_))[phx::ref(v) = _1])) );
+ assert(v[0] == 'x');
+ assert(!v[1]);
+ assert(v[2] == 'y');
+ assert(!v[3]);
+ assert(v[4] == 'z');
     }
 
     {


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