Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73455 - trunk/libs/spirit/example/qi/compiler_tutorial/conjure3
From: joel_at_[hidden]
Date: 2011-07-30 20:57:20


Author: djowel
Date: 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
New Revision: 73455
URL: http://svn.boost.org/trac/boost/changeset/73455

Log:
made assignment an expression as in C/C++. Back-end is unstable (WIP).
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp | 30 ++++++++++++------------
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp | 49 +++++++++++++++++++++++++--------------
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp | 43 ++++++++++++++++++++++++----------
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp | 2 +
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp | 2 +
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp | 15 ++++++++++++
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp | 15 ++++++++---
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp | 22 ++++++++--------
   12 files changed, 121 insertions(+), 65 deletions(-)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -21,36 +21,36 @@
     // program is being compiled.
     ///////////////////////////////////////////////////////////////////////////////
     struct set_annotation_id
- {
- typedef void result_type;
+ {
+ typedef void result_type;
 
- int id;
+ int id;
         set_annotation_id(int id) : id(id) {}
 
- void operator()(ast::function_call& x) const
- {
- x.function_name.id = id;
- }
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
 
         template <typename T>
         void dispatch(T& x, boost::mpl::true_) const
- {
- x.id = id;
- }
+ {
+ x.id = id;
+ }
 
- template <typename T>
+ template <typename T>
         void dispatch(T& x, boost::mpl::false_) const
         {
             // no-op
         }
 
         template <typename T>
- void operator()(T& x) const
- {
+ void operator()(T& x) const
+ {
             typename boost::is_base_of<ast::tagged, T> is_tagged;
             dispatch(x, is_tagged);
- }
- };
+ }
+ };
 
     struct get_annotation_id
     {

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -41,24 +41,18 @@
         std::string name;
     };
 
- struct literal : tagged
- {
- // tell spirit that this is an adapted variant
- struct adapted_variant;
-
- typedef boost::variant<
+ struct literal :
+ tagged,
+ boost::spirit::adapted_variant<
             nil
           , bool
           , unsigned int>
- variant_type;
-
- typedef variant_type::types types;
-
- literal() : val() {}
- literal(bool val) : val(val) {}
- literal(unsigned int val) : val(val) {}
-
- variant_type val;
+ {
+ literal() : base_type() {}
+ literal(bool val) : base_type(val) {}
+ literal(unsigned int val) : base_type(val) {}
+ literal(literal const& rhs)
+ : base_type(rhs.get()) {}
     };
 
     typedef boost::variant<
@@ -89,15 +83,31 @@
         std::list<expression> args;
     };
 
- struct expression
+ struct binary
     {
         operand first;
         std::list<operation> rest;
     };
 
+ struct assignment;
+
+ struct expression :
+ boost::spirit::adapted_variant<
+ nil
+ , boost::recursive_wrapper<assignment>
+ , binary>
+ {
+ expression() : base_type() {}
+ expression(assignment const& val) : base_type(val) {}
+ expression(binary const& val) : base_type(val) {}
+ expression(expression const& rhs)
+ : base_type(rhs.get()) {}
+ };
+
     struct assignment
     {
         identifier lhs;
+ token_ids::type operator_;
         expression rhs;
     };
 
@@ -112,9 +122,11 @@
     struct statement_list;
     struct return_statement;
 
+ typedef boost::optional<expression> expression_statement;
+
     typedef boost::variant<
             variable_declaration
- , assignment
+ , expression_statement
           , boost::recursive_wrapper<if_statement>
           , boost::recursive_wrapper<while_statement>
           , boost::recursive_wrapper<return_statement>
@@ -183,7 +195,7 @@
 )
 
 BOOST_FUSION_ADAPT_STRUCT(
- client::ast::expression,
+ client::ast::binary,
     (client::ast::operand, first)
     (std::list<client::ast::operation>, rest)
 )
@@ -197,6 +209,7 @@
 BOOST_FUSION_ADAPT_STRUCT(
     client::ast::assignment,
     (client::ast::identifier, lhs)
+ (client::token_ids::type, operator_)
     (client::ast::expression, rhs)
 )
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -50,7 +50,7 @@
 
     llvm::Value* compiler::operator()(ast::literal const& x)
     {
- return boost::apply_visitor(*this, x.val);
+ return boost::apply_visitor(*this, x.get());
     }
 
     llvm::Value* compiler::operator()(ast::identifier const& x)
@@ -230,7 +230,7 @@
         return lhs;
     }
 
- llvm::Value* compiler::operator()(ast::expression const& x)
+ llvm::Value* compiler::operator()(ast::binary const& x)
     {
         llvm::Value* lhs = boost::apply_visitor(*this, x.first);
         if (lhs == 0)
@@ -239,21 +239,28 @@
         return compile_expression(0, lhs, rest_begin, x.rest.end());
     }
 
+ llvm::Value* compiler::operator()(ast::expression const& x)
+ {
+ return boost::apply_visitor(*this, x.get());
+ }
+
     llvm::Value* compiler::operator()(ast::assignment const& x)
     {
- llvm::Value* lhs = named_values[x.lhs.name];
- if (lhs == 0)
- {
- error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
- return 0;
- }
+ //~ llvm::Value* lhs = named_values[x.lhs.name];
+ //~ if (lhs == 0)
+ //~ {
+ //~ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ //~ return 0;
+ //~ }
+
+ //~ llvm::Value* rhs = (*this)(x.rhs);
+ //~ if (rhs == 0)
+ //~ return 0;
 
- llvm::Value* rhs = (*this)(x.rhs);
- if (rhs == 0)
- return 0;
+ //~ builder.CreateStore(rhs, lhs);
+ //~ return rhs;
 
- builder.CreateStore(rhs, lhs);
- return rhs;
+ return 0;
     }
 
     // Create an alloca instruction in the entry block of
@@ -322,6 +329,16 @@
         return true;
     }
 
+ bool compiler::operator()(ast::expression_statement const& x)
+ {
+ if (x)
+ {
+ if ((*this)(*x) == 0)
+ return false;
+ }
+ return true;
+ }
+
     bool compiler::operator()(ast::if_statement const& x)
     {
         llvm::Value* condition = (*this)(x.condition);

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -62,12 +62,14 @@
         llvm::Value* operator()(ast::identifier const& x);
         llvm::Value* operator()(ast::unary const& x);
         llvm::Value* operator()(ast::function_call const& x);
+ llvm::Value* operator()(ast::binary const& x);
         llvm::Value* operator()(ast::expression const& x);
         llvm::Value* operator()(ast::assignment const& x);
 
         bool operator()(ast::variable_declaration const& x);
         bool operator()(ast::statement_list const& x);
         bool operator()(ast::statement const& x);
+ bool operator()(ast::expression_statement const& x);
         bool operator()(ast::if_statement const& x);
         bool operator()(ast::while_statement const& x);
         bool operator()(ast::return_statement const& x);

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -46,6 +46,8 @@
         Lexer const& lexer;
 
         qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::assignment()> assign_expr;
+ qi::rule<Iterator, ast::binary()> binary_expr;
         qi::rule<Iterator, ast::operand()> unary_expr, primary_expr;
         qi::rule<Iterator, ast::function_call()> function_call;
         qi::rule<Iterator, std::list<ast::expression>()> argument_list;

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -39,7 +39,19 @@
 
         ///////////////////////////////////////////////////////////////////////
         // Main expression grammar
+
         expr =
+ assign_expr
+ | binary_expr
+ ;
+
+ assign_expr =
+ identifier
+ >> tokenid_mask(token_ids::op_assign)
+ >> expr
+ ;
+
+ binary_expr =
                 unary_expr
>> *(tokenid_mask(token_ids::op_binary) > unary_expr)
             ;
@@ -75,8 +87,11 @@
         // Debugging and error handling and reporting support.
         BOOST_SPIRIT_DEBUG_NODES(
             (expr)
+ (assign_expr)
+ (binary_expr)
             (unary_expr)
             (primary_expr)
+ (literal)
             (function_call)
             (argument_list)
             (identifier)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -79,7 +79,7 @@
 
     template <op::type op>
     struct assign_op
- : make_op<op_type::binary | op_type::assign, op> {};
+ : make_op<op_type::assign, op> {};
 
     template <op::type op>
     struct binary_or_unary_op

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -14,4 +14,4 @@
 typedef std::string::const_iterator base_iterator_type;
 template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();
 template bool client::lexer::conjure_tokens<base_iterator_type>::add_keyword(
- std::string const&);
+ std::string const&, int);

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -87,7 +87,7 @@
 
     protected:
         // add a keyword to the mapping table
- bool add_keyword(std::string const& keyword);
+ bool add_keyword(std::string const& keyword, int id = token_ids::invalid);
 
     public:
         typedef BaseIterator base_iterator_type;

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -26,6 +26,8 @@
         add_keyword("while");
         add_keyword("return");
 
+ add_keyword("=", token_ids::assign);
+
         this->self.add
                 ("\\|\\|", token_ids::logical_or)
                 ("&&", token_ids::logical_and)
@@ -42,7 +44,7 @@
                 ("!", token_ids::not_)
             ;
 
- this->self += lex::char_('(') | ')' | '{' | '}' | ',' | '=' | ';';
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | ';';
 
         this->self +=
                 identifier
@@ -58,12 +60,17 @@
     }
 
     template <typename BaseIterator>
- bool conjure_tokens<BaseIterator>::add_keyword(std::string const& keyword)
+ bool conjure_tokens<BaseIterator>::add_keyword(
+ std::string const& keyword, int id_)
     {
         // add the token to the lexer
- token_ids::type id = token_ids::type(this->get_next_id());
- this->self.add(keyword, id);
+ token_ids::type id;
+ if (id_ == token_ids::invalid)
+ id = token_ids::type(this->get_next_id());
+ else
+ id = token_ids::type(id_);
 
+ this->self.add(keyword, id);
         // store the mapping for later retrieval
         std::pair<typename keyword_map_type::iterator, bool> p =
             keywords_.insert(typename keyword_map_type::value_type(keyword, id));

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -30,7 +30,7 @@
 
         qi::rule<Iterator, ast::statement()> statement_;
         qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
- qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::expression_statement()> expr_statement;
         qi::rule<Iterator, ast::if_statement()> if_statement;
         qi::rule<Iterator, ast::while_statement()> while_statement;
         qi::rule<Iterator, ast::return_statement()> return_statement;

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp 2011-07-30 20:57:18 EDT (Sat, 30 Jul 2011)
@@ -41,8 +41,8 @@
 
         statement_ =
                 variable_declaration
- | assignment
             | compound_statement
+ | expr_statement
             | if_statement
             | while_statement
             | return_statement
@@ -51,15 +51,12 @@
         variable_declaration =
                 l("int")
> expr.identifier
- > -('=' > expr)
+ > -(l("=") > expr.binary_expr)
> ';'
             ;
 
- assignment =
- expr.identifier
- > '='
- > expr
- > ';'
+ expr_statement =
+ ';' | (expr > ';')
             ;
 
         if_statement =
@@ -96,8 +93,13 @@
         // Debugging and error handling and reporting support.
         BOOST_SPIRIT_DEBUG_NODES(
             (statement_list)
+ (statement_)
             (variable_declaration)
- (assignment)
+ (expr_statement)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
         );
 
         // Error handling: on error in statement_list, call error_handler.
@@ -105,9 +107,7 @@
             error_handler_function(error_handler)(
                 "Error! Expecting ", _4, _3));
 
- // Annotation: on success in assignment, call annotation.
- on_success(assignment,
- annotation_function(error_handler.iters)(_val, _1));
+ // Annotation: on success in return_statement, call annotation.
         on_success(return_statement,
             annotation_function(error_handler.iters)(_val, _1));
     }


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