|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r68645 - in trunk: boost/spirit/home/karma/auto boost/spirit/home/karma/detail boost/spirit/home/karma/numeric boost/spirit/home/karma/operator boost/spirit/home/karma/stream boost/spirit/home/qi/detail boost/spirit/home/qi/directive boost/spirit/home/qi/numeric boost/spirit/home/qi/operator boost/spirit/home/qi/stream boost/spirit/home/support boost/spirit/home/support/detail boost/spirit/home/support/utree libs/spirit/doc libs/spirit/test libs/spirit/test/karma libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2011-02-04 22:48:58
Author: hkaiser
Date: 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
New Revision: 68645
URL: http://svn.boost.org/trac/boost/changeset/68645
Log:
Spirit: unified handling of sequences and container components for container attributes, modified hold_any to enable streaming with wchar_t, added extract_from_container CP, fixed integral generators for const data types
Added:
trunk/libs/spirit/test/karma/regression_const_real_policies.cpp (contents, props changed)
Text files modified:
trunk/boost/spirit/home/karma/auto/auto.hpp | 2
trunk/boost/spirit/home/karma/detail/attributes.hpp | 2
trunk/boost/spirit/home/karma/detail/extract_from.hpp | 122 ++++++++++++++++++++++++++++++++++++-
trunk/boost/spirit/home/karma/detail/pass_container.hpp | 59 ++++++++++++++++-
trunk/boost/spirit/home/karma/numeric/bool.hpp | 6 +
trunk/boost/spirit/home/karma/numeric/int.hpp | 9 +-
trunk/boost/spirit/home/karma/numeric/real.hpp | 9 +-
trunk/boost/spirit/home/karma/numeric/uint.hpp | 8 +-
trunk/boost/spirit/home/karma/operator/kleene.hpp | 67 +++++++++++++------
trunk/boost/spirit/home/karma/operator/list.hpp | 76 +++++++++++++---------
trunk/boost/spirit/home/karma/operator/optional.hpp | 4
trunk/boost/spirit/home/karma/operator/plus.hpp | 85 +++++++++++++++++--------
trunk/boost/spirit/home/karma/operator/sequence.hpp | 83 +-----------------------
trunk/boost/spirit/home/karma/stream/stream.hpp | 2
trunk/boost/spirit/home/qi/detail/assign_to.hpp | 12 +-
trunk/boost/spirit/home/qi/detail/pass_container.hpp | 36 +++++++++-
trunk/boost/spirit/home/qi/directive/repeat.hpp | 90 ++++++--------------------
trunk/boost/spirit/home/qi/numeric/int.hpp | 20 +++---
trunk/boost/spirit/home/qi/operator/expect.hpp | 5
trunk/boost/spirit/home/qi/operator/kleene.hpp | 37 ++++++----
trunk/boost/spirit/home/qi/operator/list.hpp | 47 ++++++++-----
trunk/boost/spirit/home/qi/operator/optional.hpp | 33 ++++++++-
trunk/boost/spirit/home/qi/operator/plus.hpp | 44 +++++++------
trunk/boost/spirit/home/qi/operator/sequence.hpp | 5
trunk/boost/spirit/home/qi/operator/sequence_base.hpp | 1
trunk/boost/spirit/home/qi/stream/stream.hpp | 2
trunk/boost/spirit/home/support/attributes.hpp | 5
trunk/boost/spirit/home/support/attributes_fwd.hpp | 3
trunk/boost/spirit/home/support/container.hpp | 2
trunk/boost/spirit/home/support/detail/hold_any.hpp | 130 +++++++++++++++++++++++----------------
trunk/boost/spirit/home/support/utree/operators.hpp | 1
trunk/boost/spirit/home/support/utree/utree_traits.hpp | 44 +++++++++---
trunk/libs/spirit/doc/what_s_new.qbk | 4
trunk/libs/spirit/test/Jamfile | 1
trunk/libs/spirit/test/karma/kleene.cpp | 53 ++++++++++++++++
trunk/libs/spirit/test/karma/list.cpp | 7 ++
trunk/libs/spirit/test/karma/lit.cpp | 4 +
trunk/libs/spirit/test/karma/plus.cpp | 49 +++++++++++++++
trunk/libs/spirit/test/karma/repeat2.cpp | 9 ++
trunk/libs/spirit/test/karma/stream.cpp | 2
trunk/libs/spirit/test/karma/utree2.cpp | 4
trunk/libs/spirit/test/karma/wstream.cpp | 2
trunk/libs/spirit/test/qi/alternative.cpp | 8 ++
trunk/libs/spirit/test/qi/debug.cpp | 2
trunk/libs/spirit/test/qi/kleene.cpp | 8 --
trunk/libs/spirit/test/qi/list.cpp | 15 ++++
trunk/libs/spirit/test/qi/optional.cpp | 6 +
trunk/libs/spirit/test/qi/plus.cpp | 8 --
trunk/libs/spirit/test/qi/regression_repeat.cpp | 10 +-
trunk/libs/spirit/test/qi/repeat.cpp | 46 +++++++++++---
trunk/libs/spirit/test/qi/sequence.cpp | 33 +++++++++
trunk/libs/spirit/test/qi/utree1.cpp | 12 +--
trunk/libs/spirit/test/qi/utree2.cpp | 5
53 files changed, 882 insertions(+), 457 deletions(-)
Modified: trunk/boost/spirit/home/karma/auto/auto.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auto/auto.hpp (original)
+++ trunk/boost/spirit/home/karma/auto/auto.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -60,7 +60,7 @@
template <typename Context, typename Unused>
struct attribute
{
- typedef spirit::hold_any type;
+ typedef spirit::basic_hold_any<char> type;
};
auto_generator(Modifiers const& modifiers)
Modified: trunk/boost/spirit/home/karma/detail/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/attributes.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/attributes.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -20,7 +20,7 @@
typedef Transformed type;
static Transformed pre(Exposed& val)
{
- return Transformed(traits::extract_from<Exposed>(val, unused));
+ return Transformed(traits::extract_from<Transformed>(val, unused));
}
// Karma only, no post() and no fail() required
};
Modified: trunk/boost/spirit/home/karma/detail/extract_from.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/extract_from.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/extract_from.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -117,8 +117,109 @@
};
///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Exposed, typename Enable>
+ struct extract_from_container
+ {
+ typedef typename traits::container_value<Attribute const>::type
+ value_type;
+ typedef typename is_convertible<value_type, Exposed>::type
+ is_convertible_to_value_type;
+
+ typedef typename mpl::if_<
+ mpl::or_<
+ is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
+ , Exposed const&, Exposed
+ >::type type;
+
+ // handle case where container value type is convertible to result type
+ // we simply return the front element of the container
+ template <typename Context, typename Pred>
+ static type call(Attribute const& attr, Context& ctx, mpl::true_, Pred)
+ {
+ // return first element from container
+ typedef typename traits::container_iterator<Attribute const>::type
+ iterator_type;
+
+ iterator_type it = boost::begin(attr);
+ type result = *it;
+ ++it;
+ return result;
+ }
+
+ // handle strings
+ template <typename Iterator>
+ static void append_to_string(Exposed& result, Iterator begin, Iterator end)
+ {
+ for (Iterator i = begin; i != end; ++i)
+ push_back(result, *i);
+ }
+
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx, mpl::false_, mpl::true_)
+ {
+ typedef typename char_type_of<Attribute>::type char_type;
+
+ Exposed result;
+ append_to_string(result, traits::get_begin<char_type>(attr)
+ , traits::get_end<char_type>(attr));
+ return result;
+ }
+
+ // everything else gets just passed through
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx, mpl::false_, mpl::false_)
+ {
+ return type(attr);
+ }
+
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx)
+ {
+ typedef typename mpl::and_<
+ traits::is_string<Exposed>, traits::is_string<Attribute>
+ >::type handle_strings;
+
+ // return first element from container
+ return call(attr, ctx, is_convertible_to_value_type()
+ , handle_strings());
+ }
+ };
+
+ template <typename Attribute>
+ struct extract_from_container<Attribute, Attribute>
+ {
+ typedef Attribute const& type;
+
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx)
+ {
+ return attr;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ // overload for non-container attributes
+ template <typename Exposed, typename Attribute, typename Context>
+ inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
+ extract_from(Attribute const& attr, Context& ctx, mpl::false_)
+ {
+ return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
+ }
+
+ // overload for containers (but not for variants or optionals
+ // holding containers)
+ template <typename Exposed, typename Attribute, typename Context>
+ inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
+ extract_from(Attribute const& attr, Context& ctx, mpl::true_)
+ {
+ return extract_from_container<Attribute, Exposed>::call(attr, ctx);
+ }
+ }
+
template <typename Exposed, typename Attribute, typename Context>
- typename spirit::result_of::extract_from<Exposed, Attribute>::type
+ inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx
#if (defined(__GNUC__) && (__GNUC__ < 4)) || \
(defined(__APPLE__) && defined(__INTEL_COMPILER))
@@ -126,11 +227,18 @@
#endif
)
{
- return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
+ typedef typename mpl::and_<
+ traits::is_container<Attribute>
+ , traits::not_is_variant<Attribute>
+ , traits::not_is_optional<Attribute>
+ >::type is_not_wrapped_container;
+
+ return detail::extract_from<Exposed>(attr, ctx
+ , is_not_wrapped_container());
}
template <typename Exposed, typename Context>
- unused_type extract_from(unused_type, Context&)
+ inline unused_type extract_from(unused_type, Context&)
{
return unused;
}
@@ -141,7 +249,13 @@
{
template <typename Exposed, typename Attribute>
struct extract_from
- : traits::extract_from_attribute<Attribute, Exposed>
+ : mpl::if_<
+ mpl::and_<
+ traits::is_container<Attribute>
+ , traits::not_is_variant<Attribute>
+ , traits::not_is_optional<Attribute> >
+ , traits::extract_from_container<Attribute, Exposed>
+ , traits::extract_from_attribute<Attribute, Exposed> >::type
{};
template <typename Exposed>
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -32,18 +32,27 @@
// to the RHS.
template <typename RHS, typename LHSAttribute
- , bool IsContainer = traits::is_container<LHSAttribute>::value>
+ , bool IsContainer = traits::is_container<LHSAttribute>::value
+ , bool IsSequence = fusion::traits::is_sequence<LHSAttribute>::value>
struct has_same_elements : mpl::false_ {};
template <typename RHS, typename LHSAttribute>
- struct has_same_elements<RHS, LHSAttribute, true>
+ struct has_same_elements<RHS, LHSAttribute, true, false>
: mpl::or_<
is_convertible<RHS, typename LHSAttribute::value_type>
- , is_same<typename LHSAttribute::value_type, hold_any>
+ , traits::is_hold_any<typename LHSAttribute::value_type>
> {};
template <typename RHS, typename T>
- struct has_same_elements<RHS, optional<T>, true>
+ struct has_same_elements<RHS, optional<T>, false, false>
+ : has_same_elements<RHS, T> {};
+
+ template <typename RHS, typename T>
+ struct has_same_elements<RHS, optional<T>, true, false>
+ : has_same_elements<RHS, T> {};
+
+ template <typename RHS, typename T>
+ struct has_same_elements<RHS, optional<T>, false, true>
: has_same_elements<RHS, T> {};
#define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data) \
@@ -54,12 +63,26 @@
// container (see support/container.hpp).
template <typename RHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct has_same_elements<
- RHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true>
+ RHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true, false>
: mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
, BOOST_SPIRIT_IS_CONVERTIBLE, _) false> {};
#undef BOOST_SPIRIT_IS_CONVERTIBLE
+ // Specialization for fusion sequences, in this case we check whether the
+ // lhs attribute is convertible to the types in the sequence.
+ // We return false if the rhs attribute itself is a fusion sequence.
+ template <typename RHS, typename LHSAttribute>
+ struct has_same_elements<RHS, LHSAttribute, false, true>
+ {
+ typedef typename mpl::find_if<
+ LHSAttribute, mpl::not_<is_convertible<RHS, mpl::_1> >
+ >::type iter;
+ typedef typename mpl::end<LHSAttribute>::type end;
+
+ typedef typename is_same<iter, end>::type type;
+ };
+
///////////////////////////////////////////////////////////////////////////
// This function handles the case where the attribute (Attr) given
// to the sequence is an STL container. This is a wrapper around F.
@@ -73,18 +96,34 @@
: f(f), iter(begin), end(end)
{}
+ bool is_at_end() const
+ {
+ return traits::compare(iter, end);
+ }
+
+ void next()
+ {
+ traits::next(iter);
+ }
+
// this is for the case when the current element expects an attribute
// which is taken from the next entry in the container
template <typename Component>
bool dispatch_attribute_element(Component const& component, mpl::false_) const
{
// get the next value to generate from container
- if (!traits::compare(iter, end) && !f(component, traits::deref(iter)))
+ if (!is_at_end() && !f(component, traits::deref(iter)))
{
// needs to return false as long as everything is ok
traits::next(iter);
return false;
}
+
+// // in non-strict mode increment iterator if the underlying
+// // generator failed
+// if (!Strict::value && !is_at_end())
+// traits::next(iter);
+
// either no elements available any more or generation failed
return true;
}
@@ -180,6 +219,14 @@
// silence MSVC warning C4512: assignment operator could not be generated
pass_container& operator= (pass_container const&);
};
+
+ // Utility function to make a pass_container
+ template <typename Strict, typename F, typename Attr, typename Iterator>
+ pass_container<F, Attr, Iterator, Strict>
+ inline make_pass_container(F const& f, Attr& attr, Iterator b, Iterator e)
+ {
+ return pass_container<F, Attr, Iterator, Strict>(f, attr, b, e);
+ }
}}}}
#endif
Modified: trunk/boost/spirit/home/karma/numeric/bool.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/bool.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/bool.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -312,7 +312,8 @@
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
- : detail::make_bool<Modifiers, T, Policies> {};
+ : detail::make_bool<Modifiers
+ , typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -356,7 +357,8 @@
terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
, fusion::vector1<A0> >
, Modifiers>
- : detail::make_bool_direct<Modifiers, T, Policies> {};
+ : detail::make_bool_direct<Modifiers
+ , typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
Modified: trunk/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/int.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/int.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -378,7 +378,8 @@
template <typename T, unsigned Radix, bool force_sign, typename Modifiers>
struct make_primitive<tag::int_generator<T, Radix, force_sign>, Modifiers>
- : detail::make_int<T, Modifiers, Radix, force_sign> {};
+ : detail::make_int<typename remove_const<T>::type
+ , Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -436,7 +437,8 @@
struct make_primitive<
terminal_ex<tag::int_generator<T, Radix, force_sign>
, fusion::vector1<A0> >, Modifiers>
- : detail::make_int_direct<T, Modifiers, Radix, force_sign> {};
+ : detail::make_int_direct<typename remove_const<T>::type
+ , Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -489,7 +491,6 @@
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_int<A0> >::type>
- : detail::basic_int_literal<A0, Modifiers>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -497,7 +498,7 @@
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
- A0
+ typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -322,7 +322,8 @@
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::double_, T>, Modifiers>
- : detail::make_real<T, Modifiers, Policies> {};
+ : detail::make_real<typename remove_const<T>::type
+ , Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -376,7 +377,8 @@
terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
, fusion::vector1<A0> >
, Modifiers>
- : detail::make_real_direct<T, Modifiers, Policies> {};
+ : detail::make_real_direct<typename remove_const<T>::type
+ , Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -423,7 +425,6 @@
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_real<A0> >::type>
- : detail::basic_real_literal<A0, Modifiers>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -431,7 +432,7 @@
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
- A0, real_policies<A0>
+ typename remove_const<A0>::type, real_policies<A0>
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/numeric/uint.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/uint.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/uint.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -417,7 +417,7 @@
template <typename T, unsigned Radix, typename Modifiers>
struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
- : detail::make_uint<T, Modifiers, Radix> {};
+ : detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -487,7 +487,8 @@
struct make_primitive<
terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
, Modifiers>
- : detail::make_uint_direct<T, Modifiers, Radix> {};
+ : detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
+ {};
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -542,7 +543,6 @@
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_uint<A0> >::type>
- : detail::basic_uint_literal<A0, Modifiers>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
@@ -550,7 +550,7 @@
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
- A0
+ typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
Modified: trunk/boost/spirit/home/karma/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/kleene.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/kleene.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,7 +15,10 @@
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -41,29 +44,39 @@
struct base_kleene : unary_generator<Derived>
{
private:
- template <
- typename OutputIterator, typename Context, typename Delimiter
- , typename Attribute>
- bool generate_subject(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Attribute const& attr) const
+ // Ignore return value in relaxed mode (failing subject generators
+ // are just skipped). This allows to selectively generate items in
+ // the provided attribute.
+ template <typename F, typename Attribute>
+ bool generate_subject(F f, Attribute const&, mpl::false_) const
+ {
+ bool r = !f(subject);
+ if (!r && !f.is_at_end())
+ f.next();
+ return true;
+ }
+
+ template <typename F, typename Attribute>
+ bool generate_subject(F f, Attribute const&, mpl::true_) const
{
- // Ignore return value, failing subject generators are just
- // skipped. This allows to selectively generate items in the
- // provided attribute.
- bool r = subject.generate(sink, ctx, d, attr);
- return !Strict::value || r;
+ return !f(subject);
}
- template <typename OutputIterator, typename Context, typename Delimiter>
- bool generate_subject(OutputIterator& sink, Context& ctx
- , Delimiter const& d, unused_type) const
+ // There is no way to distinguish a failed generator from a
+ // generator to be skipped. We assume the user takes responsibility
+ // for ending the loop if no attribute is specified.
+ template <typename F>
+ bool generate_subject(F f, unused_type, mpl::false_) const
{
- // There is no way to distinguish a failed generator from a
- // generator to be skipped. We assume the user takes responsibility
- // for ending the loop if no attribute is specified.
- return subject.generate(sink, ctx, d, unused);
+ return !f(subject);
}
+// template <typename F>
+// bool generate_subject(F f, unused_type, mpl::true_) const
+// {
+// return !f(subject);
+// }
+
public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
@@ -87,18 +100,28 @@
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
+ typedef detail::fail_function<
+ OutputIterator, Context, Delimiter> fail_function;
+
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
+ typedef typename detail::make_indirect_iterator<iterator_type>::type
+ indirect_iterator_type;
+ typedef detail::pass_container<
+ fail_function, Attribute, indirect_iterator_type, Strict>
+ pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
+ pass_container pass(fail_function(sink, ctx, d),
+ indirect_iterator_type(it), indirect_iterator_type(end));
+
// kleene fails only if the underlying output fails
- for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end);
- traits::next(it))
+ while (!pass.is_at_end())
{
- if (!generate_subject(sink, ctx, d, traits::deref(it)))
+ if (!generate_subject(pass, attr, Strict()))
break;
}
return detail::sink_is_good(sink);
@@ -170,13 +193,13 @@
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::kleene<Subject>, Attribute
- , Context, Iterator>
+ , Context, Iterator>
: mpl::true_ {};
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_kleene<Subject>, Attribute
- , Context, Iterator>
+ , Context, Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/karma/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/list.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/list.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,7 +15,10 @@
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -41,39 +44,35 @@
private:
// iterate over the given container until its exhausted or the embedded
// (left) generator succeeds
- template <
- typename OutputIterator, typename Context, typename Delimiter
- , typename Iterator, typename Attribute>
- bool generate_left(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Iterator& it, Iterator& end, Attribute const&) const
+ template <typename F, typename Attribute>
+ bool generate_left(F f, Attribute const&, mpl::false_) const
{
- if (Strict::value) {
- if (!traits::compare(it, end))
- return left.generate(sink, ctx, d, traits::deref(it));
- }
- else {
- // Failing subject generators are just skipped. This allows to
- // selectively generate items in the provided attribute.
- while (!traits::compare(it, end))
- {
- if (left.generate(sink, ctx, d, traits::deref(it)))
- return true;
- traits::next(it);
- }
+ // Failing subject generators are just skipped. This allows to
+ // selectively generate items in the provided attribute.
+ while (!f.is_at_end())
+ {
+ bool r = !f(left);
+ if (r)
+ return true;
+ if (!f.is_at_end())
+ f.next();
}
return false;
}
- template <
- typename OutputIterator, typename Context, typename Delimiter
- , typename Iterator>
- bool generate_left(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Iterator&, Iterator&, unused_type) const
+ template <typename F, typename Attribute>
+ bool generate_left(F f, Attribute const&, mpl::true_) const
+ {
+ return !f(left);
+ }
+
+ // There is no way to distinguish a failed generator from a
+ // generator to be skipped. We assume the user takes responsibility
+ // for ending the loop if no attribute is specified.
+ template <typename F>
+ bool generate_left(F f, unused_type, mpl::false_) const
{
- // There is no way to distinguish a failed generator from a
- // generator to be skipped. We assume the user takes responsibility
- // for ending the loop if no attribute is specified.
- return left.generate(sink, ctx, d, unused);
+ return !f(left);
}
public:
@@ -106,16 +105,29 @@
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
+ typedef detail::fail_function<
+ OutputIterator, Context, Delimiter
+ > fail_function;
+
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
+ typedef
+ typename detail::make_indirect_iterator<iterator_type>::type
+ indirect_iterator_type;
+ typedef detail::pass_container<
+ fail_function, Attribute, indirect_iterator_type, Strict>
+ pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
- if (generate_left(sink, ctx, d, it, end, attr))
+ pass_container pass(fail_function(sink, ctx, d),
+ indirect_iterator_type(it), indirect_iterator_type(end));
+
+ if (generate_left(pass, attr, Strict()))
{
- for (traits::next(it); !traits::compare(it, end); traits::next(it))
+ while (!pass.is_at_end())
{
// wrap the given output iterator as generate_left might fail
detail::enable_buffering<OutputIterator> buffering(sink);
@@ -125,7 +137,7 @@
if (!right.generate(sink, ctx, d, unused))
return false; // shouldn't happen
- if (!generate_left(sink, ctx, d, it, end, attr))
+ if (!generate_left(pass, attr, Strict()))
break; // return true as one item succeeded
}
buffering.buffer_copy();
@@ -203,13 +215,13 @@
template <typename Left, typename Right, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::list<Left, Right>, Attribute
- , Context, Iterator>
+ , Context, Iterator>
: mpl::true_ {};
template <typename Left, typename Right, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::strict_list<Left, Right>, Attribute
- , Context, Iterator>
+ , Context, Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/karma/operator/optional.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/optional.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/optional.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -98,8 +98,8 @@
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::optional<Subject>, Attribute, Context
- , Iterator>
- : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+ , Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/plus.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/plus.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -14,8 +14,11 @@
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
+#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -42,36 +45,50 @@
struct base_plus : unary_generator<Derived>
{
private:
- template <
- typename OutputIterator, typename Context, typename Delimiter
- , typename Attribute>
- bool generate_subject(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Attribute const& attr, bool& result) const
+ // Ignore return value in relaxed mode (failing subject generators
+ // are just skipped). This allows to selectively generate items in
+ // the provided attribute.
+ template <typename F, typename Attribute>
+ bool generate_subject(F f, Attribute const& attr, bool& result, mpl::false_) const
{
- // Ignore return value, failing subject generators are just
- // skipped. This allows to selectively generate items in the
- // provided attribute.
- if (subject.generate(sink, ctx, d, attr)) {
+ bool r = !f(subject);
+ if (r)
result = true;
- return true;
- }
- return !Strict::value;
+ else if (!f.is_at_end())
+ f.next();
+ return true;
}
- template <typename OutputIterator, typename Context, typename Delimiter>
- bool generate_subject(OutputIterator& sink, Context& ctx
- , Delimiter const& d, unused_type, bool& result) const
+ template <typename F, typename Attribute>
+ bool generate_subject(F f, Attribute const& attr, bool& result, mpl::true_) const
{
- // There is no way to distinguish a failed generator from a
- // generator to be skipped. We assume the user takes responsibility
- // for ending the loop if no attribute is specified.
- if (subject.generate(sink, ctx, d, unused)) {
+ bool r = !f(subject);
+ if (r)
result = true;
- return true;
- }
- return false;
+ return r;
+ }
+
+ // There is no way to distinguish a failed generator from a
+ // generator to be skipped. We assume the user takes responsibility
+ // for ending the loop if no attribute is specified.
+ template <typename F>
+ bool generate_subject(F f, unused_type, bool& result, mpl::false_) const
+ {
+ bool r = f(subject);
+ if (!r)
+ result = true;
+ return !r;
}
+// template <typename F>
+// bool generate_subject(F f, unused_type, bool& result, mpl::true_) const
+// {
+// bool r = f(subject);
+// if (!r)
+// result = true;
+// return !r;
+// }
+
public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
@@ -95,9 +112,17 @@
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
+ typedef detail::fail_function<
+ OutputIterator, Context, Delimiter> fail_function;
+
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
+ typedef typename detail::make_indirect_iterator<iterator_type>::type
+ indirect_iterator_type;
+ typedef detail::pass_container<
+ fail_function, Attribute, indirect_iterator_type, Strict>
+ pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
@@ -106,13 +131,15 @@
if (traits::compare(it, end))
return false;
+ pass_container pass(fail_function(sink, ctx, d),
+ indirect_iterator_type(it), indirect_iterator_type(end));
+
// from now on plus fails if the underlying output fails or overall
// no subject generators succeeded
bool result = false;
- for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end);
- traits::next(it))
+ while (!pass.is_at_end())
{
- if (!generate_subject(sink, ctx, d, traits::deref(it), result))
+ if (!generate_subject(pass, attr, result, Strict()))
break;
}
return result && detail::sink_is_good(sink);
@@ -184,14 +211,14 @@
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::plus<Subject>, Attribute
- , Context, Iterator>
- : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+ , Context, Iterator>
+ : mpl::true_ {};
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_plus<Subject>, Attribute
- , Context, Iterator>
- : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+ , Context, Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -20,6 +20,7 @@
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/detail/what_function.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
+#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/support/algorithm/any_if.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/sequence_base_id.hpp>
@@ -83,83 +84,11 @@
, mpl::bitor_<mpl::_2, mpl::_1>
>::type type;
};
-
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
- namespace detail
- {
-
- ///////////////////////////////////////////////////////////////////////
- // This is a wrapper for any iterator allowing to pass a reference of it
- // to the components of the sequence
- template <typename Iterator>
- class indirect_iterator
- : public boost::iterator_facade<
- indirect_iterator<Iterator>
- , typename boost::detail::iterator_traits<Iterator>::value_type
- , boost::forward_traversal_tag
- , typename boost::detail::iterator_traits<Iterator>::value_type const&>
- {
- typedef typename boost::detail::iterator_traits<Iterator>::value_type
- base_value_type;
-
- typedef boost::iterator_facade<
- indirect_iterator<Iterator>, base_value_type
- , boost::forward_traversal_tag, base_value_type const&
- > base_type;
-
- public:
- indirect_iterator(Iterator& iter)
- : iter_(&iter)
- {}
- indirect_iterator(indirect_iterator const& iter)
- : iter_(iter.iter_)
- {}
-
- private:
- friend class boost::iterator_core_access;
-
- void increment()
- {
- ++*iter_;
- }
-
- bool equal(indirect_iterator const& other) const
- {
- return *iter_ == *other.iter_;
- }
-
- typename base_type::reference dereference() const
- {
- return **iter_;
- }
-
- private:
- Iterator* iter_;
- };
-
- template <typename Iterator>
- struct make_indirect_iterator
- {
- typedef indirect_iterator<Iterator> type;
- };
-
- template <typename Iterator>
- struct make_indirect_iterator<indirect_iterator<Iterator> >
- {
- typedef indirect_iterator<Iterator> type;
- };
-
- template <>
- struct make_indirect_iterator<unused_type const*>
- {
- typedef unused_type const* type;
- };
- }
-
template <typename Elements, typename Strict, typename Derived>
struct base_sequence : nary_generator<Derived>
{
@@ -365,14 +294,14 @@
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::sequence<Elements>, Attribute, Context
- , Iterator>
- : nary_handles_container<Elements, Attribute, Context, Iterator> {};
-
+ , Iterator>
+ : mpl::true_ {};
+
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_sequence<Elements>, Attribute
- , Context, Iterator>
- : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+ , Context, Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/stream/stream.hpp (original)
+++ trunk/boost/spirit/home/karma/stream/stream.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -113,7 +113,7 @@
template <typename Context, typename Unused = unused_type>
struct attribute
{
- typedef spirit::hold_any type;
+ typedef spirit::basic_hold_any<Char> type;
};
// any_stream_generator has an attached attribute
Modified: trunk/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/assign_to.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/assign_to.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -227,9 +227,9 @@
namespace detail
{
// overload for non-container attributes
- template <typename T, typename Attribute, typename P1, typename P2>
+ template <typename T, typename Attribute>
inline void
- assign_to(T const& val, Attribute& attr, P1, P2)
+ assign_to(T const& val, Attribute& attr, mpl::false_)
{
assign_to_attribute_from_value<Attribute, T>::call(val, attr);
}
@@ -238,7 +238,7 @@
// holding containers)
template <typename T, typename Attribute>
inline void
- assign_to(T const& val, Attribute& attr, mpl::true_, mpl::true_)
+ assign_to(T const& val, Attribute& attr, mpl::true_)
{
assign_to_container_from_value<Attribute, T>::call(val, attr);
}
@@ -248,13 +248,13 @@
inline void
assign_to(T const& val, Attribute& attr)
{
- typedef typename traits::is_container<Attribute>::type is_container;
typedef typename mpl::and_<
- traits::not_is_variant<Attribute>
+ traits::is_container<Attribute>
+ , traits::not_is_variant<Attribute>
, traits::not_is_optional<Attribute>
>::type is_not_wrapped_container;
- detail::assign_to(val, attr, is_container(), is_not_wrapped_container());
+ detail::assign_to(val, attr, is_not_wrapped_container());
}
template <typename T>
Modified: trunk/boost/spirit/home/qi/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/pass_container.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/pass_container.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -26,15 +26,24 @@
// to the LHS.
template <typename LHS, typename RHSAttribute
- , bool IsContainer = traits::is_container<RHSAttribute>::value>
+ , bool IsContainer = traits::is_container<RHSAttribute>::value
+ , bool IsSequence = fusion::traits::is_sequence<RHSAttribute>::value>
struct has_same_elements : mpl::false_ {};
template <typename LHS, typename RHSAttribute>
- struct has_same_elements<LHS, RHSAttribute, true>
+ struct has_same_elements<LHS, RHSAttribute, true, false>
: is_convertible<typename RHSAttribute::value_type, LHS> {};
template <typename LHS, typename T>
- struct has_same_elements<LHS, optional<T>, true>
+ struct has_same_elements<LHS, optional<T>, false, false>
+ : has_same_elements<LHS, T> {};
+
+ template <typename LHS, typename T>
+ struct has_same_elements<LHS, optional<T>, true, false>
+ : has_same_elements<LHS, T> {};
+
+ template <typename LHS, typename T>
+ struct has_same_elements<LHS, optional<T>, false, true>
: has_same_elements<LHS, T> {};
#define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data) \
@@ -45,12 +54,28 @@
// container (see support/container.hpp).
template <typename LHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct has_same_elements<
- LHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true>
+ LHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true, false>
: mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
, BOOST_SPIRIT_IS_CONVERTIBLE, _) false> {};
#undef BOOST_SPIRIT_IS_CONVERTIBLE
+ // Specialization for fusion sequences, in this case we check whether all
+ // the types in the sequence are convertible to the lhs attribute.
+ // We return false if the lhs attribute itself is a fusion sequence.
+ template <typename LHS, typename RHSAttribute>
+ struct has_same_elements<LHS, RHSAttribute, false, true>
+ {
+ typedef typename mpl::find_if<
+ RHSAttribute, mpl::not_<is_convertible<mpl::_1, LHS> >
+ >::type iter;
+ typedef typename mpl::end<RHSAttribute>::type end;
+
+ typedef typename mpl::and_<
+ mpl::not_<fusion::traits::is_sequence<LHS> >, is_same<iter, end>
+ >::type type;
+ };
+
// This function handles the case where the attribute (Attr) given
// the sequence is an STL container. This is a wrapper around F.
// The function F does the actual parsing.
@@ -163,6 +188,9 @@
, iterator_type>
> predicate;
+// // ensure the attribute is actually a container type
+// traits::make_container(attr);
+
return dispatch_main(component, predicate());
}
Modified: trunk/boost/spirit/home/qi/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/directive/repeat.hpp (original)
+++ trunk/boost/spirit/home/qi/directive/repeat.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,11 +19,12 @@
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/fusion/include/at.hpp>
-#include <boost/foreach.hpp>
#include <vector>
namespace boost { namespace spirit
@@ -152,57 +154,26 @@
repeat_parser(Subject const& subject, LoopIter const& iter)
: subject(subject), iter(iter) {}
- template <typename Iterator, typename Context
- , typename Skipper, typename ValueType, typename Attribute
- , typename LoopVar>
- bool parse_minimal(Iterator &first, Iterator const& last
- , Context& context, Skipper const& skipper
- , Attribute& attr, ValueType& val, LoopVar& i) const
+ template <typename F>
+ bool parse_container(F f) const
{
- // this scope allows save and required_attr to be reclaimed
- // immediately after we're done with the required minimum
- // iteration.
- Iterator save = first;
- std::vector<ValueType> required_attr;
- for (; !iter.got_min(i); ++i)
+ typename LoopIter::type i = iter.start();
+ for (/**/; !iter.got_min(i); ++i)
{
- if (!subject.parse(save, last, context, skipper, val) ||
- !traits::push_back(required_attr, val))
- {
+ if (f (subject))
return false;
- }
-
- first = save;
- traits::clear(val);
}
- // if we got the required number of items, these are copied
- // over (appended) to the 'real' attribute
- BOOST_FOREACH(ValueType const& v, required_attr)
+ // parse some more up to the maximum specified
+ typename F::iterator_type save = f.f.first;
+ for (/**/; !iter.got_max(i); ++i)
{
- traits::push_back(attr, v);
+ if (f (subject))
+ break;
+ save = f.f.first;
}
- return true;
- }
- template <typename Iterator, typename Context
- , typename Skipper, typename LoopVar>
- bool parse_minimal(Iterator &first, Iterator const& last
- , Context& context, Skipper const& skipper
- , unused_type, unused_type, LoopVar& i) const
- {
- // this scope allows save and required_attr to be reclaimed
- // immediately after we're done with the required minimum
- // iteration.
- Iterator save = first;
- for (; !iter.got_min(i); ++i)
- {
- if (!subject.parse(save, last, context, skipper, unused))
- {
- return false;
- }
- first = save;
- }
+ f.f.first = save;
return true;
}
@@ -212,35 +183,18 @@
, Context& context, Skipper const& skipper
, Attribute& attr) const
{
- // create a local value if Attribute is not unused_type
- typedef typename traits::container_value<Attribute>::type
- value_type;
- value_type val = value_type();
- typename LoopIter::type i = iter.start();
+ typedef detail::fail_function<Iterator, Context, Skipper>
+ fail_function;
// ensure the attribute is actually a container type
traits::make_container(attr);
- // parse the minimum required
- Iterator save = first;
- if (!iter.got_min(i) &&
- !parse_minimal(save, last, context, skipper, attr, val, i))
- {
+ Iterator iter = first;
+ fail_function f(iter, last, context, skipper);
+ if (!parse_container(detail::make_pass_container(f, attr)))
return false;
- }
-
- // parse some more up to the maximum specified
- for (/**/; !iter.got_max(i); ++i) {
- if (!subject.parse(save, last, context, skipper, val) ||
- !traits::push_back(attr, val))
- {
- break;
- }
- first = save;
- traits::clear(val);
- }
- first = save;
+ first = f.first;
return true;
}
@@ -334,7 +288,7 @@
template <typename Subject, typename LoopIter, typename Attribute
, typename Context, typename Iterator>
struct handles_container<qi::repeat_parser<Subject, LoopIter>
- , Attribute, Context, Iterator>
+ , Attribute, Context, Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/qi/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/numeric/int.hpp (original)
+++ trunk/boost/spirit/home/qi/numeric/int.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -56,7 +56,7 @@
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<is_same<A0, signed short> >::type>
: mpl::true_ {};
-
+
template <typename A0> // enables short_(n)
struct use_terminal<qi::domain
, terminal_ex<tag::short_, fusion::vector1<A0> > >
@@ -69,7 +69,7 @@
//[primitive_parsers_enable_int
template <> // enables int_
struct use_terminal<qi::domain, tag::int_> : mpl::true_ {};
- //]
+ //]
template <typename A0> // enables lit(n)
struct use_terminal<qi::domain
@@ -84,13 +84,13 @@
template <> // enables *lazy* int_(n)
struct use_lazy_terminal<qi::domain, tag::int_, 1> : mpl::true_ {};
-
+
///////////////////////////////////////////////////////////////////////////
//[primitive_parsers_enable_long
template <> // enables long_
struct use_terminal<qi::domain, tag::long_> : mpl::true_ {};
- //]
-
+ //]
+
template <typename A0> // enables lit(n)
struct use_terminal<qi::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
@@ -104,7 +104,7 @@
template <> // enables *lazy* long_(n)
struct use_lazy_terminal<qi::domain, tag::long_, 1> : mpl::true_ {};
-
+
///////////////////////////////////////////////////////////////////////////
#ifdef BOOST_HAS_LONG_LONG
//[primitive_parsers_enable_long_long
@@ -236,7 +236,7 @@
{
typedef extract_int<T, Radix, MinDigits, MaxDigits> extract;
qi::skip_over(first, last, skipper);
-
+
Iterator save = first;
T attr_;
@@ -277,7 +277,7 @@
}
};
//]
-
+
template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
, int MaxDigits = -1>
struct make_direct_int
@@ -290,7 +290,7 @@
return result_type(fusion::at_c<0>(term.args));
}
};
-
+
template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
, int MaxDigits = -1>
struct make_literal_int
@@ -302,7 +302,7 @@
return result_type(fusion::at_c<0>(term.args));
}
};
-
+
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
Modified: trunk/boost/spirit/home/qi/operator/expect.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/expect.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/expect.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -95,8 +96,8 @@
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<qi::expect<Elements>, Attribute, Context
- , Iterator>
- : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+ , Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/qi/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/kleene.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/kleene.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +16,8 @@
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/info.hpp>
@@ -33,7 +36,6 @@
namespace boost { namespace spirit { namespace qi
{
-
//[composite_parsers_kleene
template <typename Subject>
struct kleene : unary_parser<kleene<Subject> >
@@ -57,28 +59,31 @@
kleene(Subject const& subject)
: subject(subject) {}
+ template <typename F>
+ bool parse_container(F f) const
+ {
+ while (!f (subject))
+ ;
+ return true;
+ }
+
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
, Attribute& attr) const
{
- // create a local value if Attribute is not unused_type
- typedef typename traits::container_value<Attribute>::type
- value_type;
- value_type val = value_type();
-
// ensure the attribute is actually a container type
traits::make_container(attr);
- // Repeat while subject parses ok
- Iterator save = first;
- while (subject.parse(save, last, context, skipper, val) &&
- traits::push_back(attr, val)) // push the parsed value into our attribute
- {
- first = save;
- traits::clear(val);
- }
+ typedef detail::fail_function<Iterator, Context, Skipper>
+ fail_function;
+
+ Iterator iter = first;
+ fail_function f(iter, last, context, skipper);
+ parse_container(detail::make_pass_container(f, attr));
+
+ first = f.first;
return true;
}
@@ -120,9 +125,9 @@
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
- , typename Iterator>
+ , typename Iterator>
struct handles_container<qi::kleene<Subject>, Attribute
- , Context, Iterator>
+ , Context, Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/qi/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/list.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/list.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +16,8 @@
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/info.hpp>
@@ -55,36 +58,42 @@
list(Left const& left, Right const& right)
: left(left), right(right) {}
+ template <typename F>
+ bool parse_container(F f) const
+ {
+ // in order to succeed we need to match at least one element
+ if (f (left))
+ return false;
+
+ typename F::iterator_type save = f.f.first;
+ while (right.parse(f.f.first, f.f.last, f.f.context, f.f.skipper, unused)
+ && !f (left))
+ {
+ save = f.f.first;
+ }
+
+ f.f.first = save;
+ return true;
+ }
+
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
, Attribute& attr) const
{
- // create a local value if Attribute is not unused_type
- typedef typename traits::container_value<Attribute>::type
- value_type;
- value_type val = value_type();
+ typedef detail::fail_function<Iterator, Context, Skipper>
+ fail_function;
// ensure the attribute is actually a container type
traits::make_container(attr);
- Iterator save = first;
- if (!left.parse(save, last, context, skipper, val) ||
- !traits::push_back(attr, val))
- {
+ Iterator iter = first;
+ fail_function f(iter, last, context, skipper);
+ if (!parse_container(detail::make_pass_container(f, attr)))
return false;
- }
- first = save;
- while (right.parse(save, last, context, skipper, unused)
- && (traits::clear(val), true)
- && left.parse(save, last, context, skipper, val))
- {
- if (!traits::push_back(attr, val))
- break;
- first = save;
- }
+ first = f.first;
return true;
}
@@ -119,7 +128,7 @@
template <typename Left, typename Right, typename Attribute
, typename Context, typename Iterator>
struct handles_container<qi::list<Left, Right>, Attribute, Context
- , Iterator>
+ , Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/qi/operator/optional.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/optional.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/optional.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +17,7 @@
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
@@ -58,9 +60,9 @@
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
- bool parse(Iterator& first, Iterator const& last
+ bool parse_impl(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
- , Attribute& attr) const
+ , Attribute& attr, mpl::false_) const
{
// create a local value if Attribute is not unused_type
typename spirit::result_of::optional_value<Attribute>::type val;
@@ -73,6 +75,29 @@
return true;
}
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr, mpl::true_) const
+ {
+ subject.parse(first, last, context, skipper, attr);
+ return true;
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr) const
+ {
+ typedef typename spirit::result_of::optional_value<Attribute>::type
+ attribute_type;
+
+ return parse_impl(first, last, context, skipper, attr
+ , traits::is_container<attribute_type>());
+ }
+
template <typename Context>
info what(Context& context) const
{
@@ -102,8 +127,8 @@
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<qi::optional<Subject>, Attribute
- , Context, Iterator>
- : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+ , Context, Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/qi/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/plus.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/plus.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +16,8 @@
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/fail_function.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/info.hpp>
@@ -53,37 +56,36 @@
plus(Subject const& subject)
: subject(subject) {}
+ template <typename F>
+ bool parse_container(F f) const
+ {
+ // in order to succeed we need to match at least one element
+ if (f (subject))
+ return false;
+
+ while (!f (subject))
+ ;
+ return true;
+ }
+
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
, Attribute& attr) const
{
- // create a local value if Attribute is not unused_type
- typedef typename traits::container_value<Attribute>::type
- value_type;
- value_type val = value_type();
+ typedef detail::fail_function<Iterator, Context, Skipper>
+ fail_function;
// ensure the attribute is actually a container type
traits::make_container(attr);
- Iterator save = first;
- if (!subject.parse(save, last, context, skipper, val) ||
- !traits::push_back(attr, val))
- {
+ Iterator iter = first;
+ fail_function f(iter, last, context, skipper);
+ if (!parse_container(detail::make_pass_container(f, attr)))
return false;
- }
- first = save;
- traits::clear(val);
-
- while (subject.parse(save, last, context, skipper, val))
- {
- if (!traits::push_back(attr, val))
- break;
-
- first = save;
- traits::clear(val);
- }
+
+ first = f.first;
return true;
}
@@ -116,7 +118,7 @@
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<qi::plus<Subject>, Attribute, Context
- , Iterator>
+ , Iterator>
: mpl::true_ {};
}}}
Modified: trunk/boost/spirit/home/qi/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/sequence.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/sequence.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -88,8 +89,8 @@
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<qi::sequence<Elements>, Attribute, Context
- , Iterator>
- : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+ , Iterator>
+ : mpl::true_ {};
}}}
#endif
Modified: trunk/boost/spirit/home/qi/operator/sequence_base.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/sequence_base.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/sequence_base.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Modified: trunk/boost/spirit/home/qi/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/stream/stream.hpp (original)
+++ trunk/boost/spirit/home/qi/stream/stream.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -40,7 +40,7 @@
using spirit::stream;
using spirit::wstream;
- template <typename Char = char, typename T = spirit::hold_any>
+ template <typename Char = char, typename T = spirit::basic_hold_any<char> >
struct stream_parser
: primitive_parser<stream_parser<Char, T> >
{
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -45,6 +45,7 @@
#include <boost/range/iterator_range.hpp>
#include <vector>
#include <utility>
+#include <ios>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
@@ -115,7 +116,7 @@
template <typename Container>
struct is_hold_any_container
- : is_same<hold_any, typename traits::container_value<Container>::type>
+ : traits::is_hold_any<typename traits::container_value<Container>::type>
{};
}
@@ -124,7 +125,7 @@
struct compute_compatible_component_variant
: mpl::or_<
traits::detail::attribute_is_compatible<Expected, Attribute>
- , is_same<hold_any, Expected>
+ , traits::is_hold_any<Expected>
, mpl::eval_if<
is_container<Expected>
, traits::detail::is_hold_any_container<Expected>
Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -132,6 +132,9 @@
template <typename Attribute, typename Exposed, typename Enable = void>
struct extract_from_attribute;
+ template <typename Attribute, typename Exposed, typename Enable = void>
+ struct extract_from_container;
+
template <typename Exposed, typename Attribute, typename Context>
typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx
Modified: trunk/boost/spirit/home/support/container.hpp
==============================================================================
--- trunk/boost/spirit/home/support/container.hpp (original)
+++ trunk/boost/spirit/home/support/container.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -70,7 +70,7 @@
{};
#undef BOOST_SPIRIT_IS_CONTAINER
-
+
template <typename T, typename Enable/* = void*/>
struct is_iterator_range
: mpl::false_
Modified: trunk/boost/spirit/home/support/detail/hold_any.hpp
==============================================================================
--- trunk/boost/spirit/home/support/detail/hold_any.hpp (original)
+++ trunk/boost/spirit/home/support/detail/hold_any.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -58,6 +58,7 @@
namespace detail
{
// function pointer table
+ template <typename Char>
struct fxn_ptr_table
{
boost::detail::sp_typeinfo const& (*get_type)();
@@ -65,18 +66,18 @@
void (*destruct)(void**);
void (*clone)(void* const*, void**);
void (*move)(void* const*, void**);
- std::istream& (*stream_in)(std::istream&, void**);
- std::ostream& (*stream_out)(std::ostream&, void* const*);
+ std::basic_istream<Char>& (*stream_in)(std::basic_istream<Char>&, void**);
+ std::basic_ostream<Char>& (*stream_out)(std::basic_ostream<Char>&, void* const*);
};
// static functions for small value-types
- template<typename Small>
+ template <typename Small>
struct fxns;
- template<>
+ template <>
struct fxns<mpl::true_>
{
- template<typename T>
+ template<typename T, typename Char>
struct type
{
static boost::detail::sp_typeinfo const& get_type()
@@ -101,12 +102,14 @@
*reinterpret_cast<T*>(dest) =
*reinterpret_cast<T const*>(src);
}
- static std::istream& stream_in (std::istream& i, void** obj)
+ static std::basic_istream<Char>&
+ stream_in (std::basic_istream<Char>& i, void** obj)
{
i >> *reinterpret_cast<T*>(obj);
return i;
}
- static std::ostream& stream_out(std::ostream& o, void* const* obj)
+ static std::basic_ostream<Char>&
+ stream_out(std::basic_ostream<Char>& o, void* const* obj)
{
o << *reinterpret_cast<T const*>(obj);
return o;
@@ -115,10 +118,10 @@
};
// static functions for big value-types (bigger than a void*)
- template<>
+ template <>
struct fxns<mpl::false_>
{
- template<typename T>
+ template<typename T, typename Char>
struct type
{
static boost::detail::sp_typeinfo const& get_type()
@@ -145,12 +148,14 @@
**reinterpret_cast<T**>(dest) =
**reinterpret_cast<T* const*>(src);
}
- static std::istream& stream_in(std::istream& i, void** obj)
+ static std::basic_istream<Char>&
+ stream_in(std::basic_istream<Char>& i, void** obj)
{
i >> **reinterpret_cast<T**>(obj);
return i;
}
- static std::ostream& stream_out(std::ostream& o, void* const* obj)
+ static std::basic_ostream<Char>&
+ stream_out(std::basic_ostream<Char>& o, void* const* obj)
{
o << **reinterpret_cast<T* const*>(obj);
return o;
@@ -158,22 +163,23 @@
};
};
- template<typename T>
+ template <typename T>
struct get_table
{
typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
- static fxn_ptr_table* get()
+ template <typename Char>
+ static fxn_ptr_table<Char>* get()
{
- static fxn_ptr_table static_table =
+ static fxn_ptr_table<Char> static_table =
{
- fxns<is_small>::template type<T>::get_type,
- fxns<is_small>::template type<T>::static_delete,
- fxns<is_small>::template type<T>::destruct,
- fxns<is_small>::template type<T>::clone,
- fxns<is_small>::template type<T>::move,
- fxns<is_small>::template type<T>::stream_in,
- fxns<is_small>::template type<T>::stream_out
+ fxns<is_small>::template type<T, Char>::get_type,
+ fxns<is_small>::template type<T, Char>::static_delete,
+ fxns<is_small>::template type<T, Char>::destruct,
+ fxns<is_small>::template type<T, Char>::clone,
+ fxns<is_small>::template type<T, Char>::move,
+ fxns<is_small>::template type<T, Char>::stream_in,
+ fxns<is_small>::template type<T, Char>::stream_out
};
return &static_table;
}
@@ -207,13 +213,14 @@
}
///////////////////////////////////////////////////////////////////////////
- class hold_any
+ template <typename Char>
+ class basic_hold_any
{
public:
// constructors
template <typename T>
- explicit hold_any(T const& x)
- : table(spirit::detail::get_table<T>::get()), object(0)
+ explicit basic_hold_any(T const& x)
+ : table(spirit::detail::get_table<T>::template get<Char>()), object(0)
{
if (spirit::detail::get_table<T>::is_small::value)
new (&object) T(x);
@@ -221,26 +228,26 @@
object = new T(x);
}
- hold_any()
- : table(spirit::detail::get_table<spirit::detail::empty>::get()),
+ basic_hold_any()
+ : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
object(0)
{
}
- hold_any(hold_any const& x)
- : table(spirit::detail::get_table<spirit::detail::empty>::get()),
+ basic_hold_any(basic_hold_any const& x)
+ : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
object(0)
{
assign(x);
}
- ~hold_any()
+ ~basic_hold_any()
{
table->static_delete(&object);
}
// assignment
- hold_any& assign(hold_any const& x)
+ basic_hold_any& assign(basic_hold_any const& x)
{
if (&x != this) {
// are we copying between the same type?
@@ -258,11 +265,11 @@
}
template <typename T>
- hold_any& assign(T const& x)
+ basic_hold_any& assign(T const& x)
{
// are we copying between the same type?
- spirit::detail::fxn_ptr_table* x_table =
- spirit::detail::get_table<T>::get();
+ spirit::detail::fxn_ptr_table<Char>* x_table =
+ spirit::detail::get_table<T>::template get<Char>();
if (table == x_table) {
// if so, we can avoid deallocating and re-use memory
table->destruct(&object); // first destruct the old content
@@ -292,13 +299,13 @@
// assignment operator
template <typename T>
- hold_any& operator=(T const& x)
+ basic_hold_any& operator=(T const& x)
{
return assign(x);
}
// utility functions
- hold_any& swap(hold_any& x)
+ basic_hold_any& swap(basic_hold_any& x)
{
std::swap(table, x.table);
std::swap(object, x.object);
@@ -330,7 +337,7 @@
bool empty() const
{
- return table == spirit::detail::get_table<spirit::detail::empty>::get();
+ return table == spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
}
void reset()
@@ -338,7 +345,7 @@
if (!empty())
{
table->static_delete(&object);
- table = spirit::detail::get_table<spirit::detail::empty>::get();
+ table = spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
object = 0;
}
}
@@ -347,31 +354,35 @@
// type has a corresponding operator defined, which is completely safe
// because spirit::hold_any is used only in contexts where these operators
// do exist
- friend std::istream& operator>> (std::istream& i, hold_any& obj)
+ template <typename Char_>
+ friend inline std::basic_istream<Char_>&
+ operator>> (std::basic_istream<Char_>& i, basic_hold_any<Char_>& obj)
{
return obj.table->stream_in(i, &obj.object);
}
- friend std::ostream& operator<< (std::ostream& o, hold_any const& obj)
+ template <typename Char_>
+ friend inline std::basic_ostream<Char_>&
+ operator<< (std::basic_ostream<Char_>& o, basic_hold_any<Char_> const& obj)
{
return obj.table->stream_out(o, &obj.object);
}
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // types
- template<typename T>
- friend T* any_cast(hold_any *);
+ template <typename T, typename Char_>
+ friend T* any_cast(basic_hold_any<Char_> *);
#else
public: // types (public so any_cast can be non-friend)
#endif
// fields
- spirit::detail::fxn_ptr_table* table;
+ spirit::detail::fxn_ptr_table<Char>* table;
void* object;
};
// boost::any-like casting
- template <typename T>
- inline T* any_cast (hold_any* operand)
+ template <typename T, typename Char>
+ inline T* any_cast (basic_hold_any<Char>* operand)
{
if (operand && operand->type() == BOOST_SP_TYPEID(T)) {
return spirit::detail::get_table<T>::is_small::value ?
@@ -381,14 +392,14 @@
return 0;
}
- template <typename T>
- inline T const* any_cast(hold_any const* operand)
+ template <typename T, typename Char>
+ inline T const* any_cast(basic_hold_any<Char> const* operand)
{
- return any_cast<T>(const_cast<hold_any*>(operand));
+ return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
}
- template <typename T>
- T any_cast(hold_any& operand)
+ template <typename T, typename Char>
+ T any_cast(basic_hold_any<Char>& operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
@@ -408,8 +419,8 @@
return *result;
}
- template <typename T>
- T const& any_cast(hold_any const& operand)
+ template <typename T, typename Char>
+ T const& any_cast(basic_hold_any<Char> const& operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
@@ -419,10 +430,23 @@
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
#endif
- return any_cast<nonref const&>(const_cast<hold_any &>(operand));
+ return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // backwards compatibility
+ typedef basic_hold_any<char> hold_any;
+ typedef basic_hold_any<wchar_t> whold_any;
+
+ namespace traits
+ {
+ template <typename T>
+ struct is_hold_any : mpl::false_ {};
+
+ template <typename Char>
+ struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {};
}
-///////////////////////////////////////////////////////////////////////////////
}} // namespace boost::spirit
///////////////////////////////////////////////////////////////////////////////
Modified: trunk/boost/spirit/home/support/utree/operators.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/operators.hpp (original)
+++ trunk/boost/spirit/home/support/utree/operators.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -15,6 +15,7 @@
#endif
#include <exception>
+#include <ios>
#include <boost/spirit/home/support/utree/utree.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/throw_exception.hpp>
Modified: trunk/boost/spirit/home/support/utree/utree_traits.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/utree_traits.hpp (original)
+++ trunk/boost/spirit/home/support/utree/utree_traits.hpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -38,6 +38,11 @@
}
}
+namespace boost { namespace spirit { namespace qi
+{
+ template <typename Subject> struct kleene;
+}}}
+
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
@@ -59,6 +64,11 @@
}
return false;
}
+
+ inline bool is_uninitialized(utree const& ut)
+ {
+ return traits::which(ut) == utree_type::invalid_type;
+ }
}
// this specialization tells Spirit how to extract the type of the value
@@ -507,8 +517,15 @@
{
static void call(utree& ut)
{
- if (!detail::is_list(ut))
- ut = empty_list;
+ if (!detail::is_list(ut)) {
+ if (detail::is_uninitialized(ut))
+ ut = empty_list;
+ else {
+ utree retval (empty_list);
+ retval.push_back(ut);
+ ut.swap(retval);
+ }
+ }
}
};
@@ -644,7 +661,7 @@
// only 'invalid_type' utree nodes are not valid
static bool is_valid(utree const& val)
{
- return traits::which(val) != utree_type::invalid_type;
+ return !detail::is_uninitialized(val);
}
};
@@ -943,7 +960,7 @@
}
template <>
- struct extract_from_attribute<utree, utree::nil_type>
+ struct extract_from_container<utree, utree::nil_type>
{
typedef utree::nil_type type;
@@ -955,7 +972,7 @@
};
template <>
- struct extract_from_attribute<utree, char>
+ struct extract_from_container<utree, char>
{
typedef char type;
@@ -968,7 +985,7 @@
};
template <>
- struct extract_from_attribute<utree, bool>
+ struct extract_from_container<utree, bool>
{
typedef bool type;
@@ -980,7 +997,7 @@
};
template <>
- struct extract_from_attribute<utree, int>
+ struct extract_from_container<utree, int>
{
typedef int type;
@@ -992,7 +1009,7 @@
};
template <>
- struct extract_from_attribute<utree, double>
+ struct extract_from_container<utree, double>
{
typedef double type;
@@ -1004,7 +1021,7 @@
};
template <typename Traits, typename Alloc>
- struct extract_from_attribute<utree, std::basic_string<char, Traits, Alloc> >
+ struct extract_from_container<utree, std::basic_string<char, Traits, Alloc> >
{
typedef std::basic_string<char, Traits, Alloc> type;
@@ -1017,7 +1034,7 @@
};
template <>
- struct extract_from_attribute<utree, utf8_symbol_type>
+ struct extract_from_container<utree, utf8_symbol_type>
{
typedef std::string type;
@@ -1030,7 +1047,7 @@
};
template <>
- struct extract_from_attribute<utree, utf8_string_type>
+ struct extract_from_container<utree, utf8_string_type>
{
typedef std::string type;
@@ -1123,7 +1140,10 @@
static type pre(iterator_range<Iterator> const& t)
{
// return utree the begin iterator points to
- return utree(boost::ref(t.front()));
+ Iterator it = boost::begin(t);
+ utree result(boost::ref(*it));
+ ++it;
+ return result;
}
};
Modified: trunk/libs/spirit/doc/what_s_new.qbk
==============================================================================
--- trunk/libs/spirit/doc/what_s_new.qbk (original)
+++ trunk/libs/spirit/doc/what_s_new.qbk 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -149,8 +149,8 @@
[heading Known Problems]
-* Integer literals consume input on failure, which can lead to problems with
- the alternative operator:
+* Integer literals (like `int_(10)`) consume input on failure, which can lead to
+ problems with the alternative operator:
[endsect]
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile (original)
+++ trunk/libs/spirit/test/Jamfile 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -194,6 +194,7 @@
[ run karma/regression_optional_double.cpp : : : : karma_regression_optional_double ]
[ run karma/regression_semantic_action_attribute.cpp : : : : karma_regression_semantic_action_attribute ]
[ run karma/regression_real_scientific.cpp : : : : karma_regression_real_scientific ]
+ [ compile karma/regression_const_real_policies.cpp : : regression_const_real_policies ]
;
Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp (original)
+++ trunk/libs/spirit/test/karma/kleene.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -23,6 +23,8 @@
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/include/std_pair.hpp>
+#include <boost/assign/std/vector.hpp>
+
#include "test.hpp"
using namespace spirit_test;
@@ -63,6 +65,57 @@
}
{
+ std::string s1("aaaaa");
+ BOOST_TEST(test("aaaaa", char_ << *(char_ << char_), s1));
+ BOOST_TEST(test_delimited("a a a a a ",
+ char_ << *(char_ << char_), s1, ' '));
+
+ s1 = "a";
+ BOOST_TEST(test("a", char_ << *(char_ << char_), s1));
+ s1 = "aa";
+ BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
+// BOOST_TEST(test("aa", char_ << *buffer[char_ << char_] << char_, s1));
+ s1 = "aaaa";
+ BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
+// BOOST_TEST(test("aaaa", char_ << *buffer[char_ << char_] << char_, s1));
+ }
+
+ {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+ using namespace boost::assign;
+
+ typedef std::pair<char, char> data;
+ std::vector<data> v1;
+ v1 += std::make_pair('a', 'a'),
+ std::make_pair('b', 'b'),
+ std::make_pair('c', 'c'),
+ std::make_pair('d', 'd'),
+ std::make_pair('e', 'e'),
+ std::make_pair('f', 'f'),
+ std::make_pair('g', 'g');
+
+ karma::rule<spirit_test::output_iterator<char>::type, data()> r;
+ r = &char_('a') << char_;
+
+ BOOST_TEST(test("a", r << *(r << r), v1));
+ BOOST_TEST(test("a", relaxed[r << *(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+
+ v1 += std::make_pair('a', 'a');
+
+ BOOST_TEST(!test("", r << *(r << r), v1));
+ BOOST_TEST(!test("", relaxed[r << *(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+
+ v1 += std::make_pair('a', 'a');
+
+ BOOST_TEST(test("aaa", r << *(r << r), v1));
+ BOOST_TEST(test("aaa", relaxed[r << *(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << *(r << r)], v1));
+ }
+
+ {
using namespace boost::assign;
std::vector<char> v;
Modified: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/list.cpp (original)
+++ trunk/libs/spirit/test/karma/list.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -75,6 +75,13 @@
char_ % ',', s, space));
}
+ {
+ std::string s ("abcdefg");
+ BOOST_TEST(test("abc,de,fg", char_ << ((char_ << char_) % ','), s));
+ BOOST_TEST(test_delimited("a b c , d e , f g ",
+ char_ << ((char_ << char_) % ','), s, space));
+ }
+
{ // actions
namespace phx = boost::phoenix;
Modified: trunk/libs/spirit/test/karma/lit.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/lit.cpp (original)
+++ trunk/libs/spirit/test/karma/lit.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -63,6 +63,10 @@
BOOST_TEST(test("abc", str));
BOOST_TEST(!test("abcd", str));
+ }
+
+ {
+ using namespace boost::spirit::standard_wide;
std::basic_string<wchar_t> wstr(L"abc");
BOOST_TEST(test(L"abc", lit(wstr)));
Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp (original)
+++ trunk/libs/spirit/test/karma/plus.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -67,6 +67,55 @@
}
{
+ std::string s1("aaaaa");
+ BOOST_TEST(test("aaaaa", char_ << +(char_ << char_), s1));
+ BOOST_TEST(test_delimited("a a a a a ",
+ char_ << +(char_ << char_), s1, ' '));
+
+ s1 = "a";
+ BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+ s1 = "aa";
+ BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+ s1 = "aaaa";
+ BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
+ }
+
+ {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+ using namespace boost::assign;
+
+ typedef std::pair<char, char> data;
+ std::vector<data> v1;
+ v1 += std::make_pair('a', 'a'),
+ std::make_pair('b', 'b'),
+ std::make_pair('c', 'c'),
+ std::make_pair('d', 'd'),
+ std::make_pair('e', 'e'),
+ std::make_pair('f', 'f'),
+ std::make_pair('g', 'g');
+
+ karma::rule<spirit_test::output_iterator<char>::type, data()> r;
+ r = &char_('a') << char_;
+
+ BOOST_TEST(!test("", r << +(r << r), v1));
+ BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+
+ v1 += std::make_pair('a', 'a');
+
+ BOOST_TEST(!test("", r << *(r << r), v1));
+ BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+
+ v1 += std::make_pair('a', 'a');
+
+ BOOST_TEST(test("aaa", r << +(r << r), v1));
+ BOOST_TEST(test("aaa", relaxed[r << +(r << r)], v1));
+ BOOST_TEST(!test("", strict[r << +(r << r)], v1));
+ }
+
+ {
using namespace boost::assign;
std::vector<char> v;
Added: trunk/libs/spirit/test/karma/regression_const_real_policies.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/regression_const_real_policies.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -0,0 +1,25 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+// Copyright (c) 2011 Jeroen Habraken
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// compile test verifying it's possible to use const types for real_policies.
+
+#include <boost/spirit/include/karma.hpp>
+
+#include <iterator>
+#include <string>
+
+int main()
+{
+ using namespace boost::spirit::karma;
+
+ typedef real_generator<double const, real_policies<double const> >
+ double_const_type;
+
+ std::string generated;
+ generate(std::back_inserter(generated), double_const_type(), 1.0);
+
+ return 0;
+}
Modified: trunk/libs/spirit/test/karma/repeat2.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat2.cpp (original)
+++ trunk/libs/spirit/test/karma/repeat2.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -49,6 +49,15 @@
BOOST_TEST(test_delimited("A B C D E F G H ", upper[repeat(8)[char_]], str, space));
}
+// {
+// std::string s1 = "aaaaa";
+// BOOST_TEST(test("aaaaa", char_ << repeat(2)[char_ << char_], s1));
+// s1 = "aaa";
+// BOOST_TEST(test("aaa", char_ << repeat(1, 2)[char_ << char_], s1));
+// s1 = "aa";
+// BOOST_TEST(!test("", char_ << repeat(1)[char_ << char_], s1));
+// }
+
{ // actions
namespace phx = boost::phoenix;
Modified: trunk/libs/spirit/test/karma/stream.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/stream.cpp (original)
+++ trunk/libs/spirit/test/karma/stream.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -3,13 +3,13 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#include <stdint.h>
#include <cwchar>
#include <streambuf>
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/detail/lightweight_test.hpp>
+#include <boost/cstdint.hpp>
#include <boost/spirit/include/karma_char.hpp>
#include <boost/spirit/include/karma_string.hpp>
Modified: trunk/libs/spirit/test/karma/utree2.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/utree2.cpp (original)
+++ trunk/libs/spirit/test/karma/utree2.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -62,8 +62,8 @@
rule<output_iterator, utree::const_range()> r1list;
r1 = double_ | int_ | r1str | r1list | r1ref;
-
- r1ref = r1;
+
+ r1ref = r1.alias();
r1str = string;
Modified: trunk/libs/spirit/test/karma/wstream.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/wstream.cpp (original)
+++ trunk/libs/spirit/test/karma/wstream.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -3,13 +3,13 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#include <stdint.h>
#include <cwchar>
#include <streambuf>
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/detail/lightweight_test.hpp>
+#include <boost/cstdint.hpp>
#include <boost/spirit/include/karma_char.hpp>
#include <boost/spirit/include/karma_string.hpp>
Modified: trunk/libs/spirit/test/qi/alternative.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/alternative.cpp (original)
+++ trunk/libs/spirit/test/qi/alternative.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -216,6 +216,14 @@
BOOST_TEST(s == "abc");
}
+ {
+ using boost::spirit::qi::int_;
+
+ int i = 0;
+ BOOST_TEST( (test_attr("10", int_(5) | int_(10), i)) );
+ BOOST_TEST(i == 10);
+ }
+
return boost::report_errors();
}
Modified: trunk/libs/spirit/test/qi/debug.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/debug.cpp (original)
+++ trunk/libs/spirit/test/qi/debug.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -88,7 +88,7 @@
BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false));
}
- { // std::contaner attributes
+ { // std::container attributes
typedef boost::fusion::vector<int, char> fs;
rule<char const*, std::vector<fs>(), space_type> start;
Modified: trunk/libs/spirit/test/qi/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/kleene.cpp (original)
+++ trunk/libs/spirit/test/qi/kleene.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -87,17 +87,11 @@
s.clear();
BOOST_TEST(test_attr("b b b b ", *char_, s, space) && s == "bbbb");
- // The following 4 tests show that omit does not inhibit explicit attributes
- s.clear();
- BOOST_TEST(test_attr("bbbb", *omit[char_('b')], s) && s == "bbbb");
-
+ // The following 2 tests show that omit does not inhibit explicit attributes
s.clear();
BOOST_TEST(test_attr("bbbb", omit[*char_('b')], s) && s == "bbbb");
s.clear();
- BOOST_TEST(test_attr("b b b b", *omit[char_('b')], s, space) && s == "bbbb");
-
- s.clear();
BOOST_TEST(test_attr("b b b b", omit[*char_('b')], s, space) && s == "bbbb");
}
Modified: trunk/libs/spirit/test/qi/list.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/list.cpp (original)
+++ trunk/libs/spirit/test/qi/list.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -49,6 +49,21 @@
std::string s;
BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', s));
BOOST_TEST(s == "abcdefgh");
+
+ BOOST_TEST(!test("a,b,c,d,e,f,g,h,", char_ % ','));
+ }
+
+ {
+ std::string s;
+ BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', s));
+ BOOST_TEST(s == "abcdefgh");
+
+ BOOST_TEST(!test("ab,cd,ef,gh,", (char_ >> char_) % ','));
+ BOOST_TEST(!test("ab,cd,ef,g", (char_ >> char_) % ','));
+
+ s.clear();
+ BOOST_TEST(test_attr("ab,cd,efg", (char_ >> char_) % ',' >> char_, s));
+ BOOST_TEST(s == "abcdefg");
}
{
Modified: trunk/libs/spirit/test/qi/optional.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/optional.cpp (original)
+++ trunk/libs/spirit/test/qi/optional.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -81,6 +81,12 @@
}
{
+ std::string s;
+ BOOST_TEST((test_attr("abc", char_ >> -(char_ >> char_), s)));
+ BOOST_TEST(s == "abc");
+ }
+
+ {
namespace phx = boost::phoenix;
boost::optional<int> n = 0;
Modified: trunk/libs/spirit/test/qi/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/plus.cpp (original)
+++ trunk/libs/spirit/test/qi/plus.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -94,18 +94,12 @@
}
{
- // The following 4 tests show that omit does not inhibit explicit attributes
+ // The following 2 tests show that omit does not inhibit explicit attributes
std::string s;
- BOOST_TEST(test_attr("bbbb", +omit[char_('b')], s) && s == "bbbb");
-
- s.clear();
BOOST_TEST(test_attr("bbbb", omit[+char_('b')], s) && s == "bbbb");
s.clear();
- BOOST_TEST(test_attr("b b b b ", +omit[char_('b')], s, space) && s == "bbbb");
-
- s.clear();
BOOST_TEST(test_attr("b b b b ", omit[+char_('b')], s, space) && s == "bbbb");
}
Modified: trunk/libs/spirit/test/qi/regression_repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/regression_repeat.cpp (original)
+++ trunk/libs/spirit/test/qi/regression_repeat.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -32,12 +32,12 @@
omit[-qi::char_(" \t")];
strrule_type correct_year = repeat(4)[qi::digit];
- test("1776", correct_year | repeat(2)[qi::digit], "1776");
+ test("1776", qi::hold[correct_year] | repeat(2)[qi::digit], "1776");
test("76", obsolete_year, "76");
- test("76", obsolete_year | correct_year, "76");
- test(" 76", correct_year | obsolete_year, "76");
- test("76", correct_year | obsolete_year, "76");
- test("76", correct_year | repeat(2)[qi::digit], "76");
+ test("76", qi::hold[obsolete_year] | correct_year, "76");
+ test(" 76", qi::hold[correct_year] | obsolete_year, "76");
+ test("76", qi::hold[correct_year] | obsolete_year, "76");
+ test("76", qi::hold[correct_year] | repeat(2)[qi::digit], "76");
return boost::report_errors();
}
Modified: trunk/libs/spirit/test/qi/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/repeat.cpp (original)
+++ trunk/libs/spirit/test/qi/repeat.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -77,6 +77,40 @@
BOOST_TEST(!test("aa", repeat(3, inf)[char_]));
}
+ {
+ std::string s;
+ BOOST_TEST(test_attr("aaaaaaaa", repeat[char_ >> char_], s)); // kleene synonym
+ BOOST_TEST(s == "aaaaaaaa");
+
+ s.clear();
+ BOOST_TEST(test_attr("aaaaaaaa", repeat(4)[char_ >> char_], s));
+ BOOST_TEST(s == "aaaaaaaa");
+
+ BOOST_TEST(!test("aa", repeat(3)[char_ >> char_]));
+ BOOST_TEST(!test("a", repeat(1)[char_ >> char_]));
+
+ s.clear();
+ BOOST_TEST(test_attr("aa", repeat(1, 3)[char_ >> char_], s));
+ BOOST_TEST(s == "aa");
+
+ s.clear();
+ BOOST_TEST(test_attr("aaaaaa", repeat(1, 3)[char_ >> char_], s));
+ BOOST_TEST(s == "aaaaaa");
+
+ BOOST_TEST(!test("aaaaaaa", repeat(1, 3)[char_ >> char_]));
+ BOOST_TEST(!test("a", repeat(1, 3)[char_ >> char_]));
+
+ s.clear();
+ BOOST_TEST(test_attr("aaaa", repeat(2, inf)[char_ >> char_], s));
+ BOOST_TEST(s == "aaaa");
+
+ s.clear();
+ BOOST_TEST(test_attr("aaaaaa", repeat(2, inf)[char_ >> char_], s));
+ BOOST_TEST(s == "aaaaaa");
+
+ BOOST_TEST(!test("aa", repeat(2, inf)[char_ >> char_]));
+ }
+
{ // from classic spirit tests
BOOST_TEST(test("", repeat(0, inf)['x']));
@@ -142,17 +176,11 @@
s.clear();
BOOST_TEST(test_attr("b b b b", repeat(4)[char_], s, space) && s == "bbbb");
- // The following 4 tests show that omit does not inhibit explicit attributes
- s.clear();
- BOOST_TEST(test_attr("bbbb", repeat(4)[omit[char_('b')]], s) && s == "bbbb");
-
+ // The following 2 tests show that omit does not inhibit explicit attributes
s.clear();
BOOST_TEST(test_attr("bbbb", omit[repeat(4)[char_('b')]], s) && s == "bbbb");
s.clear();
- BOOST_TEST(test_attr("b b b b", repeat(4)[omit[char_('b')]], s, space) && s == "bbbb");
-
- s.clear();
BOOST_TEST(test_attr("b b b b", omit[repeat(4)[char_('b')]], s, space) && s == "bbbb");
}
@@ -166,9 +194,7 @@
BOOST_TEST(test_attr("1 2 3", int_ >> repeat(2)[int_], v, space));
BOOST_TEST(v.size() == 3 && v[0] == 1 && v[1] == 2 && v[2] == 3);
- v.clear();
- BOOST_TEST(!test_attr("1 2", int_ >> repeat(2)[int_], v, space));
- BOOST_TEST(v.size() == 1 && v[0] == 1);
+ BOOST_TEST(!test("1 2", int_ >> repeat(2)[int_], space));
}
{ // actions
Modified: trunk/libs/spirit/test/qi/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/sequence.cpp (original)
+++ trunk/libs/spirit/test/qi/sequence.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -174,6 +174,38 @@
{ // alternative forms of attributes. Allow sequences to take in
// stl containers.
+ using boost::spirit::qi::hold;
+
+ std::vector<char> v;
+ BOOST_TEST(test_attr("abc", char_ >> *(char_ >> char_), v));
+ BOOST_TEST(v.size() == 3);
+ BOOST_TEST(v[0] == 'a');
+ BOOST_TEST(v[1] == 'b');
+ BOOST_TEST(v[2] == 'c');
+
+ v.clear();
+ BOOST_TEST(!test_attr("abcd", char_ >> *(char_ >> char_), v));
+
+ v.clear();
+ BOOST_TEST(test_attr("abcdef", char_ >> *hold[char_ >> char_] >> char_, v));
+ BOOST_TEST(v.size() == 6);
+ BOOST_TEST(v[0] == 'a');
+ BOOST_TEST(v[1] == 'b');
+ BOOST_TEST(v[2] == 'c');
+ BOOST_TEST(v[3] == 'd');
+ BOOST_TEST(v[4] == 'e');
+ BOOST_TEST(v[5] == 'f');
+
+ v.clear();
+ BOOST_TEST(test_attr("abc", char_ >> +(char_ >> char_), v));
+ BOOST_TEST(v.size() == 3);
+ BOOST_TEST(v[0] == 'a');
+ BOOST_TEST(v[1] == 'b');
+ BOOST_TEST(v[2] == 'c');
+ }
+
+ { // alternative forms of attributes. Allow sequences to take in
+ // stl containers.
std::vector<char> v;
BOOST_TEST(test_attr("abc", char_ >> -(+char_), v));
@@ -248,7 +280,6 @@
}
{ // testing "what"
-
print_info(what(alpha | char_('x') >> lit("hello") >> int_));
}
Modified: trunk/libs/spirit/test/qi/utree1.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree1.cpp (original)
+++ trunk/libs/spirit/test/qi/utree1.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -165,26 +165,22 @@
BOOST_TEST(test_attr("a25.5b", r1 > r2 >> r3, ut));
BOOST_TEST(ut.which() == utree_type::list_type);
- BOOST_TEST(check(ut, "( \"a\" ( ( 25.5 ) ( \"b\" ) ) )"));
- // FIXME: "( \"a\" ( 25.5 ) ( \"b\" ) )"
+ BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
ut.clear();
BOOST_TEST(test_attr("a25.5b", r3 >> r2 > r1, ut));
BOOST_TEST(ut.which() == utree_type::list_type);
- BOOST_TEST(check(ut, "( ( ( \"a\" ) ( 25.5 ) ) \"b\" )"));
- // FIXME: "( ( \"a\" ) ( 25.5 ) \"b\" )"
+ BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
ut.clear();
BOOST_TEST(test_attr("a25.5b", char_ > r2 >> r3, ut));
BOOST_TEST(ut.which() == utree_type::list_type);
- BOOST_TEST(check(ut, "( \"a\" ( ( 25.5 ) ( \"b\" ) ) )"));
- // FIXME: "( \"a\" ( 25.5 ) ( \"b\" ) )"
+ BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
ut.clear();
BOOST_TEST(test_attr("a25.5b", r3 >> r2 > char_, ut));
BOOST_TEST(ut.which() == utree_type::list_type);
- BOOST_TEST(check(ut, "( ( ( \"a\" ) ( 25.5 ) ) \"b\" )"));
- // FIXME: "( ( \"a\" ) ( 25.5 ) \"b\" )"
+ BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
}
return boost::report_errors();
Modified: trunk/libs/spirit/test/qi/utree2.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree2.cpp (original)
+++ trunk/libs/spirit/test/qi/utree2.cpp 2011-02-04 22:48:49 EST (Fri, 04 Feb 2011)
@@ -86,8 +86,9 @@
ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
ut.clear();
- rule<char const*, utree(), space_type> r1 =
- strict_double | int_ | ~char_("()") | ('(' >> *r1 >> ')');
+ rule<char const*, utree(), space_type> r1;
+ rule<char const*, utree::list_type(), space_type> r2 = '(' >> *r1 >> ')';
+ r1 = strict_double | int_ | ~char_("()") | r2;
BOOST_TEST(test_attr("(x y)", r1, ut, space) &&
ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk