$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55304 - in trunk/libs/spirit/repository: doc/html doc/qi example/qi test test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2009-07-30 21:12:33
Author: hkaiser
Date: 2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
New Revision: 55304
URL: http://svn.boost.org/trac/boost/changeset/55304
Log:
Spirit: repository doc update, added example and test for qi::confix
Added:
   trunk/libs/spirit/repository/doc/qi/confix.qbk   (contents, props changed)
   trunk/libs/spirit/repository/example/qi/confix.cpp   (contents, props changed)
   trunk/libs/spirit/repository/test/qi/confix.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/repository/doc/html/index.html          |    24 ++++++++++++++----------                
   trunk/libs/spirit/repository/doc/qi/compound_parsers.qbk  |     2 +-                                      
   trunk/libs/spirit/repository/doc/qi/directives.qbk        |     3 ++-                                     
   trunk/libs/spirit/repository/doc/qi/distinct.qbk          |     2 +-                                      
   trunk/libs/spirit/repository/doc/qi/flush_multi_pass.qbk  |     2 +-                                      
   trunk/libs/spirit/repository/doc/qi/primitive_parsers.qbk |     2 +-                                      
   trunk/libs/spirit/repository/test/CMakeLists.txt          |     1 +                                       
   trunk/libs/spirit/repository/test/Jamfile                 |     1 +                                       
   8 files changed, 22 insertions(+), 15 deletions(-)
Modified: trunk/libs/spirit/repository/doc/html/index.html
==============================================================================
--- trunk/libs/spirit/repository/doc/html/index.html	(original)
+++ trunk/libs/spirit/repository/doc/html/index.html	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -34,7 +34,7 @@
 <div><p class="copyright">Copyright © 2001-2009 Joel
       de Guzman, Hartmut Kaiser</p></div>
 <div><div class="legalnotice" title="Legal Notice">
-<a name="id1026275"></a><p>
+<a name="id1015171"></a><p>
         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)
       </p>
@@ -48,14 +48,18 @@
 <dt><span class="section">Preface</span></dt>
 <dt><span class="section">Qi Components</span></dt>
 <dd><dl>
-<dt><span class="section"><a href="spirit_repository/qi_components/qi_parser_primitives.html">Qi
-      Parser Primitives</a></span></dt>
-<dd><dl><dt><span class="section"><a href="spirit_repository/qi_components/qi_parser_primitives/qi_flush_multi_pass_parser.html">Qi
-        flush_multi_pass parser</a></span></dt></dl></dd>
-<dt><span class="section"><a href="spirit_repository/qi_components/qi_parser_directives.html">Qi
-      Parser Directives</a></span></dt>
-<dd><dl><dt><span class="section"><a href="spirit_repository/qi_components/qi_parser_directives/qi_distinct_parser.html">Qi
-        Distinct Parser</a></span></dt></dl></dd>
+<dt><span class="section"><a href="spirit_repository/qi_components/primitive.html"> Qi Parser
+      Primitives</a></span></dt>
+<dd><dl><dt><span class="section"><a href="spirit_repository/qi_components/primitive/flush_multi_pass.html">
+        Qi flush_multi_pass parser</a></span></dt></dl></dd>
+<dt><span class="section"><a href="spirit_repository/qi_components/directives.html"> Qi Parser
+      Directives</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="spirit_repository/qi_components/directives/confix.html">
+        Qi Confix Parser Directive</a></span></dt>
+<dt><span class="section"><a href="spirit_repository/qi_components/directives/distinct.html">
+        Qi Distinct Parser Directive</a></span></dt>
+</dl></dd>
 </dl></dd>
 <dt><span class="section">Karma Components</span></dt>
 <dd><dl>
@@ -68,7 +72,7 @@
 </div>
 </div>
 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
-<td align="left"><p><small>Last revised: July 27, 2009 at 18:43:05 GMT</small></p></td>
+<td align="left"><p><small>Last revised: July 30, 2009 at 22:57:50 GMT</small></p></td>
 <td align="right"><div class="copyright-footer"></div></td>
 </tr></table>
 <hr>
Modified: trunk/libs/spirit/repository/doc/qi/compound_parsers.qbk
==============================================================================
--- trunk/libs/spirit/repository/doc/qi/compound_parsers.qbk	(original)
+++ trunk/libs/spirit/repository/doc/qi/compound_parsers.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -6,5 +6,5 @@
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ===============================================================================/]
 
-[section Qi Compound Parsers]
+[section:compound Qi Compound Parsers]
 [endsect]
Added: trunk/libs/spirit/repository/doc/qi/confix.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/repository/doc/qi/confix.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -0,0 +1,136 @@
+[/==============================================================================
+    Copyright (C) 2001-2009 Hartmut Kaiser
+    Copyright (C) 2001-2009 Joel de Guzman
+    Copyright (C) 2009 Chris Hoeppler
+
+    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)
+===============================================================================/]
+
+[section:confix Qi Confix Parser Directive]
+
+[heading Description]
+
+The __qi__ `confix` directive is a unary parser component allowing to embed a
+parser (the subject) inside an opening (the prefix) and a closing (the suffix):
+
+    confix(prefix, suffix)[subject]
+
+This results in a parser that is equivalent to the sequence 
+
+    omit[prefix] >> subject >> omit[suffix]
+
+A simple example is a parser for non-nested comments which can now be written
+as:
+
+    confix("/*", "*/")[*(char_ - "*/")]  // C style comment
+    confix("//", eol)[*(char_ - eol)]    // C++ style comment
+
+Using the `confix` directive instead of the explicit sequence has the advantage
+of being able to encapsulate the prefix and the suffix into a separate construct.
+The following code snippet illustrates the idea:
+
+    namespace spirit = boost::spirit;
+    namespace repo = boost::spirit::repository;
+
+    // Define a metafunction allowing to compute the type
+    // of the confix() construct
+    template <typename Prefix, typename Suffix = Prefix>
+    struct confix_spec
+    {
+        typedef typename spirit::result_of::terminal<
+            repo::tag::confix(Prefix, Suffix)
+        >::type type;
+    };
+
+    confix_spec<std::string>::type const c_comment = repo::confix("/*", "*/");
+    confix_spec<std::string>::type const cpp_comment = repo::confix("//", "\n");
+
+Now, the comment parsers can be written as
+
+    c_comment[*(char_ - "*/")]    // C style comment
+    cpp_comment[*(char_ - eol)]   // C++ style comment
+
+[note While the `confix_p(prefix, subject, suffix)` parser in __classic__
+      was equivalent to the sequence `prefix >> (subject - suffix) >> suffix,
+      the __qi__ `confix` directive will not perform this refactoring any more.
+      This simplifies the code and makes things more explicit.]
+
+[heading Header]
+
+    #include <boost/spirit/repository/include/qi_confix.hpp>
+
+[heading Synopsis]
+
+    confix(prefix, suffix)[subject]
+
+[heading Parameters]
+
+[table
+    [[Parameter]            [Description]]
+    [[`prefix`]             [The parser for the opening (the prefix).]]
+    [[`suffix`]             [The parser for the ending (the suffix).]]
+    [[`subject`]            [The parser for the input sequence between the
+                             `prefix` and `suffix` parts.]]
+]
+
+All three parameters can be arbitrarily complex parsers themselves.
+
+[heading Attribute]
+
+The `confix` directive exposes the attribute type of its subject as its own 
+attribute type. If the `subject` does not expose any attribute (the type is
+`unused_type`), then the `confix` does not expose any attribute either.
+
+    a: A, p: P, s: S: --> confix(p, s)[a]: A
+
+[note This notation is used all over the Spirit documentation and reads as:
+      Given, `a`, `p`, and `s` are parsers, and `A`, `P`, and `S` are the types
+      of their attributes, then the type of the attribute exposed by
+      `confix(p, s)[a]` will be `A`.]
+
+[heading Example]
+
+The following example shows simple use cases of the `confix` directive. We will
+illustrate its usage by generating parsers for different comment styles and 
+for some simple tagged data (for the full example code see
+[@../../example/qi/confix.cpp confix.cpp])
+
+[import ../example/qi/confix.cpp]
+
+[heading Prerequisites]
+
+In addition to the main header file needed to include the core components 
+implemented in __qi__ we add the header file needed for the new `confix` 
+directive.
+
+[qi_confix_includes]
+
+In order to make the examples below more readable we import a number of
+elements into the current namespace:
+
+[qi_confix_using]
+
+[heading Parsing Different Comment Styles]
+
+We will show how to parse different comment styles. First we will parse
+a C++ comment:
+
+[qi_confix_cpp_comment]
+
+This function will obviously parse input such as "`// This is a comment \n `".
+Similarily parsing a 'C'-style comment proves to be straightforward:
+
+[qi_confix_c_comment]
+
+which again will be able to parse e.g. "`/* This is a comment */ `".
+
+[heading Parsing Tagged Data]
+
+Generating a parser that extracts the body from the HTML snippet "`<b>The Body</b>`"
+is not very hard, either:
+
+[qi_confix_tagged_data]
+
+
+[endsect]
Modified: trunk/libs/spirit/repository/doc/qi/directives.qbk
==============================================================================
--- trunk/libs/spirit/repository/doc/qi/directives.qbk	(original)
+++ trunk/libs/spirit/repository/doc/qi/directives.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -6,6 +6,7 @@
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ===============================================================================/]
 
-[section Qi Parser Directives]
+[section:directives Qi Parser Directives]
+[include        confix.qbk]
 [include        distinct.qbk]
 [endsect]
Modified: trunk/libs/spirit/repository/doc/qi/distinct.qbk
==============================================================================
--- trunk/libs/spirit/repository/doc/qi/distinct.qbk	(original)
+++ trunk/libs/spirit/repository/doc/qi/distinct.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -6,7 +6,7 @@
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ===============================================================================/]
 
-[section Qi Distinct Parser]
+[section:distinct Qi Distinct Parser Directive]
 
 [heading Description]
 
Modified: trunk/libs/spirit/repository/doc/qi/flush_multi_pass.qbk
==============================================================================
--- trunk/libs/spirit/repository/doc/qi/flush_multi_pass.qbk	(original)
+++ trunk/libs/spirit/repository/doc/qi/flush_multi_pass.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -6,7 +6,7 @@
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ===============================================================================/]
 
-[section Qi flush_multi_pass parser]
+[section:flush_multi_pass Qi flush_multi_pass parser]
 
 [heading Description]
 
Modified: trunk/libs/spirit/repository/doc/qi/primitive_parsers.qbk
==============================================================================
--- trunk/libs/spirit/repository/doc/qi/primitive_parsers.qbk	(original)
+++ trunk/libs/spirit/repository/doc/qi/primitive_parsers.qbk	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -6,6 +6,6 @@
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ===============================================================================/]
 
-[section Qi Parser Primitives]
+[section:primitive Qi Parser Primitives]
 [include        flush_multi_pass.qbk]
 [endsect]
Added: trunk/libs/spirit/repository/example/qi/confix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/repository/example/qi/confix.cpp	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -0,0 +1,113 @@
+//  Copyright (c) 2009 Chris Hoeppler
+// 
+//  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)
+
+//  The purpose of this example is to demonstrate different use cases for the
+//  confix directive.
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+//[qi_confix_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/repository/include/qi_confix.hpp>
+//]
+
+namespace client {
+//[qi_confix_using
+    using boost::spirit::eol;
+    using boost::spirit::lexeme;
+    using boost::spirit::ascii::alnum;
+    using boost::spirit::ascii::char_;
+    using boost::spirit::ascii::space;
+    using boost::spirit::qi::parse;
+    using boost::spirit::qi::phrase_parse;
+    using boost::spirit::repository::confix;
+//]
+
+//[qi_confix_cpp_comment
+    template <typename Iterator>
+    bool parse_cpp_comment(Iterator first, Iterator last, std::string& attr)
+    {
+        bool r = parse(first, last,
+            confix("//", eol)[*(char_ - eol)],  // grammar
+            attr);                              // attribute
+        
+        if (!r || first != last) // fail if we did not get a full match
+            return false;
+        return r;
+    }
+//]
+
+//[qi_confix_c_comment
+    template <typename Iterator>
+    bool parse_c_comment(Iterator first, Iterator last, std::string& attr)
+    {
+        bool r = parse(first, last,
+            confix("/*", "*/")[*(char_ - "*/")],    // grammar
+            attr);                                  // attribute
+        
+        if (!r || first != last) // fail if we did not get a full match
+            return false;
+        return r;
+    }
+//]
+
+//[qi_confix_tagged_data
+    template <typename Iterator>
+    bool parse_tagged(Iterator first, Iterator last, std::string& attr)
+    {
+        bool r = phrase_parse(first, last,
+            confix("<b>", "</b>")[lexeme[*(char_ - '<')]],  // grammar
+            space,                                          // skip
+            attr);                                          // attribute
+        
+        if (!r || first != last) // fail if we did not get a full match
+            return false;
+        return r;
+    }
+//]
+}
+
+
+int main()
+{
+    // C++ comment
+    std::string comment("// This is a comment\n");
+    std::string attr;
+    bool r = client::parse_cpp_comment(comment.begin(), comment.end(), attr);
+
+    std::cout << "Parsing a C++ comment";
+    if (r && attr == " This is a comment")
+        std::cout << " succeeded." << std::endl;
+    else
+        std::cout << " failed" << std::endl;
+
+    // C comment
+    comment = "/* This is another comment */";
+    attr.clear();
+    r = client::parse_c_comment(comment.begin(), comment.end(), attr);
+
+    std::cout << "Parsing a C comment";
+    if (r && attr == " This is another comment ")
+        std::cout << " succeeded." << std::endl;
+    else
+        std::cout << " failed" << std::endl;
+
+    // Tagged data
+    std::string data = "<b> This is the body. </b>";
+    attr.clear();
+
+    r = client::parse_tagged(data.begin(), data.end(), attr);
+
+    std::cout << "Parsing tagged data";
+    if (r && attr == "This is the body. ")
+        std::cout << " succeeded." << std::endl;
+    else
+        std::cout << " failed" << std::endl;
+
+    return 0;
+}
+
Modified: trunk/libs/spirit/repository/test/CMakeLists.txt
==============================================================================
--- trunk/libs/spirit/repository/test/CMakeLists.txt	(original)
+++ trunk/libs/spirit/repository/test/CMakeLists.txt	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -19,6 +19,7 @@
 ENDIF(CMAKE_COMPILER_IS_GNUCC)
 
 # run Qi repository tests
+boost_test_run(qi_repo_confix qi/confix.cpp COMPILE_FLAGS ${test_compile_flags})
 boost_test_run(qi_repo_distinct qi/distinct.cpp COMPILE_FLAGS ${test_compile_flags})
 
 # run Karma repository tests
Modified: trunk/libs/spirit/repository/test/Jamfile
==============================================================================
--- trunk/libs/spirit/repository/test/Jamfile	(original)
+++ trunk/libs/spirit/repository/test/Jamfile	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -22,6 +22,7 @@
     test-suite spirit_v2_repository :
 
     # run Qi repository tests
+    [ run qi/confix.cpp                     : : : : qi_repo_confix ]
     [ run qi/distinct.cpp                   : : : : qi_repo_distinct ]
 
     # run Karma repository tests
Added: trunk/libs/spirit/repository/test/qi/confix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/repository/test/qi/confix.cpp	2009-07-30 19:05:02 EDT (Thu, 30 Jul 2009)
@@ -0,0 +1,147 @@
+/*=============================================================================
+    Copyright (c) 2009 Chris Hoeppler
+
+    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_action.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <boost/spirit/repository/home/qi/confix.hpp>
+
+#include <string>
+#include "test.hpp"
+
+namespace comment {
+    namespace spirit = boost::spirit;
+    namespace repo = boost::spirit::repository;
+
+    // Define a metafunction allowing to compute the type
+    // of the confix() construct
+    template <typename Prefix, typename Suffix = Prefix>
+    struct confix_spec_traits
+    {
+        typedef typename spirit::result_of::terminal<
+            repo::tag::confix(Prefix, Suffix)
+        >::type type;
+    };
+
+    template <typename Prefix, typename Suffix>
+    inline typename confix_spec_traits<Prefix, Suffix>::type
+    confix_spec(Prefix const& prefix, Suffix const& suffix)
+    {
+        return repo::confix(prefix, suffix);
+    }
+    
+    inline confix_spec_traits<std::string>::type
+    confix_spec(const char* prefix, const char* suffix)
+    {
+        return repo::confix(std::string(prefix), std::string(suffix));
+    }
+    confix_spec_traits<std::string>::type const c_comment = confix_spec("/*", "*/");
+    confix_spec_traits<std::string>::type const cpp_comment = confix_spec("//", "\n");
+}
+
+int main()
+{
+    using spirit_test::test_attr;
+    using spirit_test::test;
+
+    using namespace boost::spirit::ascii;
+    using namespace boost::spirit::qi::labels;
+    using boost::spirit::qi::locals;
+    using boost::spirit::qi::rule;
+    using boost::spirit::qi::debug;
+
+    namespace phx = boost::phoenix;
+    namespace repo = boost::spirit::repository;
+
+    { // basic tests
+
+        rule<char const*> start;
+
+        start = repo::confix('a', 'c')['b'];
+        BOOST_TEST(test("abc", start));
+
+        start = repo::confix('a', 'c')['b'] | "abd";
+        BOOST_TEST(test("abd", start));
+
+        start = repo::confix("/*", "*/")[*(alpha - "*/")];
+        BOOST_TEST(test("/*aaaabababaaabbb*/", start));
+
+        start = repo::confix(char_('/') >> '*', '*' >> char_('/'))[*alpha - "*/"];
+        BOOST_TEST(test("/*aaaabababaaabba*/", start));
+        
+        start = comment::c_comment[*(alpha - "*/")];
+        BOOST_TEST(test("/*aaaabababaaabbb*/", start));
+
+        // ignore the skipper!
+        BOOST_TEST(!test("/* aaaabababaaabba*/", start, space));
+    }
+
+    { // basic tests w/ skipper
+
+        rule<char const*, space_type> start;
+
+        start = repo::confix('a', 'c')['b'];
+        BOOST_TEST(test(" a b c ", start, space));
+
+        start = repo::confix(char_('/') >> '*', '*' >> char_('/'))[*alpha - "*/"];
+        BOOST_TEST(test(" / *a       b a b a b a a a b b b * / ", start, space));
+    }
+
+    { // context tests
+        char ch;
+        rule<char const*, char()> a;
+        a = repo::confix("/*", "*/")[alpha][_val = _1];
+
+        BOOST_TEST(test("/*x*/", a[phx::ref(ch) = _1]));
+        BOOST_TEST(ch == 'x');
+
+        a %= repo::confix("/*", "*/")[alpha];
+        BOOST_TEST(test_attr("/*z*/", a, ch)); // attribute is given.
+        BOOST_TEST(ch == 'z');
+    }
+
+    { // rules test
+        rule<char const*> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+
+        a.name("a");
+        b.name("b");
+        c.name("c");
+        start.name("start");
+
+        debug(a);
+        debug(b);
+        debug(c);
+        debug(start);
+
+        start = repo::confix(a, c)[b];
+        BOOST_TEST(test("abc", start));
+    }
+
+    { // modifiers test
+        rule<char const*> start;
+        start = no_case[repo::confix("_A_", "_Z_")["heLLo"]];
+        BOOST_TEST(test("_a_hello_z_", start));
+    }
+
+    return boost::report_errors();
+}
+