Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r57122 - in trunk/boost/spirit/home: karma/binary karma/char karma/detail karma/directive karma/numeric karma/operator karma/stream karma/string qi/operator support
From: hartmut.kaiser_at_[hidden]
Date: 2009-10-23 23:03:25


Author: hkaiser
Date: 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
New Revision: 57122
URL: http://svn.boost.org/trac/boost/changeset/57122

Log:
Spirit: more work on attribute traits, allowing optional for alternatives, maxwidth supports extracting overhang
Text files modified:
   trunk/boost/spirit/home/karma/binary/binary.hpp | 10 +
   trunk/boost/spirit/home/karma/char/char.hpp | 10 ++
   trunk/boost/spirit/home/karma/char/char_class.hpp | 4 +
   trunk/boost/spirit/home/karma/char/char_generator.hpp | 2
   trunk/boost/spirit/home/karma/detail/alternative_function.hpp | 9 +
   trunk/boost/spirit/home/karma/detail/extract_from.hpp | 64 +++++++++-------
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp | 35 +++++---
   trunk/boost/spirit/home/karma/detail/pass_container.hpp | 11 +-
   trunk/boost/spirit/home/karma/directive/maxwidth.hpp | 69 +++++++++---------
   trunk/boost/spirit/home/karma/numeric/bool.hpp | 12 ++-
   trunk/boost/spirit/home/karma/numeric/int.hpp | 14 ++-
   trunk/boost/spirit/home/karma/numeric/real.hpp | 19 ++--
   trunk/boost/spirit/home/karma/numeric/uint.hpp | 14 ++-
   trunk/boost/spirit/home/karma/operator/alternative.hpp | 51 ++++++++++++
   trunk/boost/spirit/home/karma/stream/stream.hpp | 16 ++-
   trunk/boost/spirit/home/karma/string/lit.hpp | 10 +-
   trunk/boost/spirit/home/qi/operator/optional.hpp | 2
   trunk/boost/spirit/home/support/attributes.hpp | 45 ++++++++---
   trunk/boost/spirit/home/support/attributes_fwd.hpp | 22 +++++
   trunk/boost/spirit/home/support/container.hpp | 149 +++++++++++++++++----------------------
   20 files changed, 349 insertions(+), 219 deletions(-)

Modified: trunk/boost/spirit/home/karma/binary/binary.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary/binary.hpp (original)
+++ trunk/boost/spirit/home/karma/binary/binary.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/char/char.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/char/char.hpp (original)
+++ trunk/boost/spirit/home/karma/char/char.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/char/char_class.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/char/char_class.hpp (original)
+++ trunk/boost/spirit/home/karma/char/char_class.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/char/char_generator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/char/char_generator.hpp (original)
+++ trunk/boost/spirit/home/karma/char/char_generator.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/alternative_function.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/alternative_function.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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
@@ -162,7 +163,9 @@
 
             // 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 +173,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: 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 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -18,6 +18,7 @@
 #include <boost/ref.hpp>
 #include <boost/optional.hpp>
 
+///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
@@ -31,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;
         }
@@ -42,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);
         }
@@ -52,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);
         }
@@ -63,46 +70,49 @@
     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();
         }
     };
 
     ///////////////////////////////////////////////////////////////////////////
- namespace result_of
+ template <typename Attribute, typename Context>
+ typename spirit::result_of::extract_from<Attribute>::type
+ extract_from(Attribute const& attr, Context& context)
     {
- template <typename Attribute>
- struct extract_from
- : traits::extract_from_attribute<Attribute>
- {};
+ return extract_from_attribute<Attribute>::call(attr, context);
+ };
 
- template <>
- struct extract_from<unused_type>
- {
- typedef unused_type type;
- };
+ template <typename Context>
+ unused_type extract_from(unused_type, Context&)
+ {
+ return unused;
+ };
 
- template <>
- struct extract_from<unused_type const>
- {
- typedef unused_type type;
- };
- }
+}}}
 
- ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace result_of
+{
     template <typename Attribute>
- typename extract_from_attribute<Attribute>::type
- extract_from(Attribute const& attr)
+ struct extract_from
+ : traits::extract_from_attribute<Attribute>
+ {};
+
+ template <>
+ struct extract_from<unused_type>
     {
- return extract_from_attribute<Attribute>::call(attr);
+ typedef unused_type type;
     };
 
- inline unused_type extract_from(unused_type)
+ template <>
+ struct extract_from<unused_type const>
     {
- return unused;
+ typedef unused_type type;
     };
-
 }}}
 
 #endif

Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -25,9 +25,9 @@
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
- // has_same_elements: utility to check if the RHS attribute
+ // has_same_elements: utility to check if the LHS attribute
     // is an STL container and that its value_type is convertible
- // to the LHS.
+ // to the RHS.
 
     template <typename RHS, typename LHSAttribute
       , bool IsContainer = traits::is_container<LHSAttribute>::value>
@@ -77,8 +77,7 @@
             // get the next value to generate from container
             typename traits::container_iterator<Attr>::type end =
                 traits::end(attr);
- if (!traits::compare(iter, end) &&
- !f(component, traits::deref(iter)))
+ if (!traits::compare(iter, end) && !f(component, traits::deref(iter)))
             {
                 // needs to return false as long as everything is ok
                 traits::next(iter);
@@ -147,7 +146,9 @@
         template <typename Component>
         bool dispatch_main(Component const& component, mpl::true_) const
         {
- bool result = f(component, make_iterator_range(iter, traits::end(attr)));
+ typename traits::container_iterator<Attr>::type end =
+ traits::end(attr);
+ bool result = f(component, make_iterator_range(iter, end));
             if (result)
                 iter = traits::end(attr); // adjust current iter to the end
             return result;

Modified: trunk/boost/spirit/home/karma/directive/maxwidth.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/maxwidth.hpp (original)
+++ trunk/boost/spirit/home/karma/directive/maxwidth.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 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&t
+ 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/alternative.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/alternative.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 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: trunk/boost/spirit/home/karma/string/lit.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/lit.hpp (original)
+++ trunk/boost/spirit/home/karma/string/lit.hpp 2009-10-23 23:03:23 EDT (Fri, 23 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: 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 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -61,7 +61,7 @@
           , Attribute& attr) const
         {
             // create a local value if Attribute is not unused_type
- typename traits::result_of::optional_value<Attribute>::type val;
+ typename spirit::result_of::optional_value<Attribute>::type val;
 
             if (subject.parse(first, last, context, skipper, val))
             {

Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -35,6 +35,7 @@
 #include <vector>
 #include <utility>
 
+///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
@@ -52,14 +53,33 @@
     struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
       : mpl::false_
     {};
-
+
+ template <typename T>
+ struct not_is_variant<boost::optional<T> >
+ : not_is_variant<T>
+ {};
+
+ template <typename T>
+ struct variant_type;
+
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+ struct variant_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+ : mpl::identity<boost::variant<BOOST_VARIANT_ENUM_PARAMS(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_variant<boost::optional<T> >
+ struct not_is_optional<boost::optional<T> >
       : mpl::false_
     {};
 
@@ -485,23 +505,15 @@
     {};
 
     ///////////////////////////////////////////////////////////////////////////
- namespace result_of
- {
- template <typename Exposed, typename Transformed>
- struct pre_transform
- : traits::transform_attribute<Exposed, Transformed>
- {};
- }
-
     template <typename Transformed, typename Exposed>
- typename traits::result_of::pre_transform<Exposed, Transformed>::type
+ typename spirit::result_of::pre_transform<Exposed, Transformed>::type
     pre_transform(Exposed& attr)
     {
         return transform_attribute<Exposed, Transformed>::pre(attr);
     }
 
     template <typename Transformed, typename Exposed>
- typename traits::result_of::pre_transform<Exposed const, Transformed>::type
+ typename spirit::result_of::pre_transform<Exposed const, Transformed>::type
     pre_transform(Exposed const& attr)
     {
         return transform_attribute<Exposed const, Transformed>::pre(attr);
@@ -741,7 +753,16 @@
     inline void clear(unused_type)
     {
     }
+}}}
 
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace result_of
+{
+ template <typename Exposed, typename Transformed>
+ struct pre_transform
+ : traits::transform_attribute<Exposed, Transformed>
+ {};
 }}}
 
+
 #endif

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 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -87,7 +87,29 @@
 
     template <typename Iterator, typename Enable = void>
     struct compare_iterators;
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace result_of
+{
+ // forward declaration only
+ template <typename Attribute>
+ struct extract_from;
+
+ template <typename Exposed, typename Transformed>
+ struct pre_transform;
+
+ template <typename T>
+ struct optional_value;
+
+ template <typename Container>
+ struct begin;
+
+ template <typename Container>
+ struct end;
 
+ template <typename Iterator>
+ struct deref;
 }}}
 
 #endif

Modified: trunk/boost/spirit/home/support/container.hpp
==============================================================================
--- trunk/boost/spirit/home/support/container.hpp (original)
+++ trunk/boost/spirit/home/support/container.hpp 2009-10-23 23:03:23 EDT (Fri, 23 Oct 2009)
@@ -70,40 +70,6 @@
 
 #undef BOOST_SPIRIT_IS_CONTAINER
 
- namespace result_of
- {
- ///////////////////////////////////////////////////////////////////////
- template <typename T>
- struct optional_value
- {
- typedef T type;
- };
-
- template <typename T>
- struct optional_value<optional<T> >
- {
- typedef T type;
- };
-
- template <typename T>
- struct optional_value<optional<T> const>
- {
- typedef T const type;
- };
-
- template <>
- struct optional_value<unused_type>
- {
- typedef unused_type type;
- };
-
- template <>
- struct optional_value<unused_type const>
- {
- typedef unused_type type;
- };
- }
-
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
     {
@@ -368,23 +334,14 @@
     template <typename Container, typename Enable/* = void*/>
     struct begin_container
     {
- typedef typename container_iterator<Container>::type type;
- static type call(Container& c)
+ static typename container_iterator<Container>::type call(Container& c)
         {
             return c.begin();
         }
     };
 
- namespace result_of
- {
- template <typename Container>
- struct begin
- : traits::container_iterator<Container>
- {};
- }
-
     template <typename Container>
- typename begin_container<Container>::type
+ typename spirit::result_of::begin<Container>::type
     begin(Container& c)
     {
         return begin_container<Container>::call(c);
@@ -400,23 +357,14 @@
     template <typename Container, typename Enable/* = void*/>
     struct end_container
     {
- typedef typename container_iterator<Container>::type type;
- static type call(Container& c)
+ static typename container_iterator<Container>::type call(Container& c)
         {
             return c.end();
         }
     };
 
- namespace result_of
- {
- template <typename Container>
- struct end
- : traits::container_iterator<Container>
- {};
- }
-
     template <typename Container>
- inline typename end_container<Container>::type
+ inline typename spirit::result_of::end<Container>::type
     end(Container& c)
     {
         return end_container<Container>::call(c);
@@ -439,14 +387,6 @@
         }
     };
 
- namespace result_of
- {
- template <typename Iterator>
- struct deref
- : traits::deref_iterator<Iterator>
- {};
- }
-
     template <typename Iterator>
     typename deref_iterator<Iterator>::type
     deref(Iterator& it)
@@ -464,33 +404,21 @@
     template <typename Iterator, typename Enable/* = void*/>
     struct next_iterator
     {
- typedef Iterator type;
- static type call(Iterator& it)
+ static void call(Iterator& it)
         {
- return ++it;
+ ++it;
         }
     };
 
- namespace result_of
- {
- template <typename Iterator>
- struct next
- {
- typedef Iterator type;
- };
- }
-
     template <typename Iterator>
- typename next_iterator<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
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -513,6 +441,63 @@
     {
         return false;
     }
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace result_of
+{
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct optional_value
+ {
+ typedef T type;
+ };
+
+ template <typename T>
+ struct optional_value<optional<T> >
+ {
+ typedef T type;
+ };
+
+ template <typename T>
+ struct optional_value<optional<T> const>
+ {
+ typedef T const type;
+ };
+
+ template <>
+ struct optional_value<unused_type>
+ {
+ typedef unused_type type;
+ };
+
+ template <>
+ struct optional_value<unused_type const>
+ {
+ typedef unused_type type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Container>
+ struct begin
+ : traits::container_iterator<Container>
+ {};
+
+ template <typename Container>
+ struct end
+ : traits::container_iterator<Container>
+ {};
+
+ template <typename Iterator>
+ struct deref
+ : traits::deref_iterator<Iterator>
+ {};
+
+ template <>
+ struct deref<unused_type const*>
+ {
+ typedef unused_type type;
+ };
 
 }}}
 


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