$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r69204 - trunk/libs/spirit/example/qi/compiler_tutorial
From: joel_at_[hidden]
Date: 2011-02-23 05:54:06
Author: djowel
Date: 2011-02-23 05:54:02 EST (Wed, 23 Feb 2011)
New Revision: 69204
URL: http://svn.boost.org/trac/boost/changeset/69204
Log:
More updates
Added:
   trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/example/qi/compiler_tutorial/calc4.cpp |    15 ++++++++++++---                         
   trunk/libs/spirit/example/qi/compiler_tutorial/calc5.cpp |    15 ++++++++++++---                         
   2 files changed, 24 insertions(+), 6 deletions(-)
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc4.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc4.cpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc4.cpp	2011-02-23 05:54:02 EST (Wed, 23 Feb 2011)
@@ -34,6 +34,9 @@
 
 namespace client { namespace ast
 {
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST
+    ///////////////////////////////////////////////////////////////////////////
     struct nil {};
     struct signed_;
     struct program;
@@ -85,6 +88,9 @@
 
 namespace client { namespace ast
 {
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST Printer
+    ///////////////////////////////////////////////////////////////////////////
     struct printer
     {
         typedef void result_type;
@@ -125,6 +131,9 @@
         }
     };
 
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST evaluator
+    ///////////////////////////////////////////////////////////////////////////
     struct eval
     {
         typedef int result_type;
@@ -176,7 +185,7 @@
     namespace ascii = boost::spirit::ascii;
 
     ///////////////////////////////////////////////////////////////////////////////
-    //  Our calculator grammar
+    //  The calculator grammar
     ///////////////////////////////////////////////////////////////////////////////
     template <typename Iterator>
     struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
@@ -239,7 +248,7 @@
 
         calculator calc;        // Our grammar
         ast_program program;    // Our program (AST)
-        ast_print printer;      // Prints the program
+        ast_print print;        // Prints the program
         ast_eval eval;          // Evaluates the program
 
         std::string::const_iterator iter = str.begin();
@@ -251,7 +260,7 @@
         {
             std::cout << "-------------------------\n";
             std::cout << "Parsing succeeded\n";
-            printer(program);
+            print(program);
             std::cout << "\nResult: " << eval(program) << std::endl;
             std::cout << "-------------------------\n";
         }
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc5.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc5.cpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc5.cpp	2011-02-23 05:54:02 EST (Wed, 23 Feb 2011)
@@ -41,6 +41,9 @@
 
 namespace client { namespace ast
 {
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST
+    ///////////////////////////////////////////////////////////////////////////
     struct nil {};
     struct signed_;
     struct program;
@@ -92,6 +95,9 @@
 
 namespace client { namespace ast
 {
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST Printer
+    ///////////////////////////////////////////////////////////////////////////
     struct printer
     {
         typedef void result_type;
@@ -132,6 +138,9 @@
         }
     };
 
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST evaluator
+    ///////////////////////////////////////////////////////////////////////////
     struct eval
     {
         typedef int result_type;
@@ -276,7 +285,7 @@
     typedef std::string::const_iterator iterator_type;
     typedef client::calculator<iterator_type> calculator;
     typedef client::ast::program ast_program;
-    typedef client::ast::printer ast_print;
+    typedef client::ast::print ast_print;
     typedef client::ast::eval ast_eval;
 
     std::string str;
@@ -287,7 +296,7 @@
 
         calculator calc;        // Our grammar
         ast_program program;    // Our program (AST)
-        ast_print printer;      // Prints the program
+        ast_print print;        // Prints the program
         ast_eval eval;          // Evaluates the program
 
         std::string::const_iterator iter = str.begin();
@@ -299,7 +308,7 @@
         {
             std::cout << "-------------------------\n";
             std::cout << "Parsing succeeded\n";
-            printer(program);
+            print(program);
             std::cout << "\nResult: " << eval(program) << std::endl;
             std::cout << "-------------------------\n";
         }
Added: trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp	2011-02-23 05:54:02 EST (Wed, 23 Feb 2011)
@@ -0,0 +1,361 @@
+/*=============================================================================
+    Copyright (c) 2001-2011 Joel de Guzman
+
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Yet another calculator example! This time, we will compile to a simple
+//  virtual machine. This is actually one of the very first Spirit example
+//  circa 2000. Now, it's ported to Spirit2.
+//
+//  [ JDG April 28, 2008 : For BoostCon 2008 ]
+//  [ JDG February 18, 2011 : Pure attributes. No semantic actions. ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+    ///////////////////////////////////////////////////////////////////////////
+    //  The AST
+    ///////////////////////////////////////////////////////////////////////////
+    struct nil {};
+    struct signed_;
+    struct program;
+
+    typedef boost::variant<
+            nil
+          , unsigned int
+          , boost::recursive_wrapper<signed_>
+          , boost::recursive_wrapper<program>
+        >
+    operand;
+
+    struct signed_
+    {
+        char sign;
+        operand operand_;
+    };
+
+    struct operation
+    {
+        char operator_;
+        operand operand_;
+    };
+
+    struct program
+    {
+        operand first;
+        std::list<operation> rest;
+    };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+    client::ast::signed_,
+    (char, sign)
+    (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+    client::ast::operation,
+    (char, operator_)
+    (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+    client::ast::program,
+    (client::ast::operand, first)
+    (std::list<client::ast::operation>, rest)
+)
+
+namespace client
+{
+    ///////////////////////////////////////////////////////////////////////////
+    //  The Virtual Machine
+    ///////////////////////////////////////////////////////////////////////////
+    enum byte_code
+    {
+        op_neg,     //  negate the top stack entry
+        op_add,     //  add top two stack entries
+        op_sub,     //  subtract top two stack entries
+        op_mul,     //  multiply top two stack entries
+        op_div,     //  divide top two stack entries
+        op_int,     //  push constant integer into the stack
+    };
+
+    class vmachine
+    {
+    public:
+
+        vmachine(unsigned stackSize = 4096)
+          : stack(stackSize)
+          , stack_ptr(stack.begin())
+        {
+        }
+
+        int top() const { return stack_ptr[-1]; };
+        void execute(std::vector<int> const& code);
+
+    private:
+
+        std::vector<int> stack;
+        std::vector<int>::iterator stack_ptr;
+    };
+
+    void vmachine::execute(std::vector<int> const& code)
+    {
+        std::vector<int>::const_iterator pc = code.begin();
+        stack_ptr = stack.begin();
+
+        while (pc != code.end())
+        {
+            switch (*pc++)
+            {
+                case op_neg:
+                    stack_ptr[-1] = -stack_ptr[-1];
+                    break;
+
+                case op_add:
+                    --stack_ptr;
+                    stack_ptr[-1] += stack_ptr[0];
+                    break;
+
+                case op_sub:
+                    --stack_ptr;
+                    stack_ptr[-1] -= stack_ptr[0];
+                    break;
+
+                case op_mul:
+                    --stack_ptr;
+                    stack_ptr[-1] *= stack_ptr[0];
+                    break;
+
+                case op_div:
+                    --stack_ptr;
+                    stack_ptr[-1] /= stack_ptr[0];
+                    break;
+
+                case op_int:
+                    *stack_ptr++ = *pc++;
+                    break;
+            }
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  The Compiler
+    ///////////////////////////////////////////////////////////////////////////
+    struct compiler
+    {
+        typedef void result_type;
+
+        std::vector<int>& code;
+        compiler(std::vector<int>& code)
+          : code(code) {}
+
+        void operator()(ast::nil) const { BOOST_ASSERT(0); }
+        void operator()(unsigned int n) const
+        {
+            code.push_back(op_int);
+            code.push_back(n);
+        }
+
+        void operator()(ast::operation const& x) const
+        {
+            boost::apply_visitor(*this, x.operand_);
+            switch (x.operator_)
+            {
+                case '+': code.push_back(op_add); break;
+                case '-': code.push_back(op_sub); break;
+                case '*': code.push_back(op_mul); break;
+                case '/': code.push_back(op_div); break;
+                default: BOOST_ASSERT(0); break;
+            }
+        }
+
+        void operator()(ast::signed_ const& x) const
+        {
+            boost::apply_visitor(*this, x.operand_);
+            switch (x.sign)
+            {
+                case '-': code.push_back(op_neg); break;
+                case '+': break;
+                default: BOOST_ASSERT(0); break;
+            }
+        }
+
+        void operator()(ast::program const& x) const
+        {
+            boost::apply_visitor(*this, x.first);
+            BOOST_FOREACH(ast::operation const& oper, x.rest)
+            {
+                (*this)(oper);
+            }
+        }
+    };
+
+    namespace qi = boost::spirit::qi;
+    namespace ascii = boost::spirit::ascii;
+    using boost::phoenix::function;
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //  The error handler
+    ///////////////////////////////////////////////////////////////////////////////
+    struct error_handler_
+    {
+        template <typename, typename, typename>
+        struct result { typedef void type; };
+
+        template <typename Iterator>
+        void operator()(
+            qi::info const& what
+          , Iterator err_pos, Iterator last) const
+        {
+            std::cout
+                << "Error! Expecting "
+                << what                         // what failed?
+                << " here: \""
+                << std::string(err_pos, last)   // iterators to error-pos, end
+                << "\""
+                << std::endl
+            ;
+        }
+    };
+
+    function<error_handler_> const error_handler = error_handler_();
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //  The calculator grammar
+    ///////////////////////////////////////////////////////////////////////////////
+    template <typename Iterator>
+    struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+    {
+        calculator() : calculator::base_type(expression)
+        {
+            qi::char_type char_;
+            qi::uint_type uint_;
+            qi::_2_type _2;
+            qi::_3_type _3;
+            qi::_4_type _4;
+
+            using qi::on_error;
+            using qi::fail;
+
+            expression =
+                term
+                >> *(   (char_('+') > term)
+                    |   (char_('-') > term)
+                    )
+                ;
+
+            term =
+                factor
+                >> *(   (char_('*') > factor)
+                    |   (char_('/') > factor)
+                    )
+                ;
+
+            factor =
+                    uint_
+                |   '(' > expression > ')'
+                |   (char_('-') > factor)
+                |   (char_('+') > factor)
+                ;
+
+            // Debugging and error handling and reporting support.
+            BOOST_SPIRIT_DEBUG_NODE(expression);
+            BOOST_SPIRIT_DEBUG_NODE(term);
+            BOOST_SPIRIT_DEBUG_NODE(factor);
+
+            // Error handling
+            on_error<fail>(expression, error_handler(_4, _3, _2));
+        }
+
+        qi::rule<Iterator, ast::program(), ascii::space_type> expression;
+        qi::rule<Iterator, ast::program(), ascii::space_type> term;
+        qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Expression parser...\n\n";
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+    typedef std::string::const_iterator iterator_type;
+    typedef client::calculator<iterator_type> calculator;
+    typedef client::ast::program ast_program;
+    typedef client::compiler compiler;
+
+    std::string str;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        client::vmachine mach;  // Our virtual machine
+        std::vector<int> code;  // Our VM code
+        calculator calc;        // Our grammar
+        ast_program program;    // Our program (AST)
+        compiler compile(code); // Compiles the program
+
+        std::string::const_iterator iter = str.begin();
+        std::string::const_iterator end = str.end();
+        boost::spirit::ascii::space_type space;
+        bool r = phrase_parse(iter, end, calc, space, program);
+
+        if (r && iter == end)
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing succeeded\n";
+            compile(program);
+            mach.execute(code);
+            std::cout << "\nResult: " << mach.top() << std::endl;
+            std::cout << "-------------------------\n";
+        }
+        else
+        {
+            std::string rest(iter, end);
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing failed\n";
+            std::cout << "-------------------------\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+