$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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');