$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61566 - trunk/libs/spirit/example/scheme/test
From: joel_at_[hidden]
Date: 2010-04-26 00:13:20
Author: djowel
Date: 2010-04-26 00:13:18 EDT (Mon, 26 Apr 2010)
New Revision: 61566
URL: http://svn.boost.org/trac/boost/changeset/61566
Log:
changed fragments storage from vector to map to avoid invalidation of rule addresses.
Text files modified: 
   trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp |   148 ++++++++++++++++++++++++++++++++++----- 
   1 files changed, 126 insertions(+), 22 deletions(-)
Modified: trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp	2010-04-26 00:13:18 EDT (Mon, 26 Apr 2010)
@@ -12,9 +12,12 @@
 #include <scheme/compiler.hpp>
 #include <utree/io.hpp>
 #include <boost/spirit/include/qi.hpp>
+#include <map>
 
 #include "../../../test/qi/test.hpp"
 
+#define SCHEME_QI_COMPILER_LIMIT 20
+
 namespace scheme { namespace qi
 {
     ///////////////////////////////////////////////////////////////////////////
@@ -28,36 +31,42 @@
 
     ///////////////////////////////////////////////////////////////////////////
     // All rule are stored here. Rules are held in the utree by its id;
-    // i.e. it's index in the vector.
+    // i.e. its index in the vector.
     ///////////////////////////////////////////////////////////////////////////
     template <typename Rule>
     class rule_fragments
     {
     public:
 
-        rule_fragments() {};
+        rule_fragments()
+          : index(0)
+        {
+        };
 
         template <typename Expr>
         int new_rule(Expr const& expr)
         {
-            rules.push_back(Rule());
-            rules.back() = expr;
-            return rules.size()-1;
+            rules[index] = expr;
+            return index++;
         }
 
-        Rule const& get_rule(int id) const
+        Rule const& operator[](int id) const
         {
-            return rules[id];
+            typename std::map<int, Rule>::const_iterator
+                iter = rules.find(id);
+            BOOST_ASSERT(iter != rules.end());
+            return iter->second;
         }
 
-        Rule const& get_rule(utree const& id) const
+        Rule const& operator[](utree const& id) const
         {
-            return rules[id.get<int>()];
+            return (*this)[id.get<int>()];
         }
 
     private:
 
-        std::vector<Rule> rules;
+        int index;
+        std::map<int, Rule> rules;
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -146,11 +155,11 @@
     };
 
     template <typename Fragments>
-    struct unary_char_composite
-      : composite<unary_char_composite<Fragments> >
+    struct char_composite
+      : composite<char_composite<Fragments> >
     {
         Fragments& fragments;
-        unary_char_composite(Fragments& fragments)
+        char_composite(Fragments& fragments)
           : fragments(fragments) {}
 
         function compose(actor_list const& elements) const
@@ -166,6 +175,92 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    // Handles the compilation of kleene *a
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Fragments>
+    struct kleene_function : actor<kleene_function<Fragments> >
+    {
+        Fragments& fragments;
+        function a;
+        kleene_function(
+            Fragments& fragments, function const& a)
+          : a(a), fragments(fragments)
+        {
+        }
+
+        utree eval(utree const& a) const
+        {
+            return fragments.new_rule(*fragments[a]); // *a
+        }
+
+        utree eval(scope const& env) const
+        {
+            return eval(a(env));
+        }
+    };
+
+    template <typename Fragments>
+    struct kleene_composite
+      : composite<kleene_composite<Fragments> >
+    {
+        Fragments& fragments;
+        kleene_composite(Fragments& fragments)
+          : fragments(fragments) {}
+
+        function compose(actor_list const& elements) const
+        {
+            typedef kleene_function<Fragments> function_type;
+            return function(function_type(fragments, elements.front()));
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Handles the compilation of difference a - b
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Fragments>
+    struct difference_function : actor<difference_function<Fragments> >
+    {
+        Fragments& fragments;
+        function a;
+        function b;
+        difference_function(
+            Fragments& fragments, function const& a, function const& b)
+          : a(a), b(b), fragments(fragments)
+        {
+        }
+
+        utree eval(utree const& a, utree const& b) const
+        {
+            return fragments.new_rule(
+                fragments[a] - fragments[b]); // a - b
+        }
+
+        utree eval(scope const& env) const
+        {
+            return eval(a(env), b(env));
+        }
+    };
+
+    template <typename Fragments>
+    struct difference_composite
+      : composite<difference_composite<Fragments> >
+    {
+        Fragments& fragments;
+        difference_composite(Fragments& fragments)
+          : fragments(fragments) {}
+
+        function compose(actor_list const& elements) const
+        {
+            typedef difference_function<Fragments> function_type;
+            actor_list::const_iterator i = elements.begin();
+
+            function const& a = *i++;
+            function const& b = *i;
+            return function(function_type(fragments, a, b));
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     // Build our scheme compiler environment.
     ///////////////////////////////////////////////////////////////////////////
     template <typename Fragments>
@@ -183,7 +278,13 @@
             make_primitive_parser_composite(fragments, qi::int_), 0, true);
 
         env.define("qi:char_",
-            unary_char_composite<Fragments>(fragments), 1, false);
+            char_composite<Fragments>(fragments), 1, false);
+
+        env.define("qi:*",
+            kleene_composite<Fragments>(fragments), 1, true);
+
+        env.define("qi:-",
+            difference_composite<Fragments>(fragments), 2, true);
     }
 }}
 
@@ -208,16 +309,19 @@
 
     {
         utree src =
-            "(define r (qi:char_ \"x\"))"
-            "(define r2 (qi:int_))";
+            "(define charx (qi:char_ \"x\"))"
+            "(define integer (qi:int_))"
+            "(define int_not_0 (qi:- (qi:int_) (qi:char_ \"0\")))"
+            "(define integers (qi:* (qi:int_)))";
         interpreter parser(src, "parse.scm", &env);
 
-        BOOST_TEST(test("x", fragments.get_rule(parser["r"]()), space));
-        BOOST_TEST(!test("y", fragments.get_rule(parser["r"]()), space));
-        BOOST_TEST(test("1234", fragments.get_rule(parser["r2"]()), space));
-        BOOST_TEST(!test("x1234", fragments.get_rule(parser["r2"]()), space));
-
-
+        BOOST_TEST(test("x",        fragments[parser["charx"]()],       space));
+        BOOST_TEST(!test("y",       fragments[parser["charx"]()],       space));
+        BOOST_TEST(test("1234",     fragments[parser["integer"]()],     space));
+        BOOST_TEST(!test("x1234",   fragments[parser["integer"]()],     space));
+        BOOST_TEST(test("1 2 3 4",  fragments[parser["integers"]()],    space));
+        BOOST_TEST(test("1",        fragments[parser["int_not_0"]()],   space));
+        BOOST_TEST(!test("0",       fragments[parser["int_not_0"]()],   space));
     }
 
     return boost::report_errors();