$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: hartmut.kaiser_at_[hidden]
Date: 2008-08-26 20:17:06
Author: hkaiser
Date: 2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
New Revision: 48399
URL: http://svn.boost.org/trac/boost/changeset/48399
Log:
Spirit.Qi: Added confix parser
Added:
   trunk/boost/spirit/home/qi/auxiliary/confix.hpp   (contents, props changed)
   trunk/libs/spirit/test/qi/config.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/qi/auxiliary.hpp              |     1                                         
   trunk/boost/spirit/home/qi/auxiliary/meta_grammar.hpp |    13 ++++++++++                              
   trunk/libs/spirit/test/Jamfile                        |    50 ++++++++++++++++++++------------------- 
   3 files changed, 40 insertions(+), 24 deletions(-)
Modified: trunk/boost/spirit/home/qi/auxiliary.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/auxiliary.hpp	(original)
+++ trunk/boost/spirit/home/qi/auxiliary.hpp	2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
@@ -9,6 +9,7 @@
 #define BOOST_SPIRIT_STRING_FEB_03_2007_0355PM
 
 #include <boost/spirit/home/qi/auxiliary/none.hpp>
+#include <boost/spirit/home/qi/auxiliary/confix.hpp>
 #include <boost/spirit/home/qi/auxiliary/eps.hpp>
 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
 #include <boost/spirit/home/qi/auxiliary/functor.hpp>
Added: trunk/boost/spirit/home/qi/auxiliary/confix.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/qi/auxiliary/confix.hpp	2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
@@ -0,0 +1,127 @@
+//  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_QI_CONFIX_AUG_26_2008_1012AM)
+#define BOOST_SPIRIT_QI_CONFIX_AUG_26_2008_1012AM
+
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/skip.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 qi
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // the director for a confix() generated parser
+    struct confix_director
+    {
+        template <typename Component, typename Context, typename Iterator>
+        struct attribute
+        {
+            typedef typename
+                result_of::subject<Component>::type
+            subject_type;
+
+            typedef typename
+                traits::attribute_of<
+                    qi::domain, subject_type, Context, Iterator>::type
+            type;
+        };
+
+    private:
+        ///////////////////////////////////////////////////////////////////////
+        template <
+            typename Iterator, typename Context
+          , typename Skipper, typename Expr>
+        static void parse_helper(
+            Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper, Expr const& e)
+        {
+            BOOST_MPL_ASSERT_MSG(
+                (spirit::traits::is_component<qi::domain, Expr>::value), 
+                expression_is_not_convertible_to_a_parser, (Context, Expr));
+
+            typedef 
+                typename result_of::as_component<qi::domain, Expr>::type 
+            expr;
+
+            expr eg = spirit::as_component(qi::domain(), e);
+            typedef typename expr::director director;
+            director::parse(eg, first, last, context, skipper, unused);
+        }
+
+        template <typename Context, typename Expr>
+        static std::string what_helper(Expr const& e, Context& ctx)
+        {
+            typedef 
+                typename result_of::as_component<qi::domain, Expr>::type 
+            expr;
+
+            expr eg = spirit::as_component(qi::domain(), e);
+            typedef typename expr::director director;
+            return director::what(eg, ctx);
+        }
+
+    public:
+        ///////////////////////////////////////////////////////////////////////
+        template <
+            typename Component
+          , typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        static bool parse(
+            Component const& component
+          , Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr)
+        {
+            // parse the prefix
+            parse_helper(first, last, context, skipper, 
+                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::parse(spirit::subject(component), 
+                first, last, context, skipper, attr);
+
+            // append the suffix 
+            parse_helper(first, last, context, skipper, 
+                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/qi/auxiliary/meta_grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/auxiliary/meta_grammar.hpp	(original)
+++ trunk/boost/spirit/home/qi/auxiliary/meta_grammar.hpp	2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
@@ -24,11 +24,14 @@
     ///////////////////////////////////////////////////////////////////////////
     // forwards
     ///////////////////////////////////////////////////////////////////////////
+    struct main_meta_grammar;
+
     struct none;
     struct eps_parser;
     struct semantic_predicate;
     struct lazy_parser;
     struct functor_director;
+    struct confix_director;
 
     struct eol_director;
     struct eoi_director;
@@ -50,19 +53,29 @@
     // none, eps and eps(f)
     struct auxiliary_meta_grammar1
       : proto::or_<
+        // none
             meta_grammar::empty_terminal_rule<
                 qi::domain, tag::none, none>
+        // eps
           , meta_grammar::empty_terminal_rule<
                 qi::domain, tag::eps, eps_parser>
+        // eps()
           , meta_grammar::function1_rule<
                 qi::domain, tag::eps, semantic_predicate>
+        // lazy()
           , meta_grammar::function1_rule<
                 qi::domain, tag::lazy, lazy_parser>
+        // functor parser
           , meta_grammar::terminal_rule<
                 qi::domain
               , functor_holder<proto::_, proto::_>
               , functor_director
             >
+        // confix(..., ...)[...]
+          , meta_grammar::subscript_rule<
+                qi::domain, tag::confix<proto::_, proto::_>, 
+                confix_director, main_meta_grammar
+            >
         >
     {
     };
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile	(original)
+++ trunk/libs/spirit/test/Jamfile	2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
@@ -20,40 +20,41 @@
 
     # run Qi tests
     [ run qi/actions.cpp                    : : : : ]
+    [ run qi/alternative.cpp                : : : : ]
+    [ run qi/and_predicate.cpp              : : : : ]
+    [ run qi/binary.cpp                     : : : : ]
     [ run qi/char.cpp                       : : : : ]
     [ run qi/char_class.cpp                 : : : : ]
-    [ run qi/lit.cpp                        : : : : ]
-    [ run qi/int.cpp                        : : : : ]
-    [ run qi/uint.cpp                       : : : : ]
-    [ run qi/real.cpp                       : : : : ]
+    [ run qi/confix.cpp                     : : : : ]
+    [ run qi/debug.cpp                      : : : : ]
+    [ run qi/difference.cpp                 : : : : ]
+    [ run qi/end.cpp                        : : : : ]
     [ run qi/eps.cpp                        : : : : ]
-    [ run qi/none.cpp                       : : : : ]
+    [ run qi/expect.cpp                     : : : : ]
+    [ run qi/functor.cpp                    : : : : ]
+    [ run qi/grammar.cpp                    : : : : ]
+    [ run qi/int.cpp                        : : : : ]
+    [ run qi/kleene.cpp                     : : : : ]
     [ run qi/lazy.cpp                       : : : : ]
-    [ run qi/tst.cpp                        : : : : ]
-    [ run qi/symbols.cpp                    : : : : ]
-    [ run qi/range_run.cpp                  : : : : ]
-    [ run qi/no_case.cpp                    : : : : ]
     [ run qi/lexeme.cpp                     : : : : ]
-    [ run qi/raw.cpp                        : : : : ]
-    [ run qi/sequence.cpp                   : : : : ]
-    [ run qi/alternative.cpp                : : : : ]
-    [ run qi/sequential_or.cpp              : : : : ]
-    [ run qi/permutation.cpp                : : : : ]
-    [ run qi/difference.cpp                 : : : : ]
+    [ run qi/lit.cpp                        : : : : ]
     [ run qi/list.cpp                       : : : : ]
+    [ run qi/no_case.cpp                    : : : : ]
+    [ run qi/none.cpp                       : : : : ]
+    [ run qi/not_predicate.cpp              : : : : ]
     [ run qi/optional.cpp                   : : : : ]
-    [ run qi/kleene.cpp                     : : : : ]
+    [ run qi/permutation.cpp                : : : : ]
     [ run qi/plus.cpp                       : : : : ]
-    [ run qi/and_predicate.cpp              : : : : ]
-    [ run qi/not_predicate.cpp              : : : : ]
-    [ run qi/expect.cpp                     : : : : ]
+    [ run qi/range_run.cpp                  : : : : ]
+    [ run qi/raw.cpp                        : : : : ]
+    [ run qi/real.cpp                       : : : : ]
     [ run qi/rule.cpp                       : : : : ]
-    [ run qi/grammar.cpp                    : : : : ]
-    [ run qi/functor.cpp                    : : : : ]
+    [ run qi/sequence.cpp                   : : : : ]
+    [ run qi/sequential_or.cpp              : : : : ]
+    [ run qi/symbols.cpp                    : : : : ]
+    [ run qi/tst.cpp                        : : : : ]
+    [ run qi/uint.cpp                       : : : : ]
     [ run qi/match_manip.cpp                : : : : ]
-    [ run qi/binary.cpp                     : : : : ]
-    [ run qi/debug.cpp                      : : : : ]
-    [ run qi/end.cpp                        : : : : ]
 
     [ compile-fail qi/grammar_fail.cpp      : : ]
     [ compile-fail qi/rule_fail.cpp         : : ]
@@ -65,6 +66,7 @@
     [ run karma/case_handling.cpp           : : : : ]
     [ run karma/center_alignment.cpp        : : : : ]
     [ run karma/char.cpp                    : : : : karma_char ]
+    [ run karma/confix.cpp                  : : : : karma_confix ]
     [ run karma/delimiter.cpp               : : : : ]
     [ run karma/eol.cpp                     : : : : karma_eol ]
     [ run karma/eps.cpp                     : : : : karma_eps ]
Added: trunk/libs/spirit/test/qi/config.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/config.cpp	2008-08-26 20:17:06 EDT (Tue, 26 Aug 2008)
@@ -0,0 +1,71 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/support_argument.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 spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST(test("<tag>10</tag>", confix("<tag>", "</tag>")[int_]));
+        BOOST_TEST(test(L"<tag>10</tag>", confix(L"<tag>", L"</tag>")[int_]));
+        BOOST_TEST(test("//10\n", confix(lit("//"), eol)[int_]));
+        BOOST_TEST(test(L"//10\n", confix(wlit("//"), eol)[int_]));
+        BOOST_TEST(test("<ol>10</ol>", html::ol[int_]));
+        BOOST_TEST(test(L"<ol>10</ol>", html::ol[int_]));
+    }
+
+    {
+        BOOST_TEST(test("   <tag> 10   </tag>", confix("<tag>", "</tag>")[int_], 
+            ascii::space));
+        BOOST_TEST(test(L" <tag>   10 </tag>", confix(L"<tag>", L"</tag>")[int_], 
+            ascii::space));
+        BOOST_TEST(test("// 10  \n", confix(lit("//"), eol)[int_], ascii::space));
+        BOOST_TEST(test(L"// 10  \n", confix(wlit("//"), eol)[int_], ascii::space));
+        BOOST_TEST(test("   <ol> 10   </ol>", html::ol[int_], ascii::space));
+        BOOST_TEST(test(L" <ol> 10   </ol>", html::ol[int_], ascii::space));
+    }
+
+    return boost::report_errors();
+}