|
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