$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: hartmut.kaiser_at_[hidden]
Date: 2008-04-29 20:59:09
Author: hkaiser
Date: 2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
New Revision: 44901
URL: http://svn.boost.org/trac/boost/changeset/44901
Log:
Spirit.Karma: Fixed rule, added calc2_ast_dump example
Added:
   trunk/libs/spirit/example/karma/calc2_ast_dump.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/karma/char/char.hpp                             |     4                                         
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp                |     5                                         
   trunk/boost/spirit/home/karma/nonterminal/detail/rule.hpp               |   147 ++++-----------------------             
   trunk/boost/spirit/home/karma/nonterminal/nonterminal.hpp               |    34 ++----                                  
   trunk/boost/spirit/home/karma/nonterminal/nonterminal_director.hpp      |    70 ++++++-------                           
   trunk/boost/spirit/home/karma/nonterminal/rule.hpp                      |    24 ++-                                     
   trunk/boost/spirit/home/karma/operator/alternative.hpp                  |    32 ++----                                  
   trunk/boost/spirit/home/karma/operator/detail/alternative.hpp           |   204 +++++++++++++++++++++++++-------------  
   trunk/boost/spirit/home/karma/operator/karma-alt/alternative.hpp        |    34 ++----                                  
   trunk/boost/spirit/home/karma/operator/karma-alt/detail/alternative.hpp |   207 ++++++++++++++++++++++++++------------- 
   trunk/boost/spirit/home/support/argument.hpp                            |     2                                         
   11 files changed, 382 insertions(+), 381 deletions(-)
Modified: trunk/boost/spirit/home/karma/char/char.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/char/char.hpp	(original)
+++ trunk/boost/spirit/home/karma/char/char.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -111,7 +111,7 @@
                 + '\'';
         }
     };
-                
+
     ///////////////////////////////////////////////////////////////////////////
     //
     //  lazy_char 
@@ -146,7 +146,7 @@
             return "char";
         }
     };
-                
+
     ///////////////////////////////////////////////////////////////////////////
     //
     //  lower and upper case variants of any_char with an associated parameter
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	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -14,6 +14,7 @@
 #include <vector>
 #include <algorithm>
 
+#include <boost/noncopyable.hpp>
 #include <boost/spirit/home/karma/detail/ostream_iterator.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail 
@@ -83,7 +84,7 @@
     
     ///////////////////////////////////////////////////////////////////////////
     template <typename OutputIterator>
-    class buffer_sink 
+    class buffer_sink : boost::noncopyable
     {
     public:
         buffer_sink()
@@ -144,7 +145,7 @@
     //  on demand, such as counting, buffering, and position tracking.
     ///////////////////////////////////////////////////////////////////////////
     template <typename OutputIterator, typename Enable = void>
-    class output_iterator
+    class output_iterator : boost::noncopyable
     {
     private:
         enum output_mode 
Modified: trunk/boost/spirit/home/karma/nonterminal/detail/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/detail/rule.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/detail/rule.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -33,6 +33,16 @@
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
+    struct no_delimiter
+    {
+        // this struct accepts only unused types and
+        // nothing else. This is used by the second
+        // pure virtual parse member function of
+        // virtual_component_base below.
+
+        no_delimiter(unused_type) {}
+    };
+
     template <typename OutputIterator, typename Context, typename Delimiter>
     struct virtual_component_base
     {
@@ -60,7 +70,7 @@
             delimiter_type const& delim) = 0;
 
         virtual bool
-        generate(OutputIterator& sink, Context& context, unused_type) = 0;
+        generate(OutputIterator& sink, Context& context, no_delimiter) = 0;
 
         boost::detail::atomic_count use_count;
     };
@@ -83,119 +93,6 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename Component, typename Context>
-    struct needs_single_attribute
-    :   mpl::not_<
-            typename fusion::traits::is_sequence<
-                typename traits::attribute_of<
-                    karma::domain, Component, Context>::type
-            >::type
-        >
-    {
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    template <typename MustDeref, typename Parameter>
-    struct deref_if
-    {
-        typedef typename
-            mpl::eval_if<
-                MustDeref,
-                fusion::result_of::at_c<Parameter, 1>,
-                fusion::result_of::pop_front<Parameter>
-            >::type
-        type;
-
-        template <typename Param>
-        static type
-        call(Param const& param, mpl::true_)
-        {
-            return fusion::at_c<1>(param);
-        }
-
-        template <typename Param>
-        static type
-        call(Param const& param, mpl::false_)
-        {
-            return fusion::pop_front(param);
-        }
-
-        template <typename Param>
-        static type
-        call(Param const& param)
-        {
-            return call(param, MustDeref());
-        }
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    template <typename Component, typename Context>
-    struct propagate_param
-    {
-        // If first element of the context (that's the parameter type) contains
-        // one element only, then the parameter type to propagate is unused,
-        // otherwise we consider to use everything except the first element of
-        // this sequence.
-        //
-        // If the resulting sequence type is a fusion sequence containing
-        // exactly one element and the right hand side expects a singular
-        // (non-sequence) parameter we pass on the first (and only) element of
-        // this sequence, otherwise we pass the parameter sequence itself.
-        typedef typename
-            boost::add_const<
-                typename boost::remove_reference<
-                    typename fusion::result_of::at_c<Context, 0>::type
-                >::type
-            >::type
-        parameter_type;
-
-        // this evaluates to mpl::true_ if the rules parameter type is unused
-        typedef typename
-            mpl::equal_to<mpl::size<parameter_type>, mpl::long_<1> >::type
-        no_parameter;
-
-        // this evaluates to mpl::true_ if the rules parameter type contains
-        // one element and the right hand side generator expects a single
-        // (non-sequence) parameter type
-        typedef typename
-            mpl::and_<
-                mpl::equal_to<mpl::size<parameter_type>, mpl::long_<2> >,
-                needs_single_attribute<Component, Context>
-            >::type
-        must_dereference;
-
-        typedef typename
-            mpl::eval_if<
-                no_parameter,
-                mpl::identity<unused_type const>,
-                deref_if<must_dereference, parameter_type>
-            >::type
-        propagated_type;
-
-        template <typename Ctx>
-        static unused_type const
-        call(Ctx& context, mpl::true_)
-        {
-            return unused;
-        }
-
-        template <typename Ctx>
-        static propagated_type
-        call(Ctx& context, mpl::false_)
-        {
-            return deref_if<must_dereference, parameter_type>::
-                call(fusion::at_c<0>(context));
-        }
-
-        template <typename Ctx>
-        static propagated_type
-        call(Ctx& context)
-        {
-            return call(context, no_parameter());
-        }
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
     template <typename OutputIterator, typename Component, typename Context,
         typename Delimiter, typename Auto>
     struct virtual_component
@@ -220,33 +117,37 @@
         bool generate_main(OutputIterator& sink, Context& context,
             Delimiter_ const& delim, mpl::false_)
         {
-            // If Auto is false, the component's parameter is unused.
+            // If Auto is false, we synthesize a new (default constructed) 
+            // attribute instance based on the attributes of the embedded 
+            // generator.
+            typename traits::attribute_of<
+                    karma::domain, Component, Context
+                >::type param;
+                
             typedef typename Component::director director;
-            return director::generate(component, sink, context, delim, unused);
+            return director::generate(component, sink, context, delim, param);
         }
 
         template <typename Delimiter_>
         bool generate_main(OutputIterator& sink, Context& context,
             Delimiter_ const& delim, mpl::true_)
         {
-            //  If Auto is true, we pass the rule's parameters on to the
+            //  If Auto is true, we pass the rule's attribute on to the
             //  component.
             typedef typename Component::director director;
             return director::generate(component, sink, context, delim,
-                detail::propagate_param<Component, Context>::call(context));
+                fusion::at_c<0>(fusion::at_c<0>(context)));
         }
 
         bool
-        generate_main(OutputIterator& /*sink*/, Context& /*context*/, take_no_delimiter,
-            mpl::false_)
+        generate_main(OutputIterator&, Context&, take_no_delimiter, mpl::false_)
         {
             BOOST_ASSERT(false); // this should never be called
             return false;
         }
 
         bool
-        generate_main(OutputIterator& /*sink*/, Context& /*context*/, take_no_delimiter,
-            mpl::true_)
+        generate_main(OutputIterator&, Context&, take_no_delimiter, mpl::true_)
         {
             BOOST_ASSERT(false); // this should never be called
             return false;
@@ -260,7 +161,7 @@
         }
 
         virtual bool
-        generate(OutputIterator& sink, Context& context, unused_type)
+        generate(OutputIterator& sink, Context& context, no_delimiter)
         {
             return generate_main(sink, context, unused, Auto());
         }
Modified: trunk/boost/spirit/home/karma/nonterminal/nonterminal.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/nonterminal.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/nonterminal.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -59,25 +59,24 @@
             mpl::if_<
                 is_same<result_type_, void>, unused_type, result_type_
             >::type
-        result_type;
+        attribute_type;
 
         // param_types is a sequence of types passed as parameters to the 
         // nonterminal
         typedef typename 
             function_types::parameter_types<sig_type>::type 
-        param_types_;
-
-        // if no parameters have been specified, we generate a single 
-        // unused_type parameter, which is needed to allow grammar parameter
-        // propagation to function correctly 
-        typedef typename
-            mpl::if_<
-                is_same<typename mpl::size<param_types_>::type, mpl::long_<0> >,
-                fusion::single_view<unused_type>, 
-                param_types_
-            >::type
         param_types;
 
+        // the parameter tuple has the attribute value pre-pended
+        typedef typename 
+            fusion::result_of::as_vector<
+                fusion::joint_view<
+                    fusion::single_view<attribute_type const&>,
+                    param_types
+                >
+            >::type
+        retval_param_types;
+        
         // locals_type is a sequence of types to be used as local variables
         typedef typename 
             fusion::result_of::as_vector<Locals>::type 
@@ -86,16 +85,7 @@
         //  The overall context_type consist of a tuple with:
         //      1) a tuple of the return value and parameters
         //      2) the locals
-        typedef fusion::vector<
-                typename fusion::result_of::as_vector<
-                    fusion::joint_view<
-                        fusion::single_view<result_type const>,
-                        param_types
-                    >
-                >::type,
-                typename fusion::result_of::as_vector<locals_type>::type
-            >
-        context_type;
+        typedef fusion::vector<retval_param_types, locals_type> context_type;
 
         typedef nonterminal<Derived, Sig, Locals> self_type;
         typedef nonterminal_holder<Derived const*, Derived> nonterminal_holder_;
Modified: trunk/boost/spirit/home/karma/nonterminal/nonterminal_director.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/nonterminal_director.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/nonterminal_director.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -15,6 +15,7 @@
 #include <boost/spirit/home/support/nonterminal/detail/expand_arg.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
 #include <boost/spirit/home/support/component.hpp>
+#include <boost/spirit/home/support/attribute_transform.hpp>
 #include <boost/spirit/home/support/detail/values.hpp>
 #include <boost/fusion/include/transform.hpp>
 #include <boost/fusion/include/join.hpp>
@@ -28,56 +29,63 @@
 {
     struct nonterminal_director
     {
+        // The attribute (parameter) of nonterminals is the type given to them 
+        // as the return value of the function signature.
         template <typename Component, typename Context, typename Unused>
         struct attribute
         {
-            typedef typename result_of::subject<Component>::type nonterminal_holder;
-            typedef typename nonterminal_holder::nonterminal_type::param_types type;
+            typedef typename 
+                result_of::subject<Component>::type 
+            nonterminal_holder;
+            typedef typename 
+                nonterminal_holder::nonterminal_type::attribute_type 
+            type;
         };
 
+        // the nonterminal_holder holds an actual nonterminal_object
         template <
             typename NonterminalContext, typename Nonterminal,
-            typename OutputIterator, typename Context,
-            typename Delimiter, typename Parameter>
+            typename OutputIterator, typename Context, typename Delimiter, 
+            typename Parameter>
         static bool generate_nonterminal(
             nonterminal_object<Nonterminal> const& x,
-            OutputIterator& sink, Context& context_,
-            Delimiter const& delim, Parameter const& param)
+            OutputIterator& sink, Context&, Delimiter const& delim, 
+            Parameter const& param)
         {
-            // the nonterminal_holder holds an actual nonterminal_object
             typedef typename Nonterminal::locals_type locals_type;
-            NonterminalContext context(param, locals_type());
+            fusion::single_view<Parameter const&> front(param);
+            NonterminalContext context(front, locals_type());
             return x.obj.generate(sink, context, delim);
         }
 
+        // the nonterminal_holder holds a pointer to a nonterminal
         template <
             typename NonterminalContext, typename Nonterminal,
-            typename OutputIterator, typename Context,
-            typename Delimiter, typename Parameter>
+            typename OutputIterator, typename Context, typename Delimiter, 
+            typename Parameter>
         static bool generate_nonterminal(
             Nonterminal const* ptr,
-            OutputIterator& sink, Context& /*context_*/,
-            Delimiter const& delim, Parameter const& param)
+            OutputIterator& sink, Context&, Delimiter const& delim, 
+            Parameter const& param)
         {
-            // the nonterminal_holder holds a pointer to a nonterminal
             typedef typename Nonterminal::locals_type locals_type;
-            NonterminalContext context(param, locals_type());
+            fusion::single_view<Parameter const&> front(param);
+            NonterminalContext context(front, locals_type());
             return ptr->generate(sink, context, delim);
         }
 
+        // the nonterminal_holder holds a parameterized_nonterminal
         template <
             typename NonterminalContext, typename Nonterminal,
             typename FSequence, typename OutputIterator,
-            typename Context, typename Delimiter,
-            typename Parameter>
+            typename Context, typename Delimiter, typename Parameter>
         static bool generate_nonterminal(
             parameterized_nonterminal<Nonterminal, FSequence> const& x,
-            OutputIterator& sink, Context& context_,
-            Delimiter const& delim, Parameter const& /*param*/)
+            OutputIterator& sink, Context& context_, Delimiter const& delim, 
+            Parameter const& param)
         {
-            // the nonterminal_holder holds a parameterized_nonterminal
             typedef typename Nonterminal::locals_type locals_type;
-            fusion::single_view<unused_type const> front(unused);
+            fusion::single_view<Parameter const&> front(param);
             NonterminalContext context(
                 fusion::join(
                     front,
@@ -95,8 +103,7 @@
         // main entry point
         ///////////////////////////////////////////////////////////////////////
         template <
-            typename Component,
-            typename OutputIterator, typename Context,
+            typename Component, typename OutputIterator, typename Context,
             typename Delimiter, typename Parameter>
         static bool generate(
             Component const& component, OutputIterator& sink,
@@ -107,29 +114,16 @@
             nonterminal_holder;
             
             //  The overall context_type consists of a tuple with:
-            //      1) a tuple of the return value and parameters
+            //      1) a tuple of the attribute and parameters
             //      2) the locals
             //  if no signature is specified the first tuple contains
-            //  an unused_type element at position zero only.
-
+            //  the attribute at position zero only.
             typedef typename 
                 nonterminal_holder::nonterminal_type::context_type 
             context_type;
 
-            typedef typename
-                mpl::if_<
-                    is_same<typename remove_const<Parameter>::type, unused_type>,
-                    context_type,
-                    Parameter
-                >::type
-            parameter_type;
-
-            // create an parameter if one is not supplied
-            parameter_type p (spirit::detail::make_value<parameter_type>::call(param));
-
             return generate_nonterminal<context_type>(
-                subject(component).held, sink, context, delim, p
-            );
+                subject(component).held, sink, context, delim, param);
         }
 
         template <typename Nonterminal>
Modified: trunk/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/rule.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/rule.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -75,9 +75,12 @@
             is_component;
 
             // report invalid expression error as early as possible
-            BOOST_MPL_ASSERT_MSG(
-                is_component::value,
-                xpr_is_not_convertible_to_a_generator, ());
+//             BOOST_MPL_ASSERT_MSG(
+//                 is_component::value,
+//                 xpr_is_not_convertible_to_a_generator, ());
+
+            // temp workaround for mpl problem
+            BOOST_STATIC_ASSERT(is_component::value);
 
             define(xpr, mpl::false_());
             return *this;
@@ -91,9 +94,12 @@
             is_component;
 
             // report invalid expression error as early as possible
-            BOOST_MPL_ASSERT_MSG(
-                is_component::value,
-                xpr_is_not_convertible_to_a_generator, ());
+//             BOOST_MPL_ASSERT_MSG(
+//                 is_component::value,
+//                 xpr_is_not_convertible_to_a_generator, ());
+
+            // temp workaround for mpl problem
+            BOOST_STATIC_ASSERT(is_component::value);
 
             r.define(xpr, mpl::true_());
             return r;
@@ -161,9 +167,9 @@
         {
             // If the following line produces a compilation error stating the
             // 3rd parameter is not convertible to the expected type, then you
-            // probably trying to use this rule instance with a delimiter which 
-            // is not compatible with the delimiter type used while defining 
-            // the type of this rule instance.
+            // are probably trying to use this rule instance with a delimiter 
+            // which is not compatible with the delimiter type used while 
+            // defining the type of this rule instance.
             return ptr->generate(sink, context, delim);
         }
 
Modified: trunk/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/alternative.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/alternative.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -18,7 +18,13 @@
 #include <boost/spirit/home/support/algorithm/any.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/fusion/include/for_each.hpp>
+#include <boost/fusion/include/mpl.hpp>
+#include <boost/fusion/include/transform.hpp>
 #include <boost/variant.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/insert_range.hpp>
+#include <boost/mpl/transform_view.hpp>
 
 namespace boost { namespace spirit { namespace karma
 {
@@ -51,28 +57,12 @@
             Context& ctx, Delimiter const& d, Parameter const& param)
         {
             typedef detail::alternative_generate_functor<
-                Component, OutputIterator, Context, Delimiter, Parameter>
-            functor;
+                OutputIterator, Context, Delimiter, Parameter
+            > functor;
 
-            functor f(component, sink, ctx, d, param);
-            return boost::apply_visitor(f, param);
-        }
-
-        template <typename Component, typename OutputIterator,
-            typename Context, typename Delimiter>
-        static bool
-        generate(Component const& component, OutputIterator& sink,
-            Context& ctx, Delimiter const& d, unused_type)
-        {
-            typedef typename
-                fusion::result_of::value_at_c<
-                    typename Component::elements_type, 0>::type
-            child_component_type;
-
-            typedef typename child_component_type::director director;
-            return director::generate(
-                fusion::at_c<0>(component.elements),
-                sink, ctx, d, unused);
+            // f return true if *any* of the parser succeeds
+            functor f (sink, ctx, d, param);
+            return fusion::any(component.elements, f);
         }
 
         template <typename Component>
Modified: trunk/boost/spirit/home/karma/operator/detail/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/detail/alternative.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/detail/alternative.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -11,102 +11,166 @@
 #pragma once      // MS compatible compilers support #pragma once
 #endif
 
+#include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/attribute_of.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
-#include <boost/fusion/include/at.hpp>
-#include <boost/fusion/include/value_at.hpp>
-#include <boost/type_traits/is_same.hpp>
 #include <boost/utility/enable_if.hpp>
+#include <boost/mpl/find_if.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/distance.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
 #include <boost/variant.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
-    template <typename Component, typename OutputIterator,
-        typename Context, typename Delimiter, typename Parameter>
-    struct alternative_generate_functor
+    ///////////////////////////////////////////////////////////////////////////
+    //  A component is compatible to a given parameter type if the parameter
+    //  is the same as the expected type of the component
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Expected, typename Parameter>
+    struct compute_compatible_component
     {
-        typedef bool result_type; // to satisfy boost::variant visition
-
-        template <typename Attribute, typename Got>
-        struct compute_is_compatible
-        {
-            typedef typename
-                Attribute::types
-            types; // mpl sequence of types in the variant
-
-            typedef typename
-                mpl::begin<types>::type
-            begin; // iterator to the first element
+        typedef typename Parameter::types types;
+        typedef typename mpl::end<types>::type end;
+        typedef typename mpl::begin<types>::type begin;
+
+        typedef typename
+            mpl::find_if<
+                types,
+                is_same<mpl::_1, Expected>
+            >::type
+        iter;
 
-            typedef typename
-                mpl::end<types>::type
-            end; // iterator to the last element
-
-            typedef typename
-                mpl::find_if<
-                    types,
-                    is_same<mpl::_1, Got> // $$$ fix this
-                >::type
-            iter;
+        typedef typename mpl::not_<is_same<iter, end> >::type type;
+        enum { value = type::value };
+    };
 
-            typedef typename mpl::distance<begin, iter>::type index;
-            typedef typename mpl::not_<is_same<iter, end> >::type type;
-            enum { value = type::value };
-        };
-
-        template <typename Got>
-        struct compute_is_compatible<unused_type, Got> : mpl::false_ {};
-
-        template <typename Attribute, typename Component_, typename Context_>
-        struct is_compatible :
-            compute_is_compatible<
-                typename traits::attribute_of<
-                    karma::domain, Component_, Context_>::type,
-                Attribute>
+    template <typename Expected>
+    struct compute_compatible_component<Expected, unused_type>
+      : mpl::false_
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  execute a generator if the given parameter type is compatible
+    ///////////////////////////////////////////////////////////////////////////
+
+    //  this get's instantiated if the parameter type is _not_ compatible with
+    //  the generator
+    template <typename Component, typename Parameter, typename Expected,
+        typename Enable = void>
+    struct alternative_generate
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const&, OutputIterator&, Context&, Delimiter const&, 
+            Parameter const&)
         {
-        };
+            return false;
+        }
+    };
 
-        alternative_generate_functor(Component const& component_,
-            OutputIterator& sink_, Context& ctx_,
-            Delimiter const& d, Parameter const& p)
-        : component(component_), sink(sink_), ctx(ctx_), delim(d), param(p)
-        {
+    template <typename Component>
+    struct alternative_generate<Component, unused_type, unused_type>
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& delim, unused_type const&)
+        {
+            // return true if any of the generators succeed
+            typedef typename Component::director director;
+            return director::generate(component, sink, ctx, delim, unused);
         }
+    };
 
-        template <typename Attribute>
-        bool call(Attribute const& actual_attribute, mpl::true_) const
-        {
-            typedef is_compatible<Attribute, Component, Context> is_compatible;
-            typedef typename is_compatible::index index;
-            typedef typename Component::elements_type elements;
+    //  this get's instantiated if there is no parameter given for the
+    //  alternative generator
+    template <typename Component, typename Expected>
+    struct alternative_generate<Component, unused_type, Expected>
+      : alternative_generate<Component, unused_type, unused_type>
+    {};
+
+    //  this get's instantiated if the generator does not expect to receive a
+    //  parameter (the generator is self contained).
+    template <typename Component, typename Parameter>
+    struct alternative_generate<Component, Parameter, unused_type>
+      : alternative_generate<Component, unused_type, unused_type>
+    {};
+
+    //  this get's instantiated if the parameter type is compatible to the
+    //  generator
+    template <typename Component, typename Parameter, typename Expected>
+    struct alternative_generate<
+        Component, Parameter, Expected,
+        typename enable_if<
+            compute_compatible_component<Expected, Parameter>
+        >::type
+    >
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& delim, Parameter const& param)
+        {
+            typedef
+                compute_compatible_component<Expected, Parameter>
+            component_type;
 
             typedef typename
-                fusion::result_of::value_at<elements, index>::type
-            child_component_type;
+                mpl::distance<
+                    typename component_type::begin,
+                    typename component_type::iter
+                >::type
+            distance_type;
 
-            typedef typename child_component_type::director director;
-            return director::generate(
-                fusion::at<index>(component.elements),
-                sink, ctx, delim, actual_attribute);
+            // make sure, the content of the passed variant matches our
+            // expectations
+            if (param.which() != distance_type::value)
+                return false;
+
+            // returns true if any of the generators succeed
+            typedef
+                typename mpl::deref<
+                    typename component_type::iter
+                >::type
+            compatible_type;
+
+            typedef typename Component::director director;
+            return director::generate(component, sink, ctx, delim,
+                get<compatible_type>(param));
         }
+    };
 
-        template <typename Attribute>
-        bool call(Attribute const&, mpl::false_) const
+    ///////////////////////////////////////////////////////////////////////////
+    //  alternative_generate_functor: a functor supplied to spirit::any which
+    //  will be executed for every generator in a given alternative generator
+    //  expression
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename OutputIterator, typename Context, typename Delimiter,
+        typename Parameter>
+    struct alternative_generate_functor
+    {
+        alternative_generate_functor(OutputIterator& sink_, Context& ctx_,
+              Delimiter const& d, Parameter const& p)
+          : sink(sink_), ctx(ctx_), delim(d), param(p)
         {
-            return false;
         }
 
-        template <typename Attribute>
-        bool operator()(Attribute const& actual_attribute) const
+        template <typename Component>
+        bool operator()(Component const& component)
         {
-            typedef mpl::bool_<
-                is_compatible<Attribute, Component, Context>::value>
-            is_compatible;
+            typedef
+                typename traits::attribute_of<
+                    karma::domain, Component, Context>::type
+            expected;
+            typedef
+                alternative_generate<Component, Parameter, expected>
+            generate;
 
-            return call(actual_attribute, is_compatible());
+            return generate::call(component, sink, ctx, delim, param);
         }
 
-        Component const& component;
         OutputIterator& sink;
         Context& ctx;
         Delimiter const& delim;
Modified: trunk/boost/spirit/home/karma/operator/karma-alt/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/karma-alt/alternative.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/karma-alt/alternative.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -1,4 +1,4 @@
-//  Copyright (c) 2001-2007 Hartmut Kaiser
+//  Copyright (c) 2001-2008 Hartmut Kaiser
 //  Copyright (c) 2001-2007 Joel de Guzman
 //
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -18,7 +18,13 @@
 #include <boost/spirit/home/support/algorithm/any.hpp>
 #include <boost/spirit/home/support/unused.hpp>
 #include <boost/fusion/include/for_each.hpp>
+#include <boost/fusion/include/mpl.hpp>
+#include <boost/fusion/include/transform.hpp>
 #include <boost/variant.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/insert_range.hpp>
+#include <boost/mpl/transform_view.hpp>
 
 namespace boost { namespace spirit { namespace karma
 {
@@ -51,28 +57,12 @@
             Context& ctx, Delimiter const& d, Parameter const& param)
         {
             typedef detail::alternative_generate_functor<
-                Component, OutputIterator, Context, Delimiter, Parameter>
-            functor;
+                OutputIterator, Context, Delimiter, Parameter
+            > functor;
 
-            functor f(component, sink, ctx, d, param);
-            return boost::apply_visitor(f, param);
-        }
-
-        template <typename Component, typename OutputIterator,
-            typename Context, typename Delimiter>
-        static bool
-        generate(Component const& component, OutputIterator& sink,
-            Context& ctx, Delimiter const& d, unused_type)
-        {
-            typedef typename
-                fusion::result_of::value_at_c<
-                    typename Component::elements_type, 0>::type
-            child_component_type;
-
-            typedef typename child_component_type::director director;
-            return director::generate(
-                fusion::at_c<0>(component.elements),
-                sink, ctx, d, unused);
+            // f return true if *any* of the parser succeeds
+            functor f (sink, ctx, d, param);
+            return fusion::any(component.elements, f);
         }
 
         template <typename Component>
Modified: trunk/boost/spirit/home/karma/operator/karma-alt/detail/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/karma-alt/detail/alternative.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/karma-alt/detail/alternative.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -1,4 +1,4 @@
-//  Copyright (c) 2001-2007 Hartmut Kaiser
+//  Copyright (c) 2001-2008 Hartmut Kaiser
 //  Copyright (c) 2001-2007 Joel de Guzman
 //
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -11,101 +11,166 @@
 #pragma once      // MS compatible compilers support #pragma once
 #endif
 
+#include <boost/spirit/home/support/unused.hpp>
 #include <boost/spirit/home/support/attribute_of.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
-#include <boost/fusion/include/at.hpp>
-#include <boost/fusion/include/value_at.hpp>
-#include <boost/type_traits/is_same.hpp>
 #include <boost/utility/enable_if.hpp>
+#include <boost/mpl/find_if.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/distance.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/variant.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
-    template <typename Component, typename OutputIterator,
-        typename Context, typename Delimiter, typename Parameter>
-    struct alternative_generate_functor
+    ///////////////////////////////////////////////////////////////////////////
+    //  A component is compatible to a given parameter type if the parameter
+    //  is the same as the expected type of the component
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Expected, typename Parameter>
+    struct is_compatible_component
     {
-        typedef bool result_type; // to satisfy boost::variant visition
-
-        template <typename Attribute, typename Got>
-        struct compute_is_compatible
-        {
-            typedef typename
-                Attribute::types
-            types; // mpl sequence of types in the variant
-
-            typedef typename
-                mpl::begin<types>::type
-            begin; // iterator to the first element
+        typedef typename Parameter::types types;
+        typedef typename mpl::end<types>::type end;
+        typedef typename mpl::begin<types>::type begin;
+
+        typedef typename
+            mpl::find_if<
+                types,
+                is_same<mpl::_1, Expected>
+            >::type
+        iter;
 
-            typedef typename
-                mpl::end<types>::type
-            end; // iterator to the last element
-
-            typedef typename
-                mpl::find_if<
-                    types,
-                    is_same<mpl::_1, Got> // $$$ fix this
-                >::type
-            iter;
+        typedef typename mpl::not_<is_same<iter, end> >::type type;
+        enum { value = type::value };
+    };
 
-            typedef typename mpl::distance<begin, iter>::type index;
-            typedef typename mpl::not_<is_same<iter, end> >::type type;
-            enum { value = type::value };
-        };
-
-        template <typename Got>
-        struct compute_is_compatible<unused_type, Got> : mpl::false_ {};
-
-        template <typename Attribute, typename Component_, typename Context_>
-        struct is_compatible :
-            compute_is_compatible<
-                typename traits::attribute_of<
-                    karma::domain, Component_, Context_>::type,
-                Attribute>
+    template <typename Expected>
+    struct is_compatible_component<Expected, unused_type>
+      : mpl::false_
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  execute a generator if the given parameter type is compatible
+    ///////////////////////////////////////////////////////////////////////////
+
+    //  this get's instantiated if the parameter type is _not_ compatible with
+    //  the generator
+    template <typename Component, typename Parameter, typename Expected,
+        typename Enable = void>
+    struct alternative_generate
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const&, OutputIterator&, Context&, Delimiter const&, 
+            Parameter const&)
         {
-        };
+            return false;
+        }
+    };
 
-        alternative_generate_functor(Component const& component_,
-            OutputIterator& sink_, Context& ctx_,
-            Delimiter const& d, Parameter const& p)
-        : component(component_), sink(sink_), ctx(ctx_), delim(d), param(p)
-        {
+    template <typename Component>
+    struct alternative_generate<Component, unused_type, unused_type>
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& delim, unused_type const&)
+        {
+            // return true if any of the generators succeed
+            typedef typename Component::director director;
+            return director::generate(component, sink, ctx, delim, unused);
         }
+    };
 
-        template <typename Attribute>
-        bool call(Attribute const& actual_attribute, mpl::true_) const
-        {
-            typedef is_compatible<Attribute, Component, Context> is_compatible;
-            typedef typename is_compatible::index index;
-            typedef typename Component::elements_type elements;
+    //  this get's instantiated if there is no parameter given for the
+    //  alternative generator
+    template <typename Component, typename Expected>
+    struct alternative_generate<Component, unused_type, Expected>
+      : alternative_generate<Component, unused_type, unused_type>
+    {};
+
+    //  this get's instantiated if the generator does not expect to receive a
+    //  parameter (the generator is self contained).
+    template <typename Component, typename Parameter>
+    struct alternative_generate<Component, Parameter, unused_type>
+      : alternative_generate<Component, unused_type, unused_type>
+    {};
+
+    //  this get's instantiated if the parameter type is compatible to the
+    //  generator
+    template <typename Component, typename Parameter, typename Expected>
+    struct alternative_generate<
+        Component, Parameter, Expected,
+        typename enable_if<
+            is_compatible_component<Expected, Parameter>
+        >::type
+    >
+    {
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& delim, Parameter const& param)
+        {
+            typedef
+                is_compatible_component<Expected, Parameter>
+            component_type;
 
             typedef typename
-                fusion::result_of::value_at<elements, index>::type
-            child_component_type;
+                mpl::distance<
+                    typename component_type::begin,
+                    typename component_type::iter
+                >::type
+            distance_type;
 
-            typedef typename child_component_type::director director;
-            return director::generate(
-                fusion::at<index>(component.elements),
-                sink, ctx, delim, actual_attribute);
+            // make sure, the content of the passed variant matches our
+            // expectations
+            if (param.which() != distance_type::value)
+                return false;
+
+            // returns true if any of the generators succeed
+            typedef
+                typename mpl::deref<
+                    typename component_type::iter
+                >::type
+            compatible_type;
+
+            typedef typename Component::director director;
+            return director::generate(component, sink, ctx, delim,
+                get<compatible_type>(param));
         }
+    };
 
-        template <typename Attribute>
-        bool call(Attribute const& actual_attribute, mpl::false_) const
+    ///////////////////////////////////////////////////////////////////////////
+    //  alternative_generate_functor: a functor supplied to spirit::any which
+    //  will be executed for every generator in a given alternative generator
+    //  expression
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename OutputIterator, typename Context, typename Delimiter,
+        typename Parameter>
+    struct alternative_generate_functor
+    {
+        alternative_generate_functor(OutputIterator& sink_, Context& ctx_,
+              Delimiter const& d, Parameter const& p)
+          : sink(sink_), ctx(ctx_), delim(d), param(p)
         {
-            return false;
         }
 
-        template <typename Attribute>
-        bool operator()(Attribute const& actual_attribute) const
+        template <typename Component>
+        bool operator()(Component const& component)
         {
-            typedef mpl::bool_<
-                is_compatible<Attribute, Component, Context>::value>
-            is_compatible;
+            typedef
+                typename traits::attribute_of<
+                    karma::domain, Component, Context>::type
+            expected;
+            typedef
+                alternative_generate<Component, Parameter, expected>
+            generate;
 
-            return call(actual_attribute, is_compatible());
+            return generate::call(component, sink, ctx, delim, param);
         }
 
-        Component const& component;
         OutputIterator& sink;
         Context& ctx;
         Delimiter const& delim;
Modified: trunk/boost/spirit/home/support/argument.hpp
==============================================================================
--- trunk/boost/spirit/home/support/argument.hpp	(original)
+++ trunk/boost/spirit/home/support/argument.hpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -209,7 +209,7 @@
     // current lexer state 
         phoenix::actor<lexer_state> const state = lexer_state();
     
-    // _val refers to the |return| value of a rule
+    // _val refers to the 'return' value of a rule
     // _r0, _r1, ... refer to the rule arguments
         phoenix::actor<attribute<0> > const _val = attribute<0>();
         phoenix::actor<attribute<0> > const _r0 = attribute<0>();
Added: trunk/libs/spirit/example/karma/calc2_ast_dump.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/calc2_ast_dump.cpp	2008-04-29 20:59:08 EDT (Tue, 29 Apr 2008)
@@ -0,0 +1,385 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 Joel de Guzman
+    Copyright (c) 2001-2008 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A Calculator example demonstrating generation of AST which gets dumped into
+//  a human readable format afterwards.
+//
+//  [ JDG April 28, 2008 ]
+//  [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include <boost/function_output_iterator.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our AST
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op;
+struct unary_op;
+struct nil {};
+
+struct expression_ast
+{
+    typedef
+        boost::variant<
+            nil // can't happen!
+          , int
+          , boost::recursive_wrapper<binary_op>
+          , boost::recursive_wrapper<unary_op>
+        >
+    type;
+
+    // expose variant types 
+    typedef type::types types;
+    
+    // expose variant functionality
+    int which() const { return expr.which(); }
+    
+    // constructors
+    expression_ast()
+      : expr(nil()) {}
+
+    expression_ast(unary_op const& expr)
+      : expr(expr) {}
+
+    expression_ast(binary_op const& expr)
+      : expr(expr) {}
+
+    expression_ast(unsigned int expr)
+      : expr(expr) {}
+      
+    expression_ast(type const& expr)
+      : expr(expr) {}
+      
+    expression_ast& operator+=(expression_ast const& rhs);
+    expression_ast& operator-=(expression_ast const& rhs);
+    expression_ast& operator*=(expression_ast const& rhs);
+    expression_ast& operator/=(expression_ast const& rhs);
+
+    type expr;
+};
+
+// expose variant functionality
+template <typename T>
+inline T get(expression_ast const& expr)
+{
+    return boost::get<T>(expr.expr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op
+{
+    binary_op() {}
+    
+    binary_op(
+        char op
+      , expression_ast const& left
+      , expression_ast const& right)
+      : op(op), left(left), right(right) {}
+
+    char op;
+    expression_ast left;
+    expression_ast right;
+};
+
+struct unary_op
+{
+    unary_op(
+        char op
+      , expression_ast const& right)
+    : op(op), right(right) {}
+
+    char op;
+    expression_ast right;
+};
+
+expression_ast& expression_ast::operator+=(expression_ast const& rhs)
+{
+    expr = binary_op('+', expr, rhs);
+    return *this;
+}
+
+expression_ast& expression_ast::operator-=(expression_ast const& rhs)
+{
+    expr = binary_op('-', expr, rhs);
+    return *this;
+}
+
+expression_ast& expression_ast::operator*=(expression_ast const& rhs)
+{
+    expr = binary_op('*', expr, rhs);
+    return *this;
+}
+
+expression_ast& expression_ast::operator/=(expression_ast const& rhs)
+{
+    expr = binary_op('/', expr, rhs);
+    return *this;
+}
+
+// We should be using expression_ast::operator-. There's a bug
+// in phoenix type deduction mechanism that prevents us from
+// doing so. Phoenix will be switching to BOOST_TYPEOF. In the
+// meantime, we will use a phoenix::function below:
+struct negate_expr
+{
+    template <typename T>
+    struct result { typedef T type; };
+
+    expression_ast operator()(expression_ast const& expr) const
+    {
+        return unary_op('-', expr);
+    }
+};
+
+boost::phoenix::function<negate_expr> neg;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator : qi::grammar_def<Iterator, expression_ast(), space_type>
+{
+    calculator()
+    {
+        expression =
+            term                            [_val = _1]
+            >> *(   ('+' >> term            [_val += _1])
+                |   ('-' >> term            [_val -= _1])
+                )
+            ;
+
+        term =
+            factor                          [_val = _1]
+            >> *(   ('*' >> factor          [_val *= _1])
+                |   ('/' >> factor          [_val /= _1])
+                )
+            ;
+
+        factor =
+            uint_                           [_val = _1]
+            |   '(' >> expression           [_val = _1] >> ')'
+            |   ('-' >> factor              [_val = neg(_1)])
+            |   ('+' >> factor              [_val = _1])
+            ;
+    }
+
+    qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A couple of phoenix functions helping to access the elements of the 
+//  generated AST
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+struct get_element
+{
+    template <typename T1>
+    struct result { typedef T const& type; };
+
+    T const& operator()(expression_ast const& expr) const
+    {
+        return boost::get<T>(expr.expr);
+    }
+};
+
+boost::phoenix::function<get_element<int> > _int;
+boost::phoenix::function<get_element<binary_op> > _bin_op;
+boost::phoenix::function<get_element<unary_op> > _unary_op;
+
+///////////////////////////////////////////////////////////////////////////////
+struct get_left
+{
+    template <typename T1>
+    struct result { typedef expression_ast const& type; };
+
+    expression_ast const& operator()(binary_op const& bin_op) const
+    {
+        return bin_op.left;
+    }
+};
+
+boost::phoenix::function<get_left> _left;
+
+struct get_right
+{
+    template <typename T1>
+    struct result { typedef expression_ast const& type; };
+
+    template <typename Node>
+    expression_ast const& operator()(Node const& op) const
+    {
+        return op.right;
+    }
+};
+
+boost::phoenix::function<get_right> _right;
+
+struct get_op
+{
+    template <typename T1>
+    struct result { typedef char type; };
+
+    template <typename Node>
+    char operator()(Node const& bin_op) const
+    {
+        return bin_op.op;
+    }
+};
+
+boost::phoenix::function<get_op> _op;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our AST grammar for the generator
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator>
+struct dump_ast
+  : karma::grammar_def<OuputIterator, expression_ast(), space_type>
+{
+    dump_ast()
+    {
+        ast_node %= 
+                int_        [_1 = _int(_r0)]
+            |   binary_node [_1 = _bin_op(_r0)]
+            |   unary_node  [_1 = _unary_op(_r0)]
+            ;
+            
+        binary_node = 
+                ('(' << ast_node << char_ << ast_node << ')')
+                [ 
+                    _1 = _left(_r0), _2 = _op(_r0), _3 = _right(_r0)
+                ]
+            ;
+
+        unary_node =
+                ('(' << char_ << ast_node << ')')
+                [
+                    _1 = _op(_r0), _2 = _right(_r0)
+                ]
+            ;
+    }
+
+    karma::rule<OuputIterator, expression_ast(), space_type> ast_node;
+    karma::rule<OuputIterator, binary_op(), space_type> binary_node;
+    karma::rule<OuputIterator, unary_op(), space_type> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////
+template <typename String>
+struct string_appender
+{
+    string_appender(String& s)
+    :   str(s)
+    {}
+
+    template <typename T>
+    void operator()(T const &x) const
+    {
+        str += x;
+    }
+
+    String& str;
+};
+
+template <typename String>
+inline string_appender<String>
+make_string_appender(String& str)
+{
+    return string_appender<String>(str);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using boost::make_function_output_iterator;
+
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Expression parser...\n\n";
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+    //  Our parser grammar definitions
+    typedef std::string::const_iterator iterator_type;
+    typedef calculator<iterator_type> calculator;
+
+    calculator def; 
+    qi::grammar<calculator> calc(def, def.expression);
+
+    // Our generator grammar definitions
+    typedef 
+        boost::function_output_iterator<string_appender<std::string> > 
+    output_iterator_type;
+    typedef dump_ast<output_iterator_type> dump_ast;
+    
+    dump_ast dump_ast_def;
+    karma::grammar<dump_ast> ast_grammar(dump_ast_def, dump_ast_def.ast_node); 
+
+    std::string str;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        expression_ast ast;
+        std::string::const_iterator iter = str.begin();
+        std::string::const_iterator end = str.end();
+        bool r = qi::phrase_parse(iter, end, calc, ast, space);
+
+        if (r && iter == end)
+        {
+            std::string generated;
+            r = karma::generate_delimited(
+                make_function_output_iterator(make_string_appender(generated)),
+                ast_grammar, ast, space
+            );
+            
+            if (r)
+            {
+                std::cout << "AST for '" << str << "': " << generated 
+                          << std::endl;
+            }
+            else
+            {
+                std::cout << "-------------------------\n";
+                std::cout << "Generating failed\n";
+                std::cout << "-------------------------\n";
+            }
+        }
+        else
+        {
+            std::string rest(iter, end);
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing failed\n";
+            std::cout << "stopped at: \": " << rest << "\"\n";
+            std::cout << "-------------------------\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+