|
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