Boost logo

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