$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: hartmut.kaiser_at_[hidden]
Date: 2008-08-26 20:15:37
Author: hkaiser
Date: 2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
New Revision: 48398
URL: http://svn.boost.org/trac/boost/changeset/48398
Log:
Spirit.Karma: Added confix generator
Added:
   trunk/boost/spirit/home/karma/auxiliary/confix.hpp   (contents, props changed)
   trunk/boost/spirit/home/support/auxiliary/confix.hpp   (contents, props changed)
   trunk/libs/spirit/test/karma/confix.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/karma/action/meta_grammar.hpp                        |     2                                         
   trunk/boost/spirit/home/karma/auxiliary.hpp                                  |     1                                         
   trunk/boost/spirit/home/karma/auxiliary/meta_grammar.hpp                     |    16 ++++++++++++                            
   trunk/boost/spirit/home/karma/directive/detail/center_alignment_generate.hpp |     6 ++--                                    
   trunk/boost/spirit/home/karma/numeric/real.hpp                               |     5 ++-                                     
   trunk/boost/spirit/home/support/placeholders.hpp                             |     8 +++---                                  
   trunk/libs/spirit/test/karma/test.hpp                                        |    50 ++++++++++++++++++++--------------------
   7 files changed, 52 insertions(+), 36 deletions(-)
Modified: trunk/boost/spirit/home/karma/action/meta_grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/action/meta_grammar.hpp	(original)
+++ trunk/boost/spirit/home/karma/action/meta_grammar.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -20,7 +20,7 @@
     // forwards
     /////////////////////////////////////////////////////////////////////////// 
     struct action;
-    
+
     struct main_meta_grammar;
 
     template <typename Expr, typename Enable>
Modified: trunk/boost/spirit/home/karma/auxiliary.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary.hpp	(original)
+++ trunk/boost/spirit/home/karma/auxiliary.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -7,6 +7,7 @@
 #define BOOST_SPIRIT_KARMA_AUXILIARY_MAR_26_2007_1225PM
 
 #include <boost/spirit/home/karma/auxiliary/none.hpp>
+#include <boost/spirit/home/karma/auxiliary/confix.hpp>
 #include <boost/spirit/home/karma/auxiliary/eps.hpp>
 #include <boost/spirit/home/karma/auxiliary/eol.hpp>
 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
Added: trunk/boost/spirit/home/karma/auxiliary/confix.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/auxiliary/confix.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -0,0 +1,121 @@
+//  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)
+
+#if !defined(BOOST_SPIRIT_KARMA_CONFIX_AUG_19_2008_1041AM)
+#define BOOST_SPIRIT_KARMA_CONFIX_AUG_19_2008_1041AM
+
+#include <boost/spirit/home/karma/domain.hpp>
+#include <boost/spirit/home/karma/delimit.hpp>
+#include <boost/spirit/home/support/component.hpp>
+#include <boost/spirit/home/support/attribute_of.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/auxiliary/confix.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace karma
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // the director for a confix() generated generator
+    struct confix_director
+    {
+        template <typename Component, typename Context, typename Unused>
+        struct attribute
+        {
+            typedef typename
+                result_of::subject<Component>::type
+            subject_type;
+
+            typedef typename
+                traits::attribute_of<karma::domain, subject_type, Context>::type
+            type;
+        };
+
+    private:
+        ///////////////////////////////////////////////////////////////////////
+        template <typename OutputIterator, typename Context, 
+            typename Delimiter, typename Expr>
+        static void
+        generate_helper(OutputIterator& sink, Context& ctx, Delimiter const& d,
+            Expr const& e)
+        {
+            BOOST_MPL_ASSERT_MSG(
+                (spirit::traits::is_component<karma::domain, Expr>::value), 
+                expression_is_not_convertible_to_a_generator, (Context, Expr));
+
+            typedef 
+                typename result_of::as_component<karma::domain, Expr>::type 
+            expr;
+
+            expr eg = spirit::as_component(karma::domain(), e);
+            typedef typename expr::director director;
+            director::generate(eg, sink, ctx, d, unused);
+        }
+
+        template <typename Context, typename Expr>
+        static std::string what_helper(Expr const& e, Context& ctx)
+        {
+            typedef 
+                typename result_of::as_component<karma::domain, Expr>::type 
+            expr;
+
+            expr eg = spirit::as_component(karma::domain(), e);
+            typedef typename expr::director director;
+            return director::what(eg, ctx);
+        }
+
+    public:
+        ///////////////////////////////////////////////////////////////////////
+        template <typename Component, typename OutputIterator, 
+            typename Context, typename Delimiter, typename Parameter>
+        static bool 
+        generate(Component const& component, OutputIterator& sink, 
+            Context& ctx, Delimiter const& d, Parameter const& param) 
+        {
+            // generate the prefix
+            generate_helper(sink, ctx, d, 
+                spirit::detail::confix_extractor::prefix(
+                    proto::arg_c<0>(spirit::argument1(component))));
+
+            // generate the embedded items
+            typedef typename
+                spirit::result_of::subject<Component>::type::director
+            director;
+            bool result = director::generate(spirit::subject(component), sink, 
+                ctx, d, param);
+
+            // append the suffix 
+            generate_helper(sink, ctx, d, 
+                spirit::detail::confix_extractor::suffix(
+                    proto::arg_c<0>(spirit::argument1(component))));
+
+            return result;
+        }
+
+        template <typename Component, typename Context>
+        static std::string what(Component const& component, Context const& ctx)
+        {
+            std::string result = "confix(";
+
+            result += what_helper(spirit::detail::confix_extractor::prefix(
+                    proto::arg_c<0>(spirit::argument1(component))), ctx);
+            result += ", ";
+
+            result += what_helper(spirit::detail::confix_extractor::suffix(
+                    proto::arg_c<0>(spirit::argument1(component))), ctx);
+            result += ")[";
+
+            typedef typename
+                spirit::result_of::subject<Component>::type::director
+            director;
+            result += director::what(spirit::subject(component), ctx);
+            result += "]";
+
+            return result;
+        }
+    };
+
+}}}
+
+#endif
Modified: trunk/boost/spirit/home/karma/auxiliary/meta_grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary/meta_grammar.hpp	(original)
+++ trunk/boost/spirit/home/karma/auxiliary/meta_grammar.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -22,13 +22,16 @@
     ///////////////////////////////////////////////////////////////////////////
     // forwards
     ///////////////////////////////////////////////////////////////////////////
+    struct main_meta_grammar;
+
     struct none;
     struct eps_generator;
     struct eol_generator;
     struct semantic_predicate;
     struct lazy_generator;
     struct functor_director;
-    
+    struct confix_director;
+
     template <typename Expr, typename Enable>
     struct is_valid_expr;
 
@@ -42,20 +45,31 @@
     // none, and lazy
     struct auxiliary_meta_grammar
       : proto::or_<
+            // none
             meta_grammar::empty_terminal_rule<
                 karma::domain, tag::none, none>,
+            // eps
             meta_grammar::empty_terminal_rule<
                 karma::domain, tag::eps, eps_generator>,
+            // eol
             meta_grammar::empty_terminal_rule<
                 karma::domain, tag::eol, eol_generator>,
+            // eps(...)
             meta_grammar::function1_rule<
                 karma::domain, tag::eps, semantic_predicate>,
+            // lazy(...)
             meta_grammar::function1_rule<
                 karma::domain, tag::lazy, lazy_generator>,
+            // functor generators
             meta_grammar::terminal_rule<
                 karma::domain, 
                 functor_holder<proto::_, proto::_>,
                 functor_director
+            >,
+            // confix("...", "...")[...]
+            meta_grammar::subscript_rule<
+                karma::domain, tag::confix<proto::_, proto::_>, 
+                confix_director, main_meta_grammar
             >
         >
     {
Modified: trunk/boost/spirit/home/karma/directive/detail/center_alignment_generate.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/detail/center_alignment_generate.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/detail/center_alignment_generate.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -35,17 +35,17 @@
         BOOST_MPL_ASSERT_MSG(
             (spirit::traits::is_component<karma::domain, Padding>::value), 
             padding_is_not_convertible_to_a_generator, (Context, Padding));
-            
+
         typedef 
             typename result_of::as_component<karma::domain, Embedded>::type 
         embedded;
         typedef 
             typename result_of::as_component<karma::domain, Padding>::type 
         padding;
-        
+
         // wrap the given output iterator to allow left padding
         detail::enable_buffering<OutputIterator> buffering(sink, width);
-        
+
         // first generate the embedded output 
         embedded ec = spirit::as_component(karma::domain(), e);
         typedef typename embedded::director director;
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -49,8 +49,9 @@
         generate(Component const& component, OutputIterator& sink,
             Context& /*ctx*/, Delimiter const& d, Parameter const& param)
         {
-            RealPolicies const& p = detail::real_policy<RealPolicies>::get(
-                fusion::at_c<0>(component.elements));
+            RealPolicies const& p = 
+                detail::real_policy<RealPolicies>::get(spirit::subject(component));
+
             bool result = real_inserter<T, RealPolicies, Tag>::
                 call(sink, param, p);
 
Added: trunk/boost/spirit/home/support/auxiliary/confix.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/auxiliary/confix.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -0,0 +1,87 @@
+//  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)
+
+#if !defined(BOOST_SPIRIT_SUPPORT_CONFIX_AUG_19_2008_1103AM)
+#define BOOST_SPIRIT_SUPPORT_CONFIX_AUG_19_2008_1103AM
+
+#include <boost/spirit/home/support/placeholders.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace tag
+{
+    // This is the tag returned by the confix() function
+    template <typename Prefix, typename Suffix>
+    struct confix
+    {
+        Prefix prefix;
+        Suffix suffix;
+    };
+
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit 
+{
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Prefix, typename Suffix = Prefix>
+    struct confix_spec
+      : proto::terminal<tag::confix<Prefix, Suffix> >::type
+    {
+    private:
+        typedef typename 
+            proto::terminal<tag::confix<Prefix, Suffix> >::type
+        base_type;
+
+        base_type make_tag(Prefix const& prefix, Suffix const& suffix) const
+        {
+            base_type xpr = {{prefix, suffix}};
+            return xpr;
+        }
+
+    public:
+        confix_spec(Prefix const& prefix, Suffix const& suffix)
+          : base_type(make_tag(prefix, suffix))
+        {}
+    };
+
+    namespace detail
+    {
+        struct confix_extractor
+        {
+            template <typename Prefix, typename Suffix>
+            static Prefix const& prefix(tag::confix<Prefix, Suffix> const& c) 
+            { return c.prefix; }
+
+            template <typename Prefix, typename Suffix>
+            static Suffix const& suffix(tag::confix<Prefix, Suffix> const& c) 
+            { return c.suffix; }
+        };
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // construct a confix component
+    ///////////////////////////////////////////////////////////////////////////
+    inline confix_spec<char const*>
+    confix(char const* prefix, char const* suffix)
+    {
+        return confix_spec<char const*>(prefix, suffix);
+    }
+
+    inline confix_spec<wchar_t const*>
+    confix(wchar_t const* prefix, wchar_t const* suffix)
+    {
+        return confix_spec<wchar_t const*>(prefix, suffix);
+    }
+
+    template <typename Prefix, typename Suffix>
+    inline confix_spec<Prefix, Suffix>
+    confix(Prefix const& prefix, Suffix const& suffix)
+    {
+        return confix_spec<Prefix, Suffix>(prefix, suffix);
+    }
+
+}}
+
+#endif
Modified: trunk/boost/spirit/home/support/placeholders.hpp
==============================================================================
--- trunk/boost/spirit/home/support/placeholders.hpp	(original)
+++ trunk/boost/spirit/home/support/placeholders.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -30,7 +30,7 @@
         struct bin {};
         struct oct {};
         struct hex {};
-        
+
         struct byte {};
         struct word {};
         struct dword {};
@@ -44,7 +44,7 @@
         struct little_qword {};
 #endif
         struct pad {};
-        
+
         struct ushort {};
         struct ulong {};
         struct uint {};
@@ -72,10 +72,10 @@
         struct lazy {};
         struct omit {};
         struct raw {};
-        
+
         struct stream {};
         struct wstream {};
-        
+
         struct token {};
     }
 
Added: trunk/libs/spirit/test/karma/confix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/confix.cpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -0,0 +1,83 @@
+//  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)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+namespace html
+{
+    ///////////////////////////////////////////////////////////////////////////////
+    //  define a HTML tag helper generator
+    template <typename Char, typename Traits, typename Allocator>
+    inline boost::spirit::confix_spec<std::basic_string<Char, Traits, Allocator> >
+    tag (std::basic_string<Char, Traits, Allocator> const& tagname)
+    {
+        typedef std::basic_string<Char, Traits, Allocator> string_type;
+        return boost::spirit::confix_spec<string_type>(
+            string_type("<") + tagname + ">", string_type("</") + tagname + ">");
+    }
+
+    inline boost::spirit::confix_spec<std::string>
+    tag (char const* tagname)
+    {
+        return tag(std::string(tagname));
+    }
+
+    typedef boost::spirit::confix_spec<std::string> html_tag_type;
+
+    html_tag_type const ol = tag("ol");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace spirit_test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST((test("<tag>a</tag>", 
+            confix("<tag>", "</tag>")[char_('a')])));
+        BOOST_TEST((test("// some C++ comment\n", 
+            confix(lit("//"), eol)[" some C++ comment"])));
+        BOOST_TEST((test("<ol>some text</ol>", html::ol["some text"])));
+    }
+
+    {
+        BOOST_TEST((test(L"<tag>a</tag>", 
+            confix(L"<tag>", L"</tag>")[wchar(L'a')])));
+        BOOST_TEST((test(L"// some C++ comment\n", 
+            confix(wlit(L"//"), eol)[L" some C++ comment"])));
+        BOOST_TEST((test(L"<ol>some text</ol>", html::ol[L"some text"])));
+    }
+
+    {
+        BOOST_TEST((test_delimited("<tag> a </tag> ", 
+            confix("<tag>", "</tag>")[char_('a')], space)));
+        BOOST_TEST((test_delimited("// some C++ comment \n ", 
+            confix(lit("//"), eol)["some C++ comment"], space)));
+        BOOST_TEST((test_delimited("<ol> some text </ol> ", 
+            html::ol["some text"], space)));
+    }
+
+    {
+        BOOST_TEST((test_delimited(L"<tag> a </tag> ", 
+            confix(L"<tag>", L"</tag>")[wchar(L'a')], space)));
+        BOOST_TEST((test_delimited(L"// some C++ comment \n ", 
+            confix(wlit(L"//"), eol)[L"some C++ comment"], space)));
+        BOOST_TEST((test_delimited(L"<ol> some text </ol> ", 
+            html::ol[L"some text"], space)));
+    }
+
+    return boost::report_errors();
+}
Modified: trunk/libs/spirit/test/karma/test.hpp
==============================================================================
--- trunk/libs/spirit/test/karma/test.hpp	(original)
+++ trunk/libs/spirit/test/karma/test.hpp	2008-08-26 20:15:36 EDT (Tue, 26 Aug 2008)
@@ -49,14 +49,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
-        
+
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g);
-                
+
         return result && generated == expected;
     }
 
@@ -65,14 +65,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g);
-                
+
         return result && generated == expected;
     }
 
@@ -83,14 +83,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g, parameter);
-                
+
         return result && generated == expected;
     }
 
@@ -100,14 +100,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g, parameter);
-                
+
         return result && generated == expected;
     }
 
@@ -118,14 +118,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), g, d);
-                
+
         return result && generated == expected;
     }
 
@@ -135,14 +135,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), g, d);
-                
+
         return result && generated == expected;
     }
 
@@ -154,7 +154,7 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
@@ -162,7 +162,7 @@
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), 
             g, parameter, d);
-                
+
         return result && generated == expected;
     }
 
@@ -173,7 +173,7 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<Char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
@@ -181,7 +181,7 @@
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), 
             g, parameter, d);
-                
+
         return result && generated == expected;
     }
 
@@ -193,14 +193,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g);
-                
+
         return result && !std::memcmp(generated.c_str(), expected, size);
     }
 
@@ -212,14 +212,14 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
 
         string_type generated;
         bool result = karma::generate(std::back_inserter(generated), g, parameter);
-                
+
         return result && !std::memcmp(generated.c_str(), expected, size);
     }
 
@@ -231,7 +231,7 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
@@ -239,7 +239,7 @@
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), 
             g, d);
-                
+
         return result && !std::memcmp(generated.c_str(), expected, size);
     }
 
@@ -251,7 +251,7 @@
     {
         namespace karma = boost::spirit::karma;
         typedef std::basic_string<char> string_type;
-        
+
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
         karma::what(g);
@@ -259,7 +259,7 @@
         string_type generated;
         bool result = karma::generate_delimited(std::back_inserter(generated), 
             g, parameter, d);
-                
+
         return result && !std::memcmp(generated.c_str(), expected, size);
     }