Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69323 - in trunk/libs/spirit/example/qi/compiler_tutorial: . calc7
From: joel_at_[hidden]
Date: 2011-02-27 06:58:22


Author: djowel
Date: 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
New Revision: 69323
URL: http://svn.boost.org/trac/boost/changeset/69323

Log:
statement grammar plus various updates
Added:
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp (contents, props changed)
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/Jamfile | 1
   trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp | 32 +++++++++++-----------
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp | 25 +++++++++++++-----
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp | 55 ++++++++++++++++++++++++++++++---------
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp | 31 +++++++++++++++++++--
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp | 9 ++++--
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp | 14 +++++-----
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp | 16 ++++++++--
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp | 16 +++++-----
   9 files changed, 137 insertions(+), 62 deletions(-)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/Jamfile
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/Jamfile (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/Jamfile 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -23,6 +23,7 @@
     calc7/vm.cpp
     calc7/compiler.cpp
     calc7/expression.cpp
+ calc7/statement.cpp
     calc7/main.cpp
     ;
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc6.cpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -49,13 +49,13 @@
     ///////////////////////////////////////////////////////////////////////////
     struct nil {};
     struct signed_;
- struct program;
+ struct expression;
 
     typedef boost::variant<
             nil
           , unsigned int
           , boost::recursive_wrapper<signed_>
- , boost::recursive_wrapper<program>
+ , boost::recursive_wrapper<expression>
>
     operand;
 
@@ -71,7 +71,7 @@
         operand operand_;
     };
 
- struct program
+ struct expression
     {
         operand first;
         std::list<operation> rest;
@@ -91,7 +91,7 @@
 )
 
 BOOST_FUSION_ADAPT_STRUCT(
- client::ast::program,
+ client::ast::expression,
     (client::ast::operand, first)
     (std::list<client::ast::operation>, rest)
 )
@@ -212,7 +212,7 @@
             }
         }
 
- void operator()(ast::program const& x) const
+ void operator()(ast::expression const& x) const
         {
             boost::apply_visitor(*this, x.first);
             BOOST_FOREACH(ast::operation const& oper, x.rest)
@@ -256,7 +256,7 @@
     // The calculator grammar
     ///////////////////////////////////////////////////////////////////////////////
     template <typename Iterator>
- struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ struct calculator : qi::grammar<Iterator, ast::expression(), ascii::space_type>
     {
         calculator() : calculator::base_type(expression)
         {
@@ -298,8 +298,8 @@
             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::expression(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> term;
         qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
     };
 }
@@ -317,7 +317,7 @@
 
     typedef std::string::const_iterator iterator_type;
     typedef client::calculator<iterator_type> calculator;
- typedef client::ast::program ast_program;
+ typedef client::ast::expression ast_expression;
     typedef client::compiler compiler;
 
     std::string str;
@@ -326,22 +326,22 @@
         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
+ client::vmachine mach; // Our virtual machine
+ std::vector<int> code; // Our VM code
+ calculator calc; // Our grammar
+ ast_expression expression; // 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);
+ bool r = phrase_parse(iter, end, calc, space, expression);
 
         if (r && iter == end)
         {
             std::cout << "-------------------------\n";
             std::cout << "Parsing succeeded\n";
- compile(program);
+ compile(expression);
             mach.execute(code);
             std::cout << "\nResult: " << mach.top() << std::endl;
             std::cout << "-------------------------\n";

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -24,10 +24,9 @@
         template <typename, typename>
         struct result { typedef void type; };
 
- std::map<int, Iterator>& iters;
- int& current_id;
- annotation(int& current_id, std::map<int, Iterator>& iters)
- : current_id(current_id), iters(iters) {}
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
 
         struct set_id
         {
@@ -36,19 +35,31 @@
             int id;
             set_id(int id) : id(id) {}
 
+ void operator()(ast::tagged& x) const
+ {
+ x.id = id;
+ }
+
             template <typename T>
             void operator()(T& x) const
             {
- x.id = id;
+ // no need for tags
             }
         };
 
         void operator()(ast::operand& ast, Iterator pos) const
         {
- int id = current_id++;
- iters[id] = pos;
+ int id = iters.size();
+ iters.push_back(pos);
             boost::apply_visitor(set_id(id), ast);
         }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
     };
 }
 

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 06:58:18 EST (Sun, 27 Feb 2011)
@@ -17,49 +17,67 @@
     ///////////////////////////////////////////////////////////////////////////
     // The AST
     ///////////////////////////////////////////////////////////////////////////
- struct base
+ struct tagged
     {
         int id; // Used to annotate the AST with the iterator position.
                 // This id is used as a key to a map<int, Iterator>
                 // (not really part of the AST.)
     };
 
- struct nil : base {};
-
+ struct nil {};
     struct signed_;
- struct program;
+ struct expression;
 
- struct unsigned_ : base
+ struct variable : tagged
     {
- unsigned_(unsigned int n = 0) : n(n) {}
- unsigned int n;
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
     };
 
     typedef boost::variant<
             nil
- , unsigned_
+ , unsigned int
+ , variable
           , boost::recursive_wrapper<signed_>
- , boost::recursive_wrapper<program>
+ , boost::recursive_wrapper<expression>
>
     operand;
 
- struct signed_ : base
+ struct signed_
     {
         char sign;
         operand operand_;
     };
 
- struct operation : base
+ struct operation
     {
         char operator_;
         operand operand_;
     };
 
- struct program : base
+ struct expression
     {
         operand first;
         std::list<operation> rest;
     };
+
+ struct assignment
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ typedef std::list<
+ boost::variant<
+ variable_declaration,
+ assignment>
+ >
+ statement;
 }}
 
 BOOST_FUSION_ADAPT_STRUCT(
@@ -75,9 +93,20 @@
 )
 
 BOOST_FUSION_ADAPT_STRUCT(
- client::ast::program,
+ client::ast::expression,
     (client::ast::operand, first)
     (std::list<client::ast::operation>, rest)
 )
 
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::assignment, assign)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::variable, lhs)
+ (client::ast::expression, rhs)
+)
+
 #endif

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 06:58:18 EST (Sun, 27 Feb 2011)
@@ -11,10 +11,33 @@
 
 namespace client
 {
- void compiler::operator()(ast::unsigned_ const& x) const
+ void compiler::op(int a) const
     {
- op(op_int);
- op(x.n);
+ code.push_back(a);
+ }
+
+ void compiler::op(int a, int b) const
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void compiler::op(int a, int b, int c) const
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ void compiler::operator()(unsigned int x) const
+ {
+ op(op_int, x);
+ }
+
+ void compiler::operator()(ast::variable const& x) const
+ {
+ // $$$ TODO $$$
+ op(op_int, 555); // for now
     }
 
     void compiler::operator()(ast::operation const& x) const
@@ -41,7 +64,7 @@
         }
     }
 
- void compiler::operator()(ast::program const& x) const
+ void compiler::operator()(ast::expression const& x) const
     {
         boost::apply_visitor(*this, x.first);
         BOOST_FOREACH(ast::operation const& oper, x.rest)

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 06:58:18 EST (Sun, 27 Feb 2011)
@@ -23,13 +23,16 @@
         compiler(std::vector<int>& code)
           : code(code) {}
 
- void op(int opcode) const { code.push_back(opcode); }
+ void op(int a) const;
+ void op(int a, int b) const;
+ void op(int a, int b, int c) const;
 
         void operator()(ast::nil) const { BOOST_ASSERT(0); }
- void operator()(ast::unsigned_ const& x) const;
+ void operator()(unsigned int x) const;
+ void operator()(ast::variable const& x) const;
         void operator()(ast::operation const& x) const;
         void operator()(ast::signed_ const& x) const;
- void operator()(ast::program const& x) const;
+ void operator()(ast::expression const& x) const;
     };
 }
 

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 06:58:18 EST (Sun, 27 Feb 2011)
@@ -23,7 +23,7 @@
 
 #include <boost/spirit/include/qi.hpp>
 #include "ast.hpp"
-#include <map>
+#include <vector>
 
 namespace client
 {
@@ -34,18 +34,18 @@
     // The expression grammar
     ///////////////////////////////////////////////////////////////////////////////
     template <typename Iterator>
- struct expression : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
     {
         expression();
 
- qi::rule<Iterator, ast::program(), ascii::space_type> expr;
- qi::rule<Iterator, ast::program(), ascii::space_type> additive_expr;
- qi::rule<Iterator, ast::program(), ascii::space_type> multiplicative_expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> additive_expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> multiplicative_expr;
         qi::rule<Iterator, ast::operand(), ascii::space_type> unary_expr;
         qi::rule<Iterator, ast::operand(), ascii::space_type> primary_expr;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
 
- std::map<int, Iterator> iters;
- int current_id;
+ std::vector<Iterator> iters;
     };
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -13,7 +13,6 @@
     template <typename Iterator>
     expression<Iterator>::expression()
       : expression::base_type(expr)
- , current_id(0)
     {
         qi::char_type char_;
         qi::uint_type uint_;
@@ -21,6 +20,10 @@
         qi::_2_type _2;
         qi::_3_type _3;
         qi::_4_type _4;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
 
         using qi::on_error;
         using qi::on_success;
@@ -51,10 +54,15 @@
             ;
 
         primary_expr =
- uint_
+ uint_
+ | identifier
             | '(' > expr > ')'
             ;
 
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
         // Debugging and error handling and reporting support.
         BOOST_SPIRIT_DEBUG_NODES(
             (expr)
@@ -62,6 +70,7 @@
             (multiplicative_expr)
             (unary_expr)
             (primary_expr)
+ (identifier)
         );
 
         // Error handling: on error in expr, call error_handler.
@@ -70,9 +79,8 @@
         // Annotation: on success in primary_expr, call annotation.
         typedef client::annotation<Iterator> annotation_;
         typename function<annotation_>
- annotation = annotation_(current_id, iters);
+ annotation = annotation_(iters);
         on_success(primary_expr, annotation(_val, _3));
- on_success(unary_expr, annotation(_val, _3));
     }
 }
 

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 06:58:18 EST (Sun, 27 Feb 2011)
@@ -35,7 +35,7 @@
 
     typedef std::string::const_iterator iterator_type;
     typedef client::expression<iterator_type> expression;
- typedef client::ast::program ast_program;
+ typedef client::ast::expression ast_expression;
     typedef client::compiler compiler;
 
     std::string str;
@@ -44,22 +44,22 @@
         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
             break;
 
- client::vmachine mach; // Our virtual machine
- std::vector<int> code; // Our VM code
- expression calc; // Our grammar
- ast_program program; // Our program (AST)
- compiler compile(code); // Our compiler
+ 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, program);
+ bool r = phrase_parse(iter, end, calc, space, expression);
 
         if (r && iter == end)
         {
             std::cout << "-------------------------\n";
             std::cout << "Parsing succeeded\n";
- compile(program);
+ compile(expression);
             mach.execute(code);
             std::cout << "\nResult: " << mach.top() << std::endl;
             std::cout << "-------------------------\n";

Added: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -0,0 +1,10 @@
+/*=============================================================================
+ 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)
+=============================================================================*/
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::statement<iterator_type>;

Added: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -0,0 +1,39 @@
+/*=============================================================================
+ 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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_STATEMENT_HPP)
+#define BOOST_SPIRIT_CALC7_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement(), ascii::space_type>
+ {
+ statement();
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement(), ascii::space_type> start;
+ qi::rule<Iterator, ast::variable_declaration(), ascii::space_type> variable_declaration;
+ qi::rule<Iterator, ast::assignment(), ascii::space_type> assignment;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+
+
+ //~ variable_declaration;
+ //~ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ //~ qi::rule<Iterator, int(), ascii::space_type> var_ref;
+ //~ qi::rule<Iterator, qi::locals<int>, ascii::space_type> assignment;
+ //~ qi::rule<Iterator, void(int), ascii::space_type> assignment_rhs;
+ };
+}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp 2011-02-27 06:58:18 EST (Sun, 27 Feb 2011)
@@ -0,0 +1,69 @@
+/*=============================================================================
+ 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)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client
+{
+ template <typename Iterator>
+ statement<Iterator>::statement()
+ : statement::base_type(start)
+ {
+ qi::_val_type _val;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+
+ start =
+ +(variable_declaration | assignment)
+ ;
+
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ ("var" >> !(alnum | '_')) // make sure we have whole words
+ > assignment
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (start)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start, error_handler(_4, _3, _2));
+
+ // Annotation: on success in variable, call annotation.
+ typedef client::annotation<Iterator> annotation_;
+ typename function<annotation_>
+ annotation = annotation_(expr.iters);
+ on_success(assignment, annotation(_val, _3));
+ }
+}
+
+


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