|
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