$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61475 - in trunk: boost/spirit/home/karma boost/spirit/home/karma/detail boost/spirit/home/karma/nonterminal boost/spirit/home/qi/detail boost/spirit/home/qi/nonterminal boost/spirit/home/support libs/spirit/test libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-21 19:35:51
Author: hkaiser
Date: 2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
New Revision: 61475
URL: http://svn.boost.org/trac/boost/changeset/61475
Log:
Spirit: fixed gcc compilation problems, added karma debug support, fixed Qi debug indentation
Added:
   trunk/boost/spirit/home/karma/nonterminal/debug_handler.hpp   (contents, props changed)
   trunk/boost/spirit/home/karma/nonterminal/simple_trace.hpp   (contents, props changed)
   trunk/libs/spirit/test/karma/debug.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp |    28 +++++++++++++++++-----------            
   trunk/boost/spirit/home/karma/detail/pass_container.hpp  |    10 +++++++++-                              
   trunk/boost/spirit/home/karma/nonterminal.hpp            |     2 ++                                      
   trunk/boost/spirit/home/qi/detail/attributes.hpp         |    14 ++++++++++++++                          
   trunk/boost/spirit/home/qi/nonterminal/debug_handler.hpp |    11 +++++++----                             
   trunk/boost/spirit/home/qi/nonterminal/simple_trace.hpp  |    27 ++++++++++++++++-----------             
   trunk/boost/spirit/home/support/attributes.hpp           |    14 --------------                          
   trunk/libs/spirit/test/Jamfile                           |     1 +                                       
   8 files changed, 66 insertions(+), 41 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -170,7 +170,6 @@
     //  The following classes are used to intercept the output into a buffer
     //  allowing to do things like alignment, character escaping etc.
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator>
     class buffer_sink : boost::noncopyable
     {
     public:
@@ -202,7 +201,8 @@
             buffer.push_back(value);
         }
 
-        bool copy(OutputIterator& sink, std::size_t maxwidth) const 
+        template <typename OutputIterator_>
+        bool copy(OutputIterator_& sink, std::size_t maxwidth) const 
         { 
 #if defined(BOOST_MSVC)
 #pragma warning(push)
@@ -245,7 +245,6 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator>
     struct buffering_policy
     {
     public:
@@ -253,10 +252,9 @@
         buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
 
         // functions related to buffering
-        buffer_sink<OutputIterator>* chain_buffering(
-            buffer_sink<OutputIterator>* buffer_data)
+        buffer_sink* chain_buffering(buffer_sink* buffer_data)
         {
-            buffer_sink<OutputIterator>* prev_buffer = buffer;
+            buffer_sink* prev_buffer = buffer;
             buffer = buffer_data;
             return prev_buffer;
         }
@@ -275,7 +273,7 @@
         bool has_buffer() const { return NULL != buffer; }
 
     private:
-        buffer_sink<OutputIterator>* buffer;
+        buffer_sink* buffer;
     };
 
     struct no_buffering_policy
@@ -369,7 +367,7 @@
 
         typedef typename mpl::if_c<
             (properties & generator_properties::buffering) ? true : false
-          , buffering_policy<most_derived_type>, no_buffering_policy
+          , buffering_policy, no_buffering_policy
         >::type buffering_type;
 
         typedef typename mpl::if_c<
@@ -559,15 +557,23 @@
 
         // copy to the remaining characters to the specified sink
         template <typename RestIterator>
-        bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0)
+        bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0) const
         {
             return buffer_data.copy_rest(sink, start_at);
         }
 
+        // copy the contents to the given output iterator
+        template <typename OutputIterator_>
+        bool buffer_copy_to(OutputIterator_& sink
+          , std::size_t maxwidth = std::size_t(-1)) const
+        {
+            return buffer_data.copy(sink, maxwidth);
+        }
+
     private:
         OutputIterator& sink;
-        buffer_sink<OutputIterator> buffer_data;    // for buffering
-        buffer_sink<OutputIterator>* prev_buffer;   // previous buffer in chain
+        buffer_sink buffer_data;    // for buffering
+        buffer_sink* prev_buffer;   // previous buffer in chain
         bool enabled;
     };
 
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -70,6 +70,14 @@
           , boost::forward_traversal_tag
           , typename boost::detail::iterator_traits<Iterator>::value_type const&>
     {
+        typedef typename boost::detail::iterator_traits<Iterator>::value_type
+            base_value_type;
+
+        typedef boost::iterator_facade<
+            indirect_iterator<Iterator>, base_value_type
+          , boost::forward_traversal_tag, base_value_type const&
+        > base_type;
+
     public:
         indirect_iterator()
           : iter_(0) 
@@ -94,7 +102,7 @@
             return other.iter_ != 0 && *iter_ == *other.iter_;
         }
 
-        reference dereference() const
+        typename base_type::reference dereference() const
         {
             return **iter_;
         }
Modified: trunk/boost/spirit/home/karma/nonterminal.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -12,5 +12,7 @@
 
 #include <boost/spirit/home/karma/nonterminal/rule.hpp>
 #include <boost/spirit/home/karma/nonterminal/grammar.hpp>
+#include <boost/spirit/home/karma/nonterminal/debug_handler.hpp>
+#include <boost/spirit/home/karma/nonterminal/simple_trace.hpp>
 
 #endif
Added: trunk/boost/spirit/home/karma/nonterminal/debug_handler.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/nonterminal/debug_handler.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -0,0 +1,124 @@
+//  Copyright (c) 2001-2010 Hartmut Kaiser
+//  Copyright (c) 2001-2010 Joel de Guzman
+// 
+//  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_DEBUG_HANDLER_APR_21_2010_0148PM)
+#define BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/karma/nonterminal/rule.hpp>
+#include <boost/function.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/out.hpp>
+#include <iostream>
+
+namespace boost { namespace spirit { namespace karma
+{
+    enum debug_handler_state
+    {
+        pre_generate
+      , successful_generate
+      , failed_generate
+    };
+
+    template <
+        typename OutputIterator, typename Context, typename Delimiter
+      , typename Properties, typename F>
+    struct debug_handler
+    {
+        typedef detail::output_iterator<OutputIterator, Properties> 
+            output_iterator;
+        typedef detail::enable_buffering<output_iterator> buffer_type;
+
+        typedef function<bool(output_iterator&, Context&, Delimiter const&)>
+            function_type;
+
+        debug_handler(function_type subject, F f, std::string const& rule_name)
+          : subject(subject)
+          , f(f)
+          , rule_name(rule_name)
+        {}
+
+        bool operator()(output_iterator& sink, Context& context
+          , Delimiter const& delim) const
+        {
+            buffer_type buffer(sink);
+            bool r = false;
+
+            f (sink, context, pre_generate, rule_name, buffer);
+            {
+                detail::disable_counting<output_iterator> nocount(sink);
+                r = subject(sink, context, delim);
+            }
+
+            if (r) 
+            {
+                f (sink, context, successful_generate, rule_name, buffer);
+                buffer.buffer_copy();
+                return true;
+            }
+            f (sink, context, failed_generate, rule_name, buffer);
+            return false;
+        }
+
+        function_type subject;
+        F f;
+        std::string rule_name;
+    };
+
+    template <
+        typename OutputIterator, typename T0, typename T1, typename T2
+      , typename F>
+    void debug(rule<OutputIterator, T0, T1, T2>& r, F f)
+    {
+        typedef rule<OutputIterator, T0, T1, T2> rule_type;
+
+        typedef
+            debug_handler<
+                OutputIterator
+              , typename rule_type::context_type
+              , typename rule_type::delimiter_type
+              , typename rule_type::properties
+              , F>
+        debug_handler;
+        r.f = debug_handler(r.f, f, r.name());
+    }
+
+    struct simple_trace;
+
+    template <typename OutputIterator, typename T0, typename T1, typename T2>
+    void debug(rule<OutputIterator, T0, T1, T2>& r)
+    {
+        typedef rule<OutputIterator, T0, T1, T2> rule_type;
+
+        typedef
+            debug_handler<
+                OutputIterator
+              , typename rule_type::context_type
+              , typename rule_type::delimiter_type
+              , typename rule_type::properties
+              , simple_trace>
+        debug_handler;
+        r.f = debug_handler(r.f, simple_trace(), r.name());
+    }
+
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Utility macro for easy enabling of rule and grammar debugging
+#if !defined(BOOST_SPIRIT_DEBUG_NODE)
+  #if defined(BOOST_SPIRIT_KARMA_DEBUG)
+    #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r); debug(r)
+  #else
+    #define BOOST_SPIRIT_DEBUG_NODE(r)
+  #endif
+#endif
+
+#endif
Added: trunk/boost/spirit/home/karma/nonterminal/simple_trace.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/nonterminal/simple_trace.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -0,0 +1,133 @@
+//  Copyright (c) 2001-2010 Hartmut Kaiser
+//  Copyright (c) 2001-2010 Joel de Guzman
+// 
+//  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_SIMPLE_TRACE_APR_21_2010_0155PM)
+#define BOOST_SPIRIT_KARMA_SIMPLE_TRACE_APR_21_2010_0155PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/out.hpp>
+#include <iostream>
+
+//  The stream to use for debug output
+#if !defined(BOOST_SPIRIT_DEBUG_OUT)
+#define BOOST_SPIRIT_DEBUG_OUT std::cerr
+#endif
+
+//  number of tokens to print while debugging
+#if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
+#define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
+#endif
+
+//  number of spaces to indent
+#if !defined(BOOST_SPIRIT_DEBUG_INDENT)
+#define BOOST_SPIRIT_DEBUG_INDENT 2
+#endif
+
+namespace boost { namespace spirit { namespace karma
+{
+    struct simple_trace
+    {
+        int& get_indent() const
+        {
+            static int indent = 0;
+            return indent;
+        }
+
+        void print_indent() const
+        {
+            int n = get_indent();
+            n *= BOOST_SPIRIT_DEBUG_INDENT;
+            for (int i = 0; i != n; ++i)
+                BOOST_SPIRIT_DEBUG_OUT << ' ';
+        }
+
+        template <typename Buffer>
+        void print_some(char const* tag, Buffer const& buffer) const
+        {
+            print_indent();
+            BOOST_SPIRIT_DEBUG_OUT << '<' << tag << '>' << std::flush;
+            {
+                std::ostreambuf_iterator<char> out(BOOST_SPIRIT_DEBUG_OUT);
+                buffer.buffer_copy_to(out, BOOST_SPIRIT_DEBUG_PRINT_SOME);
+            }
+            BOOST_SPIRIT_DEBUG_OUT << "</" << tag << '>' << std::endl;
+        }
+
+        template <typename OutputIterator, typename Context, typename State
+          , typename Buffer>
+        void operator()(
+            OutputIterator& sink, Context const& context
+          , State state, std::string const& rule_name
+          , Buffer const& buffer) const
+        {
+            switch (state)
+            {
+                case pre_generate:
+                    print_indent();
+                    ++get_indent();
+                    BOOST_SPIRIT_DEBUG_OUT
+                        << '<' << rule_name << '>' << std::endl;
+                    print_indent();
+                    ++get_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "<try>" << std::endl;;
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "<attributes>";
+                    traits::print_attribute(
+                        BOOST_SPIRIT_DEBUG_OUT,
+                        context.attributes
+                    );
+                    BOOST_SPIRIT_DEBUG_OUT << "</attributes>" << std::endl;
+                    if (!fusion::empty(context.locals))
+                    {
+                        print_indent();
+                        BOOST_SPIRIT_DEBUG_OUT
+                            << "<locals>" << context.locals << "</locals>"
+                            << std::endl;
+                    }
+                    --get_indent();
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "</try>" << std::endl;;
+                    break;
+
+                case successful_generate:
+                    print_indent();
+                    ++get_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "<success>" << std::endl;
+                    print_some("result", buffer);
+                    if (!fusion::empty(context.locals))
+                    {
+                        print_indent();
+                        BOOST_SPIRIT_DEBUG_OUT
+                            << "<locals>" << context.locals << "</locals>"
+                            << std::endl;
+                    }
+                    --get_indent();
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "</success>" << std::endl;
+                    --get_indent();
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT 
+                        << "</" << rule_name << '>' << std::endl;
+                    break;
+
+                case failed_generate:
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT << "<fail/>" << std::endl;
+                    --get_indent();
+                    print_indent();
+                    BOOST_SPIRIT_DEBUG_OUT 
+                        << "</" << rule_name << '>' << std::endl;
+                    break;
+            }
+        }
+    };
+}}}
+
+#endif
Modified: trunk/boost/spirit/home/qi/detail/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/attributes.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/attributes.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -156,6 +156,20 @@
     struct transform_attribute<Attribute&, Attribute, qi::domain>
       : qi::transform_attribute<Attribute&, Attribute>
     {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Exposed, typename Transformed>
+    void post_transform(Exposed& dest, Transformed const& attr)
+    {
+        return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Exposed, typename Transformed>
+    void fail_transform(Exposed& dest, Transformed const&)
+    {
+        return transform_attribute<Exposed, Transformed, qi::domain>::fail(dest);
+    }
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/qi/nonterminal/debug_handler.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/debug_handler.hpp	(original)
+++ trunk/boost/spirit/home/qi/nonterminal/debug_handler.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -14,6 +14,7 @@
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/qi/nonterminal/rule.hpp>
 #include <boost/spirit/home/qi/operator/expect.hpp>
+#include <boost/spirit/home/qi/nonterminal/simple_trace.hpp>
 #include <boost/function.hpp>
 #include <boost/fusion/include/at.hpp>
 #include <boost/fusion/include/vector.hpp>
@@ -116,10 +117,12 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 //  Utility macro for easy enabling of rule and grammar debugging
-#if defined(BOOST_SPIRIT_DEBUG)
-#define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r); debug(r)
-#else
-#define BOOST_SPIRIT_DEBUG_NODE(r)
+#if !defined(BOOST_SPIRIT_DEBUG_NODE)
+  #if defined(BOOST_SPIRIT_DEBUG) || defined(BOOST_SPIRIT_QI_DEBUG)
+    #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r); debug(r)
+  #else
+    #define BOOST_SPIRIT_DEBUG_NODE(r)
+  #endif
 #endif
 
 #endif
Modified: trunk/boost/spirit/home/qi/nonterminal/simple_trace.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/simple_trace.hpp	(original)
+++ trunk/boost/spirit/home/qi/nonterminal/simple_trace.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2001-2010 Joel de Guzman
+    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)
@@ -20,7 +21,7 @@
 #define BOOST_SPIRIT_DEBUG_OUT std::cerr
 #endif
 
-//  number of input tokens to print while debugging
+//  number of tokens to print while debugging
 #if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
 #define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
 #endif
@@ -95,6 +96,12 @@
 
     struct simple_trace
     {
+        int& get_indent() const
+        {
+            static int indent = 0;
+            return indent;
+        }
+
         void print_indent(int n) const
         {
             n *= BOOST_SPIRIT_DEBUG_INDENT;
@@ -108,7 +115,7 @@
           , int indent
           , Iterator first, Iterator const& last) const
         {
-            print_indent(indent);
+            print_indent(get_indent());
             BOOST_SPIRIT_DEBUG_OUT << '<' << tag << '>';
             int const n = BOOST_SPIRIT_DEBUG_PRINT_SOME;
             for (int i = 0; first != last && i != n && *first; ++i, ++first)
@@ -127,20 +134,18 @@
           , State state
           , std::string const& rule_name) const
         {
-            int static indent = 0;
-
             switch (state)
             {
                 case pre_parse:
-                    print_indent(indent++);
+                    print_indent(get_indent()++);
                     BOOST_SPIRIT_DEBUG_OUT
                         << '<' << rule_name << '>'
                         << std::endl;
-                    print_some("try", indent, first, last);
+                    print_some("try", get_indent(), first, last);
                     break;
                 case successful_parse:
-                    print_some("success", indent, first, last);
-                    print_indent(indent);
+                    print_some("success", get_indent(), first, last);
+                    print_indent(get_indent());
                     BOOST_SPIRIT_DEBUG_OUT
                         << "<attributes>";
                     traits::print_attribute(
@@ -155,15 +160,15 @@
                             << context.locals
                             << "</locals>";
                     BOOST_SPIRIT_DEBUG_OUT << std::endl;
-                    print_indent(--indent);
+                    print_indent(--get_indent());
                     BOOST_SPIRIT_DEBUG_OUT
                         << "</" << rule_name << '>'
                         << std::endl;
                     break;
                 case failed_parse:
-                    print_indent(indent);
+                    print_indent(get_indent());
                     BOOST_SPIRIT_DEBUG_OUT << "<fail/>" << std::endl;
-                    print_indent(--indent);
+                    print_indent(--get_indent());
                     BOOST_SPIRIT_DEBUG_OUT
                         << "</" << rule_name << '>'
                         << std::endl;
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes.hpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -539,20 +539,6 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename Exposed, typename Transformed>
-    void post_transform(Exposed& dest, Transformed const& attr)
-    {
-        return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    template <typename Exposed, typename Transformed>
-    void fail_transform(Exposed& dest, Transformed const&)
-    {
-        return transform_attribute<Exposed, Transformed, qi::domain>::fail(dest);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
     // make_attribute
     //
     // All parsers and generators have specific attribute types.
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile	(original)
+++ trunk/libs/spirit/test/Jamfile	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -87,6 +87,7 @@
     [ run karma/char.cpp                    : : : : karma_char ]
     [ run karma/char_class.cpp              : : : : karma_char_class ]
     [ run karma/columns.cpp                 : : : : ]
+    [ run karma/debug.cpp                   : : : : karma_debug ]
     [ run karma/delimiter.cpp               : : : : ]
     [ run karma/encoding.cpp                : : : : karma_encoding ]
     [ run karma/eol.cpp                     : : : : karma_eol ]
Added: trunk/libs/spirit/test/karma/debug.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/debug.cpp	2010-04-21 19:35:50 EDT (Wed, 21 Apr 2010)
@@ -0,0 +1,112 @@
+//  Copyright (c) 2001-2010 Hartmut Kaiser
+//  Copyright (c) 2001-2010 Joel de Guzman
+// 
+//  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)
+
+#define BOOST_SPIRIT_KARMA_DEBUG
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <string>
+#include <cstring>
+#include <iostream>
+#include "test.hpp"
+
+int main()
+{
+    using spirit_test::test;
+    using spirit_test::test_delimited;
+
+    using namespace boost::spirit::ascii;
+    using namespace boost::spirit::karma::labels;
+    using boost::spirit::karma::locals;
+    using boost::spirit::karma::rule;
+    using boost::spirit::karma::char_;
+    using boost::spirit::karma::debug;
+    using boost::spirit::karma::space;
+    using boost::spirit::karma::eps;
+
+    namespace phx = boost::phoenix;
+
+    typedef spirit_test::output_iterator<char>::type outiter_type;
+
+    { // basic tests
+        rule<outiter_type, char()> a, b, c;
+        rule<outiter_type, std::vector<char>()> start;
+
+        std::vector<char> v;
+        v.push_back('a');
+        v.push_back('b');
+        v.push_back('a');
+        v.push_back('c');
+        v.push_back('a');
+        v.push_back('b');
+        v.push_back('b');
+        v.push_back('a');
+
+        a = char_('a');
+        b = char_('b');
+        c = char_('c');
+        BOOST_SPIRIT_DEBUG_NODE(a);
+        BOOST_SPIRIT_DEBUG_NODE(b);
+        BOOST_SPIRIT_DEBUG_NODE(c);
+
+        start = *(a | b | c);
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("abacabba", start, v));
+
+        // ignore the delimiter
+        BOOST_TEST(test_delimited("abacabba ", start, v, space));
+
+        std::vector<char> v1;
+        v1.push_back('b');
+        v1.push_back('c');
+
+        start = (a | b) << c;
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("bc", start, v1));
+    }
+
+    { // tests with locals
+        rule<outiter_type, char()> a, b, c;
+        rule<outiter_type, std::vector<char>(), locals<int, double> > start;
+
+        std::vector<char> v;
+        v.push_back('a');
+        v.push_back('b');
+        v.push_back('a');
+        v.push_back('c');
+        v.push_back('a');
+        v.push_back('b');
+        v.push_back('b');
+        v.push_back('a');
+
+        a = char_('a');
+        b = char_('b');
+        c = char_('c');
+        BOOST_SPIRIT_DEBUG_NODE(a);
+        BOOST_SPIRIT_DEBUG_NODE(b);
+        BOOST_SPIRIT_DEBUG_NODE(c);
+
+        start %= eps[_a = 0, _b = 2.0] << *(a[++_a] | b | c);
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("abacabba", start, v));
+    }
+
+    return boost::report_errors();
+}
+