|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56475 - in trunk/boost/spirit/home/karma: directive operator
From: hartmut.kaiser_at_[hidden]
Date: 2009-09-29 12:58:04
Author: hkaiser
Date: 2009-09-29 12:58:03 EDT (Tue, 29 Sep 2009)
New Revision: 56475
URL: http://svn.boost.org/trac/boost/changeset/56475
Log:
Spirit: fixed Karma repeating operators and directives to account for failing subjects
Text files modified:
trunk/boost/spirit/home/karma/directive/repeat.hpp | 58 +++++++++++++++++++++------------------
trunk/boost/spirit/home/karma/operator/kleene.hpp | 9 ++++--
trunk/boost/spirit/home/karma/operator/list.hpp | 46 ++++++++++++++++++++++++++-----
trunk/boost/spirit/home/karma/operator/plus.hpp | 13 +++++---
4 files changed, 83 insertions(+), 43 deletions(-)
Modified: trunk/boost/spirit/home/karma/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/repeat.hpp (original)
+++ trunk/boost/spirit/home/karma/directive/repeat.hpp 2009-09-29 12:58:03 EDT (Tue, 29 Sep 2009)
@@ -124,11 +124,28 @@
struct repeat_generator
: unary_generator<repeat_generator<Subject, LoopIter> >
{
+ private:
+ // iterate over the given container until its exhausted or the embedded
+ // (left) generator succeeds
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Iterator>
+ bool generate_subject(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Iterator& it, Iterator const& end) const
+ {
+ while (!traits::compare(it, end))
+ {
+ if (subject.generate(sink, ctx, d, traits::deref(it)))
+ return true;
+ traits::next(it);
+ }
+ return false;
+ }
+
+ public:
typedef Subject subject_type;
- typedef mpl::int_<
- generator_properties::countingbuffer | subject_type::properties::value
- > properties;
+ typedef mpl::int_<subject_type::properties::value> properties;
// Build a std::vector from the subject's attribute. Note
// that build_std_vector may return unused_type if the
@@ -156,38 +173,25 @@
iterator_type end = traits::end(attr);
typename LoopIter::type i = iter.start();
+ // generate the minimal required amount of output
+ for (/**/; !iter.got_min(i); ++i, traits::next(it))
{
- // inhibit (redirect) output, disable counting while buffering
- detail::enable_buffering<OutputIterator> buffering(sink);
-
+ if (!generate_subject(sink, ctx, d, it, end))
{
- detail::disable_counting<OutputIterator> nocounting(sink);
-
- // generate the minimal required amount of output
- for (/**/; !iter.got_min(i); ++i, traits::next(it))
- {
- if (traits::compare(it, end) ||
- !subject.generate(sink, ctx, d, traits::deref(it)))
- {
- // if we fail before reaching the minimum iteration
- // required, do not output anything and return false
- return false;
- }
- }
- } // re-enable counting
-
- // copy the output generated so far to the target output iterator
- buffering.buffer_copy();
+ // if we fail before reaching the minimum iteration
+ // required, do not output anything and return false
+ return false;
+ }
}
// generate some more up to the maximum specified
- bool result = true;
- for (/**/; result && !iter.got_max(i) && !traits::compare(it, end);
+ for (/**/; detail::sink_is_good(sink) && !iter.got_max(i);
++i, traits::next(it))
{
- result = subject.generate(sink, ctx, d, traits::deref(it));
+ if (!generate_subject(sink, ctx, d, it, end))
+ break;
}
- return result;
+ return detail::sink_is_good(sink);
}
template <typename Context>
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 2009-09-29 12:58:03 EDT (Tue, 29 Sep 2009)
@@ -69,10 +69,13 @@
iterator_type end = traits::end(attr);
// kleene fails only if the underlying output fails
- bool result = true;
- for (/**/; result && !traits::compare(it, end); traits::next(it))
+ for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end);
+ traits::next(it))
{
- result = subject.generate(sink, ctx, d, traits::deref(it));
+ // Ignore return value, failing subject generators are just
+ // skipped. This allows to selectively generate items in the
+ // provided attribute.
+ subject.generate(sink, ctx, d, traits::deref(it));
}
return detail::sink_is_good(sink);
}
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 2009-09-29 12:58:03 EDT (Tue, 29 Sep 2009)
@@ -36,11 +36,33 @@
template <typename Left, typename Right>
struct list : binary_generator<list<Left, Right> >
{
+ private:
+ // iterate over the given container until its exhausted or the embedded
+ // (left) generator succeeds
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Iterator>
+ bool generate_left(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Iterator& it, Iterator const& end) const
+ {
+ while (!traits::compare(it, end))
+ {
+ if (left.generate(sink, ctx, d, traits::deref(it)))
+ return true;
+ traits::next(it);
+ }
+ return false;
+ }
+
+ public:
typedef Left left_type;
typedef Right right_type;
typedef mpl::int_<
- left_type::properties::value | right_type::properties::value
+ left_type::properties::value
+ | right_type::properties::value
+ | generator_properties::buffering
+ | generator_properties::counting
> properties;
// Build a std::vector from the LHS's attribute. Note
@@ -69,16 +91,24 @@
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
- bool result = !traits::compare(it, end);
- if (result && left.generate(sink, ctx, d, traits::deref(it)))
+ if (generate_left(sink, ctx, d, it, end))
{
- for (traits::next(it); result && !traits::compare(it, end);
- traits::next(it))
+ for (traits::next(it); !traits::compare(it, end); traits::next(it))
{
- result = right.generate(sink, ctx, d, unused) &&
- left.generate(sink, ctx, d, traits::deref(it));
+ // wrap the given output iterator as generate_left might fail
+ detail::enable_buffering<OutputIterator> buffering(sink);
+ {
+ detail::disable_counting<OutputIterator> nocounting(sink);
+
+ if (!right.generate(sink, ctx, d, unused))
+ return false; // shouldn't happen
+
+ if (!generate_left(sink, ctx, d, it, end))
+ break; // return true as one item succeeded
+ }
+ buffering.buffer_copy();
}
- return result;
+ return true;
}
return false;
}
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 2009-09-29 12:58:03 EDT (Tue, 29 Sep 2009)
@@ -72,13 +72,16 @@
if (traits::compare(it, end))
return false;
- // from now on plus fails only if the underlying output fails
- bool result = true;
- for (/**/; result && !traits::compare(it, end); traits::next(it))
+ // 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))
{
- result = subject.generate(sink, ctx, d, traits::deref(it));
+ if (subject.generate(sink, ctx, d, traits::deref(it)))
+ result = true;
}
- return detail::sink_is_good(sink);
+ return result && detail::sink_is_good(sink);
}
template <typename Context>
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