$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61564 - in trunk/libs/spirit/example/scheme: scheme test test/scheme
From: joel_at_[hidden]
Date: 2010-04-25 22:02:49
Author: djowel
Date: 2010-04-25 22:02:48 EDT (Sun, 25 Apr 2010)
New Revision: 61564
URL: http://svn.boost.org/trac/boost/changeset/61564
Log:
updates
Text files modified: 
   trunk/libs/spirit/example/scheme/scheme/compiler.hpp          |    15 ++-                                     
   trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp      |   146 +++++++++++++++++++++++++++++++++++---- 
   trunk/libs/spirit/example/scheme/test/scheme/scheme_test3.cpp |    14 +++                                     
   3 files changed, 149 insertions(+), 26 deletions(-)
Modified: trunk/libs/spirit/example/scheme/scheme/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme/compiler.hpp	(original)
+++ trunk/libs/spirit/example/scheme/scheme/compiler.hpp	2010-04-25 22:02:48 EDT (Sun, 25 Apr 2010)
@@ -555,11 +555,12 @@
         interpreter(
             Source& in,
             std::string const& source_file = "",
-            environment* outer = 0)
-          : env(outer)
+            environment* envp = 0)
         {
-            if (outer == 0)
+            if (envp == 0)
                 build_basic_environment(env);
+            else
+                env = *envp;
 
             if (input::parse_sexpr_list(in, program, source_file))
             {
@@ -569,11 +570,13 @@
 
         interpreter(
             utree const& program,
-            environment* outer = 0)
-          : env(outer)
+            environment* envp = 0)
         {
-            if (outer == 0)
+            if (envp == 0)
                 build_basic_environment(env);
+            else
+                env = *envp;
+
             compile_all(program, env, flist, fragments);
         }
 
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-25 22:02:48 EDT (Sun, 25 Apr 2010)
@@ -13,7 +13,9 @@
 #include <utree/io.hpp>
 #include <boost/spirit/include/qi.hpp>
 
-namespace scheme
+#include "../../../test/qi/test.hpp"
+
+namespace scheme { namespace qi
 {
     ///////////////////////////////////////////////////////////////////////////
     // parser compiler
@@ -24,6 +26,10 @@
     typedef qi::rule<char const*> skipper_type;
     typedef qi::rule<char const*, utree(), skipper_type> rule_type;
 
+    ///////////////////////////////////////////////////////////////////////////
+    // All rule are stored here. Rules are held in the utree by its id;
+    // i.e. it's index in the vector.
+    ///////////////////////////////////////////////////////////////////////////
     template <typename Rule>
     class rule_fragments
     {
@@ -32,18 +38,21 @@
         rule_fragments() {};
 
         template <typename Expr>
-        boost::tuple<Rule const&, int>
-        new_rule(Expr const& expr)
+        int new_rule(Expr const& expr)
         {
             rules.push_back(Rule());
             rules.front() = expr;
-            return boost::tuple<Rule const&, int>(
-                rules.front(), rules.size()-1);
+            return rules.size()-1;
         }
 
         Rule const& get_rule(int id) const
         {
-            return rules[i];
+            return rules[id];
+        }
+
+        Rule const& get_rule(utree const& id) const
+        {
+            return rules[id.get<int>()];
         }
 
     private:
@@ -51,6 +60,11 @@
         std::vector<Rule> rules;
     };
 
+    ///////////////////////////////////////////////////////////////////////////
+    // Composes primitive parsers held by index. Handles the compilation of
+    // primitive (nullary) parsers such as int_, double_, alpha, space and all
+    // those that require no arguments.
+    ///////////////////////////////////////////////////////////////////////////
     struct primitive_parser_composite : composite<primitive_parser_composite>
     {
         int id;
@@ -69,43 +83,141 @@
     inline primitive_parser_composite
     make_primitive_parser_composite(Fragments& fragments, Expr const& expr)
     {
-        return primitive_parser_composite(
-            boost::get<1>(fragments.new_rule(expr)));
+        return primitive_parser_composite(fragments.new_rule(expr));
     }
 
+    ///////////////////////////////////////////////////////////////////////////
+    // Handles the compilation of char_
+    ///////////////////////////////////////////////////////////////////////////
     template <typename Fragments>
-    void build_qi_environment(Fragments& fragments, environment& env)
+    struct char_function : actor<char_function<Fragments> >
+    {
+        Fragments& fragments;
+        function a;
+        function b;
+        char_function(
+            Fragments& fragments, function const& a, function const& b)
+          : a(a), b(b), fragments(fragments)
+        {
+        }
+
+        utree eval(utree const& a) const
+        {
+            // $$$ use exceptions here $$$.
+            BOOST_ASSERT(a.which() == utree_type::string_type);
+
+            utf8_string_range a_ = a.get<utf8_string_range>();
+            if (a_.size() == 1)
+            {
+                // char_('x')
+                return fragments.new_rule(qi::char_(a_[0]));
+            }
+            else
+            {
+                // char_("some-regex")
+                return fragments.new_rule(
+                    qi::char_(std::string(a_.begin(), a_.end())));
+            }
+        }
+
+        utree eval(utree const& a, utree const& b) const
+        {
+            // $$$ use exceptions here $$$.
+            BOOST_ASSERT(a.which() == utree_type::string_type);
+            BOOST_ASSERT(b.which() == utree_type::string_type);
+
+            utf8_string_range a_ = a.get<utf8_string_range>();
+            utf8_string_range b_ = b.get<utf8_string_range>();
+            // $$$ use exceptions here $$$.
+            BOOST_ASSERT(a_.size() == 1);
+            BOOST_ASSERT(b_.size() == 1);
+
+            // char_('x', 'y')
+            return fragments.new_rule(qi::char_(a_[0], b_[0]));
+        }
+
+        utree eval(scope const& env) const
+        {
+            if (b.empty())
+                return eval(a(env));
+            else
+                return eval(a(env), b(env));
+        }
+    };
+
+    template <typename Fragments>
+    struct unary_char_composite
+      : composite<unary_char_composite<Fragments> >
+    {
+        Fragments& fragments;
+        unary_char_composite(Fragments& fragments)
+          : fragments(fragments) {}
+
+        function compose(actor_list const& elements) const
+        {
+            typedef char_function<Fragments> function_type;
+            actor_list::const_iterator i = elements.begin();
+
+            function empty;
+            function const& a = *i++;
+            function const& b = (i == elements.end())? empty : *i;
+            return function(function_type(fragments, a, b));
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Build our scheme compiler environment.
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Fragments>
+    void build_environment(Fragments& fragments, environment& env)
     {
         build_basic_environment(env);
+
         env.define("qi:space",
             make_primitive_parser_composite(fragments, qi::space), 0, true);
+
         env.define("qi:alpha",
             make_primitive_parser_composite(fragments, qi::alpha), 0, true);
+
         env.define("qi:int_",
             make_primitive_parser_composite(fragments, qi::int_), 0, true);
+
+        env.define("qi:char_",
+            unary_char_composite<Fragments>(fragments), 1, false);
     }
-}
+}}
 
 ///////////////////////////////////////////////////////////////////////////////
 //  Main program
 ///////////////////////////////////////////////////////////////////////////////
 int main()
 {
+    using scheme::utree;
     using scheme::interpreter;
     using scheme::environment;
-    using scheme::build_qi_environment;
-    using scheme::rule_fragments;
-    using scheme::rule_type;
-    using scheme::utree;
+    using scheme::qi::build_environment;
+    using scheme::qi::rule_fragments;
+    using scheme::qi::rule_type;
+    using spirit_test::test;
 
     environment env;
     rule_fragments<rule_type> fragments;
-    build_qi_environment(fragments, env);
+    build_environment(fragments, env);
+
+    scheme::qi::skipper_type space = boost::spirit::qi::space;
 
     {
-        utree src = "(define foo 123)";
+        utree src =
+            "(define r (qi:char_ \"x\"))"
+            "(define r2 (qi:int_))";
         interpreter parser(src, "parse.scm", &env);
-        std::cout << parser["qi:int_"]() << std::endl;
+        //~ std::cout << parser["r"]() << std::endl;
+        //~ std::cout << parser["r2"]() << std::endl;
+
+        BOOST_TEST(test("x", fragments.get_rule(parser["r"]()), space));
+        BOOST_TEST(!test("y", fragments.get_rule(parser["r"]()), space));
+
+
     }
 
     return boost::report_errors();
Modified: trunk/libs/spirit/example/scheme/test/scheme/scheme_test3.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/scheme/scheme_test3.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/scheme/scheme_test3.cpp	2010-04-25 22:02:48 EDT (Sun, 25 Apr 2010)
@@ -20,9 +20,17 @@
     using scheme::interpreter;
     using scheme::utree;
 
-    utree src = "(define (factorial n) (if (<= n 0) 1 (* n (factorial (- n 1)))))";
-    scheme::interpreter program(src);
-    BOOST_TEST(program["factorial"](10) == 3628800);
+    {
+        utree src = "(define n 123)";
+        scheme::interpreter program(src);
+        BOOST_TEST(program["n"]() == 123);
+    }
+
+    {
+        utree src = "(define (factorial n) (if (<= n 0) 1 (* n (factorial (- n 1)))))";
+        scheme::interpreter program(src);
+        BOOST_TEST(program["factorial"](10) == 3628800);
+    }
 
     return boost::report_errors();
 }