Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69337 - trunk/libs/spirit/example/qi/compiler_tutorial/calc7
From: joel_at_[hidden]
Date: 2011-02-27 11:30:54


Author: djowel
Date: 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
New Revision: 69337
URL: http://svn.boost.org/trac/boost/changeset/69337

Log:
almost working
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp | 5 +
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp | 102 +++++++++++++++++++++++++++++++++++----
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp | 41 +++++++++++++--
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp | 75 ++++++++++++++--------------
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp | 2
   7 files changed, 171 insertions(+), 58 deletions(-)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -10,6 +10,7 @@
 #include <boost/config/warning_disable.hpp>
 #include <boost/variant/recursive_variant.hpp>
 #include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
 #include <list>
 
 namespace client { namespace ast
@@ -78,6 +79,10 @@
             assignment>
>
     statement;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+ inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
 }}
 
 BOOST_FUSION_ADAPT_STRUCT(

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -8,36 +8,66 @@
 #include "vm.hpp"
 #include <boost/foreach.hpp>
 #include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <iostream>
+#include <string>
 
 namespace client
 {
- void compiler::op(int a) const
+ void program::op(int a)
     {
         code.push_back(a);
     }
 
- void compiler::op(int a, int b) const
+ void program::op(int a, int b)
     {
         code.push_back(a);
         code.push_back(b);
     }
 
- void compiler::op(int a, int b, int c) const
+ void program::op(int a, int b, int c)
     {
         code.push_back(a);
         code.push_back(b);
         code.push_back(c);
     }
 
+ int const* program::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ variables[name] = variables.size();
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
     void compiler::operator()(unsigned int x) const
     {
- op(op_int, x);
+ program.op(op_int, x);
     }
 
     void compiler::operator()(ast::variable const& x) const
     {
- // $$$ TODO $$$
- op(op_int, 555); // for now
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ // $$$ undefined variable throw exception
+ std::cout << "undefined variable: " << x.name << std::endl;
+ }
+ program.op(op_load, *p);
     }
 
     void compiler::operator()(ast::operation const& x) const
@@ -45,10 +75,10 @@
         boost::apply_visitor(*this, x.operand_);
         switch (x.operator_)
         {
- case '+': op(op_add); break;
- case '-': op(op_sub); break;
- case '*': op(op_mul); break;
- case '/': op(op_div); break;
+ case '+': program.op(op_add); break;
+ case '-': program.op(op_sub); break;
+ case '*': program.op(op_mul); break;
+ case '/': program.op(op_div); break;
             default: BOOST_ASSERT(0); break;
         }
     }
@@ -58,7 +88,7 @@
         boost::apply_visitor(*this, x.operand_);
         switch (x.sign)
         {
- case '-': op(op_neg); break;
+ case '-': program.op(op_neg); break;
             case '+': break;
             default: BOOST_ASSERT(0); break;
         }
@@ -72,5 +102,55 @@
             (*this)(oper);
         }
     }
+
+ void compiler::operator()(ast::assignment const& x) const
+ {
+ (*this)(x.rhs);
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ // $$$ undefined variable throw exception
+ std::cout << "undefined variable: " << x.lhs.name << std::endl;
+ }
+ program.op(op_store, *p);
+ }
+
+ void compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ // $$$ duplicate variable throw exception
+ std::cout << "duplicate variable: " << x.assign.lhs.name << std::endl;
+ }
+ program.add_var(x.assign.lhs.name);
+ (*this)(x.assign);
+ }
+
+ void compiler::operator()(ast::statement const& x) const
+ {
+ typedef
+ boost::variant<
+ ast::variable_declaration,
+ ast::assignment>
+ statement;
+
+ try
+ {
+ program.clear();
+
+ // op_adstk 0 for now. we'll know how many variables we'll have later
+ program.op(op_adstk, 0);
+ BOOST_FOREACH(statement const& s, x)
+ {
+ boost::apply_visitor(*this, s);
+ }
+ program[1] = program.nvars(); // now store the actual number of variables
+ }
+ catch(...)
+ {
+ program.clear();
+ }
+ }
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -9,23 +9,45 @@
 
 #include "ast.hpp"
 #include <vector>
+#include <map>
 
 namespace client
 {
     ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int const& operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
     // The Compiler
     ///////////////////////////////////////////////////////////////////////////
     struct compiler
     {
         typedef void result_type;
 
- std::vector<int>& code;
- compiler(std::vector<int>& code)
- : code(code) {}
-
- void op(int a) const;
- void op(int a, int b) const;
- void op(int a, int b, int c) const;
+ compiler(client::program& program)
+ : program(program) {}
 
         void operator()(ast::nil) const { BOOST_ASSERT(0); }
         void operator()(unsigned int x) const;
@@ -33,6 +55,11 @@
         void operator()(ast::operation const& x) const;
         void operator()(ast::signed_ const& x) const;
         void operator()(ast::expression const& x) const;
+ void operator()(ast::assignment const& x) const;
+ void operator()(ast::variable_declaration const& x) const;
+ void operator()(ast::statement const& x) const;
+
+ client::program& program;
     };
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -18,7 +18,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 // Uncomment this if you want to enable debugging
-//#define BOOST_SPIRIT_QI_DEBUG
+// #define BOOST_SPIRIT_QI_DEBUG
 ///////////////////////////////////////////////////////////////////////////////
 
 #include <boost/spirit/include/qi.hpp>

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -18,7 +18,7 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "expression.hpp"
+#include "statement.hpp"
 #include "vm.hpp"
 #include "compiler.hpp"
 
@@ -29,51 +29,52 @@
 main()
 {
     std::cout << "/////////////////////////////////////////////////////////\n\n";
- std::cout << "Expression parser...\n\n";
+ std::cout << "Statement 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::expression<iterator_type> expression;
- typedef client::ast::expression ast_expression;
- typedef client::compiler compiler;
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
 
     std::string str;
+ std::string source;
     while (std::getline(std::cin, str))
     {
- if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ if (str.empty())
             break;
+ source += str + '\n';
+ }
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source.begin();
+ iterator_type end = source.end();
 
- client::vmachine mach; // Our virtual machine
- std::vector<int> code; // Our VM code
- expression calc; // Our grammar
- ast_expression expression; // Our program (AST)
- compiler compile(code); // Our compiler
-
- 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, expression);
-
- if (r && iter == end)
- {
- std::cout << "-------------------------\n";
- std::cout << "Parsing succeeded\n";
- compile(expression);
- 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";
- }
+ client::vmachine vm; // Our virtual machine
+ client::program program; // Our VM program
+ client::statement<iterator_type> parser; // Our parser
+ client::ast::statement ast; // Our AST
+ client::compiler compile(program); // Our compiler
+
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, parser, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ compile(ast);
+ vm.execute(program());
+
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ std::cout << "-------------------------\n\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;
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -36,7 +36,7 @@
             ;
 
         variable_declaration =
- ("var" >> !(alnum | '_')) // make sure we have whole words
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
> assignment
             ;
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -38,8 +38,8 @@
         {
         }
 
- int top() const { return stack_ptr[-1]; };
         void execute(std::vector<int> const& code);
+ std::vector<int> const& get_stack() const { return stack; };
 
     private:
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk