Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61491 - in trunk: boost/spirit/home/karma boost/spirit/home/karma/detail boost/spirit/home/karma/directive boost/spirit/home/karma/operator boost/spirit/home/support boost/spirit/include libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-22 16:25:12


Author: hkaiser
Date: 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
New Revision: 61491
URL: http://svn.boost.org/trac/boost/changeset/61491

Log:
Spirit: added strict mode to Karma, new directives strict[] and relaxed[]. No docs yet
Added:
   trunk/boost/spirit/home/karma/detail/get_stricttag.hpp (contents, props changed)
   trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp (contents, props changed)
   trunk/boost/spirit/include/karma_strict_relaxed.hpp (contents, props changed)
Text files modified:
   trunk/boost/spirit/home/karma/detail/get_casetag.hpp | 3 +
   trunk/boost/spirit/home/karma/directive.hpp | 10 ++++-
   trunk/boost/spirit/home/karma/directive/repeat.hpp | 76 +++++++++++++++++++++++++++++++++-----
   trunk/boost/spirit/home/karma/operator/kleene.hpp | 57 +++++++++++++++++++++++-----
   trunk/boost/spirit/home/karma/operator/list.hpp | 71 ++++++++++++++++++++++++++++-------
   trunk/boost/spirit/home/karma/operator/plus.hpp | 54 +++++++++++++++++++++++----
   trunk/boost/spirit/home/karma/operator/sequence.hpp | 79 ++++++++++++++++++++++++++++++++++++---
   trunk/boost/spirit/home/support/common_terminals.hpp | 2 +
   trunk/libs/spirit/test/karma/kleene.cpp | 16 ++++++++
   trunk/libs/spirit/test/karma/list.cpp | 17 ++++++++
   trunk/libs/spirit/test/karma/plus.cpp | 18 ++++++++
   trunk/libs/spirit/test/karma/repeat.cpp | 29 ++++++++++++++
   trunk/libs/spirit/test/karma/sequence.cpp | 34 +++++++++++++++++
   13 files changed, 413 insertions(+), 53 deletions(-)

Modified: trunk/boost/spirit/home/karma/detail/get_casetag.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/get_casetag.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/get_casetag.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -12,6 +12,8 @@
 #endif
 
 #include <boost/mpl/identity.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
@@ -22,7 +24,6 @@
     struct get_casetag<Modifiers, true>
       : mpl::if_<has_modifier<Modifiers, tag::char_code_base<tag::lower> >
           , tag::lower, tag::upper> {};
-
 }}}}
 
 #endif

Added: trunk/boost/spirit/home/karma/detail/get_stricttag.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/detail/get_stricttag.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,33 @@
+// Copyright (c) 2001-2010 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)
+
+#if !defined(BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM)
+#define BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
+
+namespace boost { namespace spirit { namespace karma { namespace detail
+{
+ // the default mode for Karma is 'relaxed'
+ template <
+ typename Modifiers
+ , typename StrictModifier = typename mpl::or_<
+ has_modifier<Modifiers, tag::strict>
+ , has_modifier<Modifiers, tag::relaxed> >::type>
+ struct get_stricttag : mpl::false_ {};
+
+ // strict mode is enforced only when tag::strict is on the modifiers list
+ template <typename Modifiers>
+ struct get_stricttag<Modifiers, mpl::true_>
+ : has_modifier<Modifiers, tag::strict> {};
+}}}}
+
+#endif

Modified: trunk/boost/spirit/home/karma/directive.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive.hpp (original)
+++ trunk/boost/spirit/home/karma/directive.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -48,8 +48,8 @@
 #include <boost/spirit/home/karma/directive/repeat.hpp>
 
 ///////////////////////////////////////////////////////////////////////////////
-// omit directive
-// omit[...]
+// omit and skip[] directives
+// omit[...], skip[...]
 ///////////////////////////////////////////////////////////////////////////////
 #include <boost/spirit/home/karma/directive/omit.hpp>
 
@@ -59,4 +59,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 #include <boost/spirit/home/karma/directive/buffer.hpp>
 
+///////////////////////////////////////////////////////////////////////////////
+// strict and relaxed directives
+// strict[...], relaxed[...]
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/home/karma/directive/strict_relaxed.hpp>
+
 #endif

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-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -12,6 +12,8 @@
 #endif
 
 #include <boost/spirit/home/karma/meta_compiler.hpp>
+#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
 #include <boost/spirit/home/karma/operator/kleene.hpp>
@@ -61,7 +63,6 @@
       , tag::repeat
       , 2 // arity
> : mpl::true_ {};
-
 }}
 
 namespace boost { namespace spirit { namespace karma
@@ -132,9 +133,9 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
- template <typename Subject, typename LoopIter>
- struct repeat_generator
- : unary_generator<repeat_generator<Subject, LoopIter> >
+ template <typename Subject, typename LoopIter, typename Strict
+ , typename Derived>
+ struct base_repeat_generator : unary_generator<Derived>
     {
     private:
         // iterate over the given container until its exhausted or the embedded
@@ -151,6 +152,8 @@
             {
                 if (subject.generate(sink, ctx, d, traits::deref(it)))
                     return true;
+ if (Strict::value)
+ return false;
                 traits::next(it);
             }
             return false;
@@ -183,7 +186,7 @@
>
         {};
 
- repeat_generator(Subject const& subject, LoopIter const& iter)
+ base_repeat_generator(Subject const& subject, LoopIter const& iter)
           : subject(subject), iter(iter) {}
 
         template <typename OutputIterator, typename Context, typename Delimiter
@@ -230,14 +233,49 @@
         LoopIter iter;
     };
 
+ template <typename Subject, typename LoopIter>
+ struct repeat_generator
+ : base_repeat_generator<
+ Subject, LoopIter, mpl::false_
+ , repeat_generator<Subject, LoopIter> >
+ {
+ typedef base_repeat_generator<
+ Subject, LoopIter, mpl::false_, repeat_generator
+ > base_repeat_generator_;
+
+ repeat_generator(Subject const& subject, LoopIter const& iter)
+ : base_repeat_generator_(subject, iter)
+ {}
+ };
+
+ template <typename Subject, typename LoopIter>
+ struct strict_repeat_generator
+ : base_repeat_generator<
+ Subject, LoopIter, mpl::true_
+ , strict_repeat_generator<Subject, LoopIter> >
+ {
+ typedef base_repeat_generator<
+ Subject, LoopIter, mpl::true_, strict_repeat_generator
+ > base_repeat_generator_;
+
+ strict_repeat_generator(Subject const& subject, LoopIter const& iter)
+ : base_repeat_generator_(subject, iter)
+ {}
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
     template <typename Subject, typename Modifiers>
     struct make_directive<tag::repeat, Subject, Modifiers>
     {
- typedef kleene<Subject> result_type;
- result_type operator()(unused_type, Subject const& subject, unused_type) const
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_kleene<Subject>, kleene<Subject>
+ >::type result_type;
+
+ result_type operator()(unused_type, Subject const& subject
+ , unused_type) const
         {
             return result_type(subject);
         }
@@ -248,7 +286,12 @@
         terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
     {
         typedef exact_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
 
         template <typename Terminal>
         result_type operator()(
@@ -263,7 +306,12 @@
         terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
     {
         typedef finite_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
 
         template <typename Terminal>
         result_type operator()(
@@ -284,7 +332,12 @@
         , fusion::vector2<T, inf_type> >, Subject, Modifiers>
     {
         typedef infinite_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
 
         template <typename Terminal>
         result_type operator()(
@@ -302,6 +355,9 @@
     struct has_semantic_action<karma::repeat_generator<Subject, LoopIter> >
       : unary_has_semantic_action<Subject> {};
 
+ template <typename Subject, typename LoopIter>
+ struct has_semantic_action<karma::strict_repeat_generator<Subject, LoopIter> >
+ : unary_has_semantic_action<Subject> {};
 }}}
 
 #endif

Added: trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,76 @@
+// Copyright (c) 2001-2010 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)
+
+#if !defined(SPIRIT_STRICT_RELAXED_APR_22_2010_0959AM)
+#define SPIRIT_STRICT_RELAXED_APR_22_2010_0959AM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/common_terminals.hpp>
+#include <boost/spirit/home/support/modify.hpp>
+#include <boost/spirit/home/karma/domain.hpp>
+#include <boost/spirit/home/karma/meta_compiler.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_directive<karma::domain, tag::strict> // enables strict[]
+ : mpl::true_ {};
+
+ template <>
+ struct use_directive<karma::domain, tag::relaxed> // enables relaxed[]
+ : mpl::true_ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct is_modifier_directive<karma::domain, tag::strict>
+ : mpl::true_ {};
+
+ template <>
+ struct is_modifier_directive<karma::domain, tag::relaxed>
+ : mpl::true_ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Don't add tag::strict or tag::relaxed if there is already one of those
+ // in the modifier list
+ template <typename Current>
+ struct compound_modifier<Current, tag::strict
+ , typename enable_if<has_modifier<Current, tag::relaxed> >::type>
+ : Current
+ {
+ compound_modifier()
+ : Current() {}
+
+ compound_modifier(Current const& current, tag::strict const&)
+ : Current(current) {}
+ };
+
+ template <typename Current>
+ struct compound_modifier<Current, tag::relaxed
+ , typename enable_if<has_modifier<Current, tag::strict> >::type>
+ : Current
+ {
+ compound_modifier()
+ : Current() {}
+
+ compound_modifier(Current const& current, tag::relaxed const&)
+ : Current(current) {}
+ };
+
+ namespace karma
+ {
+ using boost::spirit::strict;
+ using boost::spirit::strict_type;
+ using boost::spirit::relaxed;
+ using boost::spirit::relaxed_type;
+ }
+}}
+
+#endif

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-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
 #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/get_stricttag.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -30,14 +31,13 @@
     template <>
     struct use_operator<karma::domain, proto::tag::dereference> // enables *g
       : mpl::true_ {};
-
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
- template <typename Subject>
- struct kleene : unary_generator<kleene<Subject> >
+ template <typename Subject, typename Strict, typename Derived>
+ struct base_kleene : unary_generator<Derived>
     {
     private:
         template <
@@ -49,8 +49,8 @@
             // 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;
+ bool r = subject.generate(sink, ctx, d, attr);
+ return !Strict::value || r;
         }
 
         template <typename OutputIterator, typename Context, typename Delimiter>
@@ -77,7 +77,7 @@
>
         {};
 
- kleene(Subject const& subject)
+ base_kleene(Subject const& subject)
           : subject(subject) {}
 
         template <
@@ -112,14 +112,48 @@
         Subject subject;
     };
 
+ template <typename Subject>
+ struct kleene
+ : base_kleene<Subject, mpl::false_, kleene<Subject> >
+ {
+ typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
+
+ kleene(Subject const& subject)
+ : base_kleene_(subject)
+ {}
+ };
+
+ template <typename Subject>
+ struct strict_kleene
+ : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
+ {
+ typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
+
+ strict_kleene(Subject const& subject)
+ : base_kleene_(subject)
+ {}
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
- template <typename Elements, typename Modifiers>
- struct make_composite<proto::tag::dereference, Elements, Modifiers>
- : make_unary_composite<Elements, kleene>
- {};
+ namespace detail
+ {
+ template <typename Subject, bool strict_mode = false>
+ struct make_kleene
+ : make_unary_composite<Subject, kleene>
+ {};
 
+ template <typename Subject>
+ struct make_kleene<Subject, true>
+ : make_unary_composite<Subject, strict_kleene>
+ {};
+ }
+
+ template <typename Subject, typename Modifiers>
+ struct make_composite<proto::tag::dereference, Subject, Modifiers>
+ : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
+ {};
 }}}
 
 namespace boost { namespace spirit { namespace traits
@@ -128,6 +162,9 @@
     struct has_semantic_action<karma::kleene<Subject> >
       : unary_has_semantic_action<Subject> {};
 
+ template <typename Subject>
+ struct has_semantic_action<karma::strict_kleene<Subject> >
+ : unary_has_semantic_action<Subject> {};
 }}}
 
 #endif

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-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
 #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/get_stricttag.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -28,14 +29,13 @@
     template <>
     struct use_operator<karma::domain, proto::tag::modulus> // enables g % d
       : mpl::true_ {};
-
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
- template <typename Left, typename Right>
- struct list : binary_generator<list<Left, Right> >
+ template <typename Left, typename Right, typename Strict, typename Derived>
+ struct base_list : binary_generator<Derived>
     {
     private:
         // iterate over the given container until its exhausted or the embedded
@@ -46,13 +46,19 @@
         bool generate_left(OutputIterator& sink, Context& ctx
           , 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)))
- return true;
- traits::next(it);
+ 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);
+ }
             }
             return false;
         }
@@ -89,7 +95,7 @@
                 typename traits::attribute_of<Left, Context, Iterator>::type>
         {};
 
- list(Left const& left, Right const& right)
+ base_list(Left const& left, Right const& right)
           : left(left), right(right)
         {}
 
@@ -139,14 +145,46 @@
         Right right;
     };
 
+ template <typename Left, typename Right>
+ struct list
+ : base_list<Left, Right, mpl::false_, list<Left, Right> >
+ {
+ typedef base_list<Left, Right, mpl::false_, list> base_list_;
+
+ list(Left const& left, Right const& right)
+ : base_list_(left, right) {}
+ };
+
+ template <typename Left, typename Right>
+ struct strict_list
+ : base_list<Left, Right, mpl::true_, strict_list<Left, Right> >
+ {
+ typedef base_list<Left, Right, mpl::true_, strict_list> base_list_;
+
+ strict_list (Left const& left, Right const& right)
+ : base_list_(left, right) {}
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
- template <typename Elements, typename Modifiers>
- struct make_composite<proto::tag::modulus, Elements, Modifiers>
- : make_binary_composite<Elements, list>
- {};
+ namespace detail
+ {
+ template <typename Subject, bool strict_mode = false>
+ struct make_list
+ : make_binary_composite<Subject, list>
+ {};
+
+ template <typename Subject>
+ struct make_list<Subject, true>
+ : make_binary_composite<Subject, strict_list>
+ {};
+ }
 
+ template <typename Subject, typename Modifiers>
+ struct make_composite<proto::tag::modulus, Subject, Modifiers>
+ : detail::make_list<Subject, detail::get_stricttag<Modifiers>::value>
+ {};
 }}}
 
 namespace boost { namespace spirit { namespace traits
@@ -155,6 +193,9 @@
     struct has_semantic_action<karma::list<Left, Right> >
       : binary_has_semantic_action<Left, Right> {};
 
+ template <typename Left, typename Right>
+ struct has_semantic_action<karma::strict_list<Left, Right> >
+ : binary_has_semantic_action<Left, Right> {};
 }}}
 
 #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 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
 #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/get_stricttag.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/container.hpp>
@@ -30,14 +31,13 @@
     template <>
     struct use_operator<karma::domain, proto::tag::unary_plus> // enables +g
       : mpl::true_ {};
-
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
- template <typename Subject>
- struct plus : unary_generator<plus<Subject> >
+ template <typename Subject, typename Strict, typename Derived>
+ struct base_plus : unary_generator<Derived>
     {
     private:
         template <
@@ -49,9 +49,11 @@
             // 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))
+ if (subject.generate(sink, ctx, d, attr)) {
                 result = true;
- return true;
+ return true;
+ }
+ return !Strict::value;
         }
 
         template <typename OutputIterator, typename Context, typename Delimiter>
@@ -82,7 +84,7 @@
>
         {};
 
- plus(Subject const& subject)
+ base_plus(Subject const& subject)
           : subject(subject) {}
 
         template <
@@ -123,15 +125,48 @@
         Subject subject;
     };
 
+ template <typename Subject>
+ struct plus
+ : base_plus<Subject, mpl::false_, plus<Subject> >
+ {
+ typedef base_plus<Subject, mpl::false_, plus> base_plus;
+
+ plus(Subject const& subject)
+ : base_plus(subject)
+ {}
+ };
+
+ template <typename Subject>
+ struct strict_plus
+ : base_plus<Subject, mpl::true_, strict_plus<Subject> >
+ {
+ typedef base_plus<Subject, mpl::true_, strict_plus> base_plus;
+
+ strict_plus(Subject const& subject)
+ : base_plus(subject)
+ {}
+ };
 
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ template <typename Elements, bool strict_mode = false>
+ struct make_plus
+ : make_unary_composite<Elements, plus>
+ {};
+
+ template <typename Elements>
+ struct make_plus<Elements, true>
+ : make_unary_composite<Elements, strict_plus>
+ {};
+ }
+
     template <typename Elements, typename Modifiers>
     struct make_composite<proto::tag::unary_plus, Elements, Modifiers>
- : make_unary_composite<Elements, plus>
+ : detail::make_plus<Elements, detail::get_stricttag<Modifiers>::value>
     {};
-
 }}}
 
 namespace boost { namespace spirit { namespace traits
@@ -140,6 +175,9 @@
     struct has_semantic_action<karma::plus<Subject> >
       : unary_has_semantic_action<Subject> {};
 
+ template <typename Subject>
+ struct has_semantic_action<karma::strict_plus<Subject> >
+ : unary_has_semantic_action<Subject> {};
 }}}
 
 #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 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
 #include <boost/spirit/home/karma/meta_compiler.hpp>
 #include <boost/spirit/home/karma/detail/fail_function.hpp>
 #include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/detail/what_function.hpp>
 #include <boost/spirit/home/karma/detail/attributes.hpp>
@@ -44,7 +45,6 @@
     template <>
     struct flatten_tree<karma::domain, proto::tag::shift_left> // flattens <<
       : mpl::true_ {};
-
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -84,12 +84,36 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
- template <typename Elements>
- struct sequence : nary_generator<sequence<Elements> >
+ namespace detail
+ {
+ template <typename T>
+ struct attribute_size
+ : fusion::result_of::size<T>
+ {};
+
+ template <>
+ struct attribute_size<unused_type>
+ : mpl::int_<0>
+ {};
+
+ template <typename Attribute>
+ inline int attr_size(Attribute const& attr)
+ {
+ return fusion::size(attr);
+ }
+
+ inline int attr_size(unused_type)
+ {
+ return 0;
+ }
+ }
+
+ template <typename Elements, typename Strict, typename Derived>
+ struct base_sequence : nary_generator<Derived>
     {
         typedef typename traits::sequence_properties<Elements>::type properties;
 
- sequence(Elements const& elements)
+ base_sequence(Elements const& elements)
           : elements(elements) {}
 
         typedef Elements elements_type;
@@ -139,6 +163,14 @@
>::type
>::type attr(attr_);
 
+ // fail generating if sequences have not the same (logical) length
+ if (Strict::value &&
+ detail::attribute_size<attr_type_>::value !=
+ detail::attr_size(attr_))
+ {
+ return false;
+ }
+
             // return false if *any* of the generators fail
             return !spirit::any_if(elements, attr, fail_function(sink, ctx, d)
               , predicate());
@@ -192,15 +224,47 @@
         Elements elements;
     };
 
+ template <typename Elements>
+ struct sequence
+ : base_sequence<Elements, mpl::false_, sequence<Elements> >
+ {
+ typedef base_sequence<Elements, mpl::false_, sequence> base_sequence_;
+
+ sequence(Elements const& subject)
+ : base_sequence_(subject) {}
+ };
+
+ template <typename Elements>
+ struct strict_sequence
+ : base_sequence<Elements, mpl::true_, strict_sequence<Elements> >
+ {
+ typedef base_sequence<Elements, mpl::true_, strict_sequence>
+ base_sequence_;
+
+ strict_sequence(Elements const& subject)
+ : base_sequence_(subject) {}
+ };
 
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ template <typename Elements, bool strict_mode = false>
+ struct make_sequence
+ : make_nary_composite<Elements, sequence>
+ {};
+
+ template <typename Elements>
+ struct make_sequence<Elements, true>
+ : make_nary_composite<Elements, strict_sequence>
+ {};
+ }
+
     template <typename Elements, typename Modifiers>
     struct make_composite<proto::tag::shift_left, Elements, Modifiers>
- : make_nary_composite<Elements, sequence>
+ : detail::make_sequence<Elements, detail::get_stricttag<Modifiers>::value>
     {};
-
 }}}
 
 namespace boost { namespace spirit { namespace traits
@@ -209,6 +273,9 @@
     struct has_semantic_action<karma::sequence<Elements> >
       : nary_has_semantic_action<Elements> {};
 
+ template <typename Elements>
+ struct has_semantic_action<karma::strict_sequence<Elements> >
+ : nary_has_semantic_action<Elements> {};
 }}}
 
 #endif

Modified: trunk/boost/spirit/home/support/common_terminals.hpp
==============================================================================
--- trunk/boost/spirit/home/support/common_terminals.hpp (original)
+++ trunk/boost/spirit/home/support/common_terminals.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -79,6 +79,8 @@
         ( false_ )
         ( matches )
         ( hold )
+ ( strict )
+ ( relaxed )
     )
 
     // Here we are reusing proto::lit

Added: trunk/boost/spirit/include/karma_strict_relaxed.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/include/karma_strict_relaxed.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,18 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+#ifndef BOOST_SPIRIT_INCLUDE_KARMA_STRICT_RELAXED
+#define BOOST_SPIRIT_INCLUDE_KARMA_STRICT_RELAXED
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/karma/directive/strict_relaxed.hpp>
+
+#endif

Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp (original)
+++ trunk/libs/spirit/test/karma/kleene.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
 #include <boost/spirit/include/karma_action.hpp>
 #include <boost/spirit/include/karma_nonterminal.hpp>
 #include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
 #include <boost/fusion/include/vector.hpp>
 #include <boost/spirit/include/phoenix_core.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
@@ -104,6 +105,9 @@
 
     // failing sub-generators
     {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
         using namespace boost::assign;
 
         typedef std::pair<char, char> data;
@@ -120,21 +124,33 @@
 
         r = &char_('d') << char_;
         BOOST_TEST(test("d", *r, v2));
+ BOOST_TEST(test("d", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
 
         r = &char_('a') << char_;
         BOOST_TEST(test("a", *r, v2));
+ BOOST_TEST(test("a", relaxed[*r], v2));
+ BOOST_TEST(test("a", strict[*r], v2));
 
         r = &char_('g') << char_;
         BOOST_TEST(test("g", *r, v2));
+ BOOST_TEST(test("g", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
 
         r = !char_('d') << char_;
         BOOST_TEST(test("abcefg", *r, v2));
+ BOOST_TEST(test("abcefg", relaxed[*r], v2));
+ BOOST_TEST(test("abc", strict[*r], v2));
 
         r = !char_('a') << char_;
         BOOST_TEST(test("bcdefg", *r, v2));
+ BOOST_TEST(test("bcdefg", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
 
         r = !char_('g') << char_;
         BOOST_TEST(test("abcdef", *r, v2));
+ BOOST_TEST(test("abcdef", relaxed[*r], v2));
+ BOOST_TEST(test("abcdef", strict[*r], v2));
 
         r = &char_('A') << char_;
         BOOST_TEST(test("", *r, v2));

Modified: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/list.cpp (original)
+++ trunk/libs/spirit/test/karma/list.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -6,6 +6,8 @@
 #include <boost/config/warning_disable.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
+#include <boost/mpl/print.hpp>
+
 #include <boost/spirit/include/karma_operator.hpp>
 #include <boost/spirit/include/karma_char.hpp>
 #include <boost/spirit/include/karma_string.hpp>
@@ -83,6 +85,9 @@
 
     // failing sub-generators
     {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
         typedef std::pair<char, char> data;
         std::vector<data> v2;
         v2 += std::make_pair('a', 'a'),
@@ -97,21 +102,33 @@
 
         r = &char_('d') << char_;
         BOOST_TEST(test("d", r % ',', v2));
+ BOOST_TEST(test("d", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
 
         r = &char_('a') << char_;
         BOOST_TEST(test("a", r % ',', v2));
+ BOOST_TEST(test("a", relaxed[r % ','], v2));
+ BOOST_TEST(test("a", strict[r % ','], v2));
 
         r = &char_('g') << char_;
         BOOST_TEST(test("g", r % ',', v2));
+ BOOST_TEST(test("g", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
 
         r = !char_('d') << char_;
         BOOST_TEST(test("a,b,c,e,f,g", r % ',', v2));
+ BOOST_TEST(test("a,b,c,e,f,g", relaxed[r % ','], v2));
+ BOOST_TEST(test("a,b,c", strict[r % ','], v2));
 
         r = !char_('a') << char_;
         BOOST_TEST(test("b,c,d,e,f,g", r % ',', v2));
+ BOOST_TEST(test("b,c,d,e,f,g", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
 
         r = !char_('g') << char_;
         BOOST_TEST(test("a,b,c,d,e,f", r % ',', v2));
+ BOOST_TEST(test("a,b,c,d,e,f", relaxed[r % ','], v2));
+ BOOST_TEST(test("a,b,c,d,e,f", strict[r % ','], v2));
 
         r = &char_('A') << char_;
         BOOST_TEST(!test("", r % ',', v2));

Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp (original)
+++ trunk/libs/spirit/test/karma/plus.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
 #include <boost/spirit/include/karma_action.hpp>
 #include <boost/spirit/include/karma_nonterminal.hpp>
 #include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
 #include <boost/fusion/include/vector.hpp>
 #include <boost/spirit/include/phoenix_core.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
@@ -108,6 +109,9 @@
 
     // failing sub-generators
     {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
         using namespace boost::assign;
 
         typedef std::pair<char, char> data;
@@ -124,21 +128,33 @@
 
         r = &char_('d') << char_;
         BOOST_TEST(test("d", +r, v2));
+ BOOST_TEST(test("d", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
 
         r = &char_('a') << char_;
- BOOST_TEST(test("a",+r, v2));
+ BOOST_TEST(test("a", +r, v2));
+ BOOST_TEST(test("a", relaxed[+r], v2));
+ BOOST_TEST(test("a", strict[+r], v2));
 
         r = &char_('g') << char_;
         BOOST_TEST(test("g", +r, v2));
+ BOOST_TEST(test("g", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
 
         r = !char_('d') << char_;
         BOOST_TEST(test("abcefg", +r, v2));
+ BOOST_TEST(test("abcefg", relaxed[+r], v2));
+ BOOST_TEST(test("abc", strict[+r], v2));
 
         r = !char_('a') << char_;
         BOOST_TEST(test("bcdefg", +r, v2));
+ BOOST_TEST(test("bcdefg", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
 
         r = !char_('g') << char_;
         BOOST_TEST(test("abcdef", +r, v2));
+ BOOST_TEST(test("abcdef", +r, v2));
+ BOOST_TEST(test("abcdef", +r, v2));
 
         r = &char_('A') << char_;
         BOOST_TEST(!test("", +r, v2));

Modified: trunk/libs/spirit/test/karma/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat.cpp (original)
+++ trunk/libs/spirit/test/karma/repeat.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -17,6 +17,7 @@
 #include <boost/spirit/include/karma_action.hpp>
 #include <boost/spirit/include/karma_nonterminal.hpp>
 #include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
 #include <boost/spirit/include/karma_phoenix_attributes.hpp>
 #include <boost/spirit/include/support_argument.hpp>
 #include <boost/spirit/include/phoenix_core.hpp>
@@ -142,6 +143,9 @@
 
     // failing sub-generators
     {
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
         using namespace boost::assign;
         namespace karma = boost::spirit::karma;
 
@@ -163,22 +167,47 @@
 
         r = &char_('d') << char_;
         BOOST_TEST(test("d", repeat[r], v2));
+ BOOST_TEST(test("d", relaxed[repeat[r]], v2));
+ BOOST_TEST(test("", strict[repeat[r]], v2));
 
         r = !char_('d') << char_;
         BOOST_TEST(test("abcefg", repeat(6)[r], v2));
         BOOST_TEST(!test("", repeat(5)[r], v2));
+ BOOST_TEST(test("abcefg", relaxed[repeat(6)[r]], v2));
+ BOOST_TEST(!test("", relaxed[repeat(5)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(6)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(5)[r]], v2));
 
         r = !char_('c') << char_;
         BOOST_TEST(test("abd", repeat(3)[r], v2));
+ BOOST_TEST(test("abd", relaxed[repeat(3)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(3)[r]], v2));
 
         r = !char_('a') << char_;
         BOOST_TEST(test("bcdef", repeat(3, 5)[r], v2));
         BOOST_TEST(test("bcd", repeat(3, 5)[r], v3));
         BOOST_TEST(!test("", repeat(4, 5)[r], v3));
+ BOOST_TEST(test("bcdef", relaxed[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("bcd", relaxed[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", relaxed[repeat(4, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(3, 5)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(4, 5)[r]], v3));
 
         BOOST_TEST(test("bcd", repeat(3, inf)[r], v3));
         BOOST_TEST(test("bcdefg", repeat(3, inf)[r], v2));
         BOOST_TEST(!test("", repeat(4, inf)[r], v3));
+
+ r = !char_('g') << char_;
+ BOOST_TEST(test("abcde", repeat(3, 5)[r], v2));
+ BOOST_TEST(test("abcd", repeat(3, 5)[r], v3));
+ BOOST_TEST(!test("", repeat(4, 5)[r], v3));
+ BOOST_TEST(test("abcde", relaxed[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("abcd", relaxed[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", relaxed[repeat(4, 5)[r]], v3));
+ BOOST_TEST(test("abcde", strict[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("abcd", strict[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(5)[r]], v3));
     }
 
     {

Modified: trunk/libs/spirit/test/karma/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/sequence.cpp (original)
+++ trunk/libs/spirit/test/karma/sequence.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -17,6 +17,7 @@
 #include <boost/spirit/include/karma_action.hpp>
 #include <boost/spirit/include/karma_nonterminal.hpp>
 #include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
 #include <boost/spirit/include/support_unused.hpp>
 #include <boost/spirit/include/phoenix_core.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
@@ -98,6 +99,39 @@
         }
 
         {
+ // element sequence can be shorter and longer than the attribute
+ // sequence
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
+ fusion::vector<char, int, char> p ('a', 12, 'c');
+ BOOST_TEST(test("a12", char_ << int_, p));
+ BOOST_TEST(test_delimited("a 12 ", char_ << int_, p, char(' ')));
+
+ BOOST_TEST(test("a12", relaxed[char_ << int_], p));
+ BOOST_TEST(test_delimited("a 12 ", relaxed[char_ << int_], p, char(' ')));
+
+ BOOST_TEST(!test("", strict[char_ << int_], p));
+ BOOST_TEST(!test_delimited("", strict[char_ << int_], p, char(' ')));
+
+ fusion::vector<char, int> p1 ('a', 12);
+ BOOST_TEST(test("a12c", char_ << int_ << char_('c'), p1));
+ BOOST_TEST(test_delimited("a 12 c ", char_ << int_ << char_('c'),
+ p1, char(' ')));
+
+ BOOST_TEST(test("a12c", relaxed[char_ << int_ << char_('c')], p1));
+ BOOST_TEST(test_delimited("a 12 c ",
+ relaxed[char_ << int_ << char_('c')], p1, char(' ')));
+
+ BOOST_TEST(!test("", strict[char_ << int_ << char_('c')], p1));
+ BOOST_TEST(!test_delimited("", strict[char_ << int_ << char_('c')],
+ p1, char(' ')));
+
+ BOOST_TEST(test("a12", strict[char_ << int_], p1));
+ BOOST_TEST(test_delimited("a 12 ", strict[char_ << int_], p1, char(' ')));
+ }
+
+ {
             // if all elements of a sequence have unused parameters, the whole
             // sequence has an unused parameter as well
             fusion::vector<char, char> p ('a', 'e');


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