|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r60451 - in trunk: boost/spirit/home/karma/directive boost/spirit/home/karma/operator libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2010-03-10 18:37:06
Author: hkaiser
Date: 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
New Revision: 60451
URL: http://svn.boost.org/trac/boost/changeset/60451
Log:
Spirit: Fixing problem in Karma repetitive generators.
Text files modified:
trunk/boost/spirit/home/karma/directive/repeat.hpp | 22 ++++++++++--
trunk/boost/spirit/home/karma/operator/kleene.hpp | 31 +++++++++++++++--
trunk/boost/spirit/home/karma/operator/list.hpp | 22 ++++++++++--
trunk/boost/spirit/home/karma/operator/plus.hpp | 34 ++++++++++++++++++-
trunk/libs/spirit/test/karma/attribute.cpp | 2
trunk/libs/spirit/test/karma/kleene.cpp | 28 ++++++++++++++++
trunk/libs/spirit/test/karma/list.cpp | 70 +++++++++++++++++++++++++++------------
trunk/libs/spirit/test/karma/plus.cpp | 28 ++++++++++++++++
trunk/libs/spirit/test/karma/repeat.cpp | 31 +++++++++++++++++
9 files changed, 231 insertions(+), 37 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 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -141,10 +141,12 @@
// (left) generator succeeds
template <
typename OutputIterator, typename Context, typename Delimiter
- , typename Iterator>
+ , typename Iterator, typename Attribute>
bool generate_subject(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Iterator& it, Iterator& end) const
+ , Delimiter const& d, Iterator& it, Iterator& end, Attribute const&) const
{
+ // Failing subject generators are just skipped. This allows to
+ // selectively generate items in the provided attribute.
while (!traits::compare(it, end))
{
if (subject.generate(sink, ctx, d, traits::deref(it)))
@@ -154,6 +156,18 @@
return false;
}
+ template <
+ typename OutputIterator, typename Context, typename Delimiter
+ , typename Iterator>
+ bool generate_subject(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, Iterator&, Iterator&, 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.
+ return subject.generate(sink, ctx, d, unused);
+ }
+
public:
typedef Subject subject_type;
@@ -188,7 +202,7 @@
// generate the minimal required amount of output
for (/**/; !iter.got_min(i); ++i, traits::next(it))
{
- if (!generate_subject(sink, ctx, d, it, end))
+ if (!generate_subject(sink, ctx, d, it, end, attr))
{
// if we fail before reaching the minimum iteration
// required, do not output anything and return false
@@ -200,7 +214,7 @@
for (/**/; detail::sink_is_good(sink) && !iter.got_max(i);
++i, traits::next(it))
{
- if (!generate_subject(sink, ctx, d, it, end))
+ if (!generate_subject(sink, ctx, d, it, end, attr))
break;
}
return detail::sink_is_good(sink);
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 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -39,6 +39,31 @@
template <typename Subject>
struct kleene : unary_generator<kleene<Subject> >
{
+ 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, failing subject generators are just
+ // skipped. This allows to selectively generate items in the
+ // provided attribute.
+ subject.generate(sink, ctx, d, attr);
+ return true;
+ }
+
+ 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.
+ return subject.generate(sink, ctx, d, unused);
+ }
+
+ public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
@@ -72,10 +97,8 @@
for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end);
traits::next(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));
+ if (!generate_subject(sink, ctx, d, traits::deref(it)))
+ break;
}
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 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -42,10 +42,12 @@
// (left) generator succeeds
template <
typename OutputIterator, typename Context, typename Delimiter
- , typename Iterator>
+ , typename Iterator, typename Attribute>
bool generate_left(OutputIterator& sink, Context& ctx
- , Delimiter const& d, Iterator& it, Iterator& end) const
+ , Delimiter const& d, Iterator& it, Iterator& end, Attribute const&) const
{
+ // 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)))
@@ -55,6 +57,18 @@
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
+ {
+ // 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);
+ }
+
public:
typedef Left left_type;
typedef Right right_type;
@@ -92,7 +106,7 @@
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
- if (generate_left(sink, ctx, d, it, end))
+ if (generate_left(sink, ctx, d, it, end, attr))
{
for (traits::next(it); !traits::compare(it, end); traits::next(it))
{
@@ -104,7 +118,7 @@
if (!right.generate(sink, ctx, d, unused))
return false; // shouldn't happen
- if (!generate_left(sink, ctx, d, it, end))
+ if (!generate_left(sink, ctx, d, it, end, attr))
break; // return true as one item succeeded
}
buffering.buffer_copy();
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 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -39,6 +39,36 @@
template <typename Subject>
struct plus : unary_generator<plus<Subject> >
{
+ 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, failing subject generators are just
+ // skipped. This allows to selectively generate items in the
+ // provided attribute.
+ if (subject.generate(sink, ctx, d, attr))
+ result = true;
+ return true;
+ }
+
+ template <typename OutputIterator, typename Context, typename Delimiter>
+ bool generate_subject(OutputIterator& sink, Context& ctx
+ , Delimiter const& d, unused_type, bool& result) 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)) {
+ result = true;
+ return true;
+ }
+ return false;
+ }
+
+ public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
@@ -78,8 +108,8 @@
for (/**/; detail::sink_is_good(sink) && !traits::compare(it, end);
traits::next(it))
{
- if (subject.generate(sink, ctx, d, traits::deref(it)))
- result = true;
+ if (!generate_subject(sink, ctx, d, traits::deref(it), result))
+ break;
}
return result && detail::sink_is_good(sink);
}
Modified: trunk/libs/spirit/test/karma/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/attribute.cpp (original)
+++ trunk/libs/spirit/test/karma/attribute.cpp 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -105,7 +105,7 @@
karma::string << karma::string << karma::double_;
BOOST_TEST(test("s11s122.5\ns21s223.4", r % karma::eol, v));
- BOOST_TEST(test_delimited("s11s122.5\n s21s223.4",
+ BOOST_TEST(test_delimited("s11s122.5 \n s21s223.4 ",
r % karma::eol, v, ' '));
}
Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp (original)
+++ trunk/libs/spirit/test/karma/kleene.cpp 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -27,6 +27,24 @@
using namespace spirit_test;
///////////////////////////////////////////////////////////////////////////////
+struct action
+{
+ action (std::vector<char>& vec)
+ : vec(vec), it(vec.begin())
+ {}
+
+ void operator()(unsigned& value, boost::spirit::unused_type, bool& pass) const
+ {
+ pass = (it != vec.end());
+ if (pass)
+ value = *it++;
+ }
+
+ std::vector<char>& vec;
+ mutable std::vector<char>::iterator it;
+};
+
+///////////////////////////////////////////////////////////////////////////////
int main()
{
using namespace boost::spirit;
@@ -122,6 +140,16 @@
BOOST_TEST(test("", *r, v2));
}
+ {
+ // make sure user defined end condition is applied if no attribute
+ // is passed in
+ using namespace boost::assign;
+
+ std::vector<char> v;
+ v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
+ BOOST_TEST(test("[6162636465666768]", '[' << *hex[action(v)] << ']'));
+ }
+
return boost::report_errors();
}
Modified: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/list.cpp (original)
+++ trunk/libs/spirit/test/karma/list.cpp 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -29,9 +29,28 @@
#include "test.hpp"
using namespace spirit_test;
+using boost::spirit::unused_type;
-int
-main()
+///////////////////////////////////////////////////////////////////////////////
+struct action
+{
+ action (std::vector<char>& vec)
+ : vec(vec), it(vec.begin())
+ {}
+
+ void operator()(unsigned& value, unused_type const&, bool& pass) const
+ {
+ pass = (it != vec.end());
+ if (pass)
+ value = *it++;
+ }
+
+ std::vector<char>& vec;
+ mutable std::vector<char>::iterator it;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
{
using namespace boost::spirit;
using namespace boost::spirit::ascii;
@@ -41,26 +60,26 @@
std::vector<char> v;
v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
-// {
-// BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', v));
-// BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
-// char_ % ',', v, space));
-// }
-//
-// {
-// std::string s ("abcdefgh");
-// BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', s));
-// BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
-// char_ % ',', s, space));
-// }
-//
-// { // actions
-// namespace phx = boost::phoenix;
-//
-// BOOST_TEST(test("a,b,c,d,e,f,g,h", (char_ % ',')[_1 = phx::ref(v)]));
-// BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
-// (char_ % ',')[_1 = phx::ref(v)], space));
-// }
+ {
+ BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', v));
+ BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
+ char_ % ',', v, space));
+ }
+
+ {
+ std::string s ("abcdefgh");
+ BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', s));
+ BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
+ char_ % ',', s, space));
+ }
+
+ { // actions
+ namespace phx = boost::phoenix;
+
+ BOOST_TEST(test("a,b,c,d,e,f,g,h", (char_ % ',')[_1 = phx::ref(v)]));
+ BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ",
+ (char_ % ',')[_1 = phx::ref(v)], space));
+ }
// failing sub-generators
{
@@ -98,6 +117,13 @@
BOOST_TEST(!test("", r % ',', v2));
}
+ {
+ // make sure user defined end condition is applied if no attribute
+ // is passed in
+ BOOST_TEST(test("[61,62,63,64,65,66,67,68]",
+ '[' << hex[action(v)] % ',' << ']'));
+ }
+
return boost::report_errors();
}
Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp (original)
+++ trunk/libs/spirit/test/karma/plus.cpp 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -27,6 +27,24 @@
using namespace spirit_test;
///////////////////////////////////////////////////////////////////////////////
+struct action
+{
+ action (std::vector<char>& vec)
+ : vec(vec), it(vec.begin())
+ {}
+
+ void operator()(unsigned& value, boost::spirit::unused_type, bool& pass) const
+ {
+ pass = (it != vec.end());
+ if (pass)
+ value = *it++;
+ }
+
+ std::vector<char>& vec;
+ mutable std::vector<char>::iterator it;
+};
+
+///////////////////////////////////////////////////////////////////////////////
int main()
{
using namespace boost::spirit;
@@ -126,6 +144,16 @@
BOOST_TEST(!test("", +r, v2));
}
+ {
+ // make sure user defined end condition is applied if no attribute
+ // is passed in
+ using namespace boost::assign;
+
+ std::vector<char> v;
+ v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
+ BOOST_TEST(test("[6162636465666768]", '[' << +hex[action(v)] << ']'));
+ }
+
return boost::report_errors();
}
Modified: trunk/libs/spirit/test/karma/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat.cpp (original)
+++ trunk/libs/spirit/test/karma/repeat.cpp 2010-03-10 18:37:04 EST (Wed, 10 Mar 2010)
@@ -13,6 +13,7 @@
#include <boost/spirit/include/karma_string.hpp>
#include <boost/spirit/include/karma_numeric.hpp>
#include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
#include <boost/spirit/include/karma_action.hpp>
#include <boost/spirit/include/karma_nonterminal.hpp>
#include <boost/spirit/include/karma_auxiliary.hpp>
@@ -32,12 +33,31 @@
using namespace spirit_test;
///////////////////////////////////////////////////////////////////////////////
+struct action
+{
+ action (std::vector<char>& vec)
+ : vec(vec), it(vec.begin())
+ {}
+
+ void operator()(unsigned& value, boost::spirit::unused_type, bool& pass) const
+ {
+ pass = (it != vec.end());
+ if (pass)
+ value = *it++;
+ }
+
+ std::vector<char>& vec;
+ mutable std::vector<char>::iterator it;
+};
+
+///////////////////////////////////////////////////////////////////////////////
int main()
{
using namespace boost::spirit::ascii;
using boost::spirit::karma::repeat;
using boost::spirit::karma::inf;
using boost::spirit::karma::int_;
+ using boost::spirit::karma::hex;
using boost::spirit::karma::_1;
{
@@ -161,6 +181,17 @@
BOOST_TEST(!test("", repeat(4, inf)[r], v3));
}
+ {
+ // make sure user defined end condition is applied if no attribute
+ // is passed in
+ using namespace boost::assign;
+
+ std::vector<char> v;
+ v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
+ BOOST_TEST(test("[6162636465666768]",
+ '[' << repeat[hex[action(v)]] << ']'));
+ }
+
// we support Phoenix attributes only starting with V2.2
#if SPIRIT_VERSION >= 0x2020
{
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