Support procedures returning values
This commit is contained in:
parent
a79def50e5
commit
7b36a3803f
@ -40,10 +40,18 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
return "pointer";
|
return "pointer";
|
||||||
}
|
}
|
||||||
else if (is_array_type(type))
|
else if (TREE_CODE(type) == ARRAY_TYPE)
|
||||||
{
|
{
|
||||||
return "array";
|
return "array";
|
||||||
}
|
}
|
||||||
|
else if (TREE_CODE(type) == RECORD_TYPE)
|
||||||
|
{
|
||||||
|
return "record";
|
||||||
|
}
|
||||||
|
else if (TREE_CODE(type) == UNION_TYPE)
|
||||||
|
{
|
||||||
|
return "union";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return "<<unknown-type>>";
|
return "<<unknown-type>>";
|
||||||
|
@ -20,7 +20,7 @@ namespace gcc
|
|||||||
this->symbol_map = symbol_table;
|
this->symbol_map = symbol_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::call_statement *statement)
|
void generic_visitor::visit(source::call_expression *statement)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup(statement->name());
|
auto symbol = this->symbol_map->lookup(statement->name());
|
||||||
|
|
||||||
@ -87,7 +87,8 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
else if (symbol)
|
else if (symbol)
|
||||||
{
|
{
|
||||||
tree fndecl_type = build_function_type(void_type_node, TYPE_ARG_TYPES(symbol->payload));
|
tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
|
||||||
|
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
|
||||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
||||||
|
|
||||||
std::vector<tree> arguments(statement->arguments().size());
|
std::vector<tree> arguments(statement->arguments().size());
|
||||||
@ -97,12 +98,19 @@ namespace gcc
|
|||||||
arguments[i] = this->current_expression;
|
arguments[i] = this->current_expression;
|
||||||
}
|
}
|
||||||
tree stmt = build_call_array_loc(get_location(&statement->position()),
|
tree stmt = build_call_array_loc(get_location(&statement->position()),
|
||||||
void_type_node, printf_fn, arguments.size(), arguments.data());
|
return_type, printf_fn, arguments.size(), arguments.data());
|
||||||
|
|
||||||
|
if (return_type == void_type_node)
|
||||||
|
{
|
||||||
append_to_statement_list(stmt, &this->current_statements);
|
append_to_statement_list(stmt, &this->current_statements);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = stmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
error_at(get_location(&statement->position()),
|
error_at(get_location(&statement->position()),
|
||||||
"procedure '%s' not declared",
|
"procedure '%s' not declared",
|
||||||
@ -126,9 +134,6 @@ namespace gcc
|
|||||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
||||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||||
DECL_RESULT(this->main_fndecl) = resdecl;
|
DECL_RESULT(this->main_fndecl) = resdecl;
|
||||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
|
|
||||||
build_int_cst_type(integer_type_node, 0));
|
|
||||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
|
||||||
|
|
||||||
enter_scope();
|
enter_scope();
|
||||||
|
|
||||||
@ -140,6 +145,9 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
body_statement->accept(this);
|
body_statement->accept(this);
|
||||||
}
|
}
|
||||||
|
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
|
||||||
|
build_int_cst_type(integer_type_node, 0));
|
||||||
|
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||||
append_to_statement_list(return_stmt, &this->current_statements);
|
append_to_statement_list(return_stmt, &this->current_statements);
|
||||||
tree_symbol_mapping mapping = leave_scope();
|
tree_symbol_mapping mapping = leave_scope();
|
||||||
|
|
||||||
@ -163,15 +171,17 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
parameter_types[i] = build_type(definition->parameters.at(i)->type());
|
parameter_types[i] = build_type(definition->parameters.at(i)->type());
|
||||||
}
|
}
|
||||||
tree declaration_type = build_function_type_array(void_type_node,
|
tree return_type = definition->return_type() == nullptr
|
||||||
|
? void_type_node
|
||||||
|
: build_type(*definition->return_type());
|
||||||
|
tree declaration_type = build_function_type_array(return_type,
|
||||||
definition->parameters.size(), parameter_types.data());
|
definition->parameters.size(), parameter_types.data());
|
||||||
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
||||||
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
|
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
|
||||||
|
|
||||||
if (definition->body() != nullptr)
|
if (definition->body() != nullptr)
|
||||||
{
|
{
|
||||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL,
|
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
||||||
NULL_TREE, TREE_TYPE(TREE_TYPE(this->main_fndecl)));
|
|
||||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||||
DECL_RESULT(this->main_fndecl) = resdecl;
|
DECL_RESULT(this->main_fndecl) = resdecl;
|
||||||
|
|
||||||
@ -454,7 +464,7 @@ namespace gcc
|
|||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||||
get_identifier(definition->identifier().c_str()), tree_type);
|
get_identifier(definition->identifier().c_str()), tree_type);
|
||||||
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree));
|
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(tree_type));
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -477,31 +487,11 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
if (source::basic_type_expression *basic_type = type.is_basic())
|
if (source::basic_type_expression *basic_type = type.is_basic())
|
||||||
{
|
{
|
||||||
if (basic_type->base_name() == "Int")
|
|
||||||
{
|
|
||||||
return integer_type_node;
|
|
||||||
}
|
|
||||||
else if (basic_type->base_name() == "Bool")
|
|
||||||
{
|
|
||||||
return boolean_type_node;
|
|
||||||
}
|
|
||||||
else if (basic_type->base_name() == "Float")
|
|
||||||
{
|
|
||||||
return double_type_node;
|
|
||||||
}
|
|
||||||
else if (basic_type->base_name() == "Char")
|
|
||||||
{
|
|
||||||
return elna_char_type_node;
|
|
||||||
}
|
|
||||||
else if (basic_type->base_name() == "String")
|
|
||||||
{
|
|
||||||
return elna_string_type_node;
|
|
||||||
}
|
|
||||||
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||||
|
|
||||||
if (symbol)
|
if (symbol && TYPE_P(symbol->payload))
|
||||||
{
|
{
|
||||||
return TREE_TYPE(symbol->payload);
|
return symbol->payload;
|
||||||
}
|
}
|
||||||
error_at(get_location(&basic_type->position()),
|
error_at(get_location(&basic_type->position()),
|
||||||
"type '%s' not declared", basic_type->base_name().c_str());
|
"type '%s' not declared", basic_type->base_name().c_str());
|
||||||
@ -844,5 +834,26 @@ namespace gcc
|
|||||||
|
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::expression_statement *statement)
|
||||||
|
{
|
||||||
|
statement->body().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::return_statement *statement)
|
||||||
|
{
|
||||||
|
source::expression *return_expression = statement->return_expression();
|
||||||
|
|
||||||
|
if (return_expression == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return_expression->accept(this);
|
||||||
|
|
||||||
|
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
|
||||||
|
this->current_expression);
|
||||||
|
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||||
|
append_to_statement_list(return_stmt, &this->current_statements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,6 @@ namespace gcc
|
|||||||
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_array_type(tree type)
|
|
||||||
{
|
|
||||||
gcc_assert(TYPE_P(type));
|
|
||||||
return TREE_CODE(type) == ARRAY_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
tree tree_chain_base::head()
|
tree tree_chain_base::head()
|
||||||
{
|
{
|
||||||
return first;
|
return first;
|
||||||
@ -76,7 +70,16 @@ namespace gcc
|
|||||||
|
|
||||||
std::shared_ptr<elna::source::symbol_table<tree>> builtin_symbol_table()
|
std::shared_ptr<elna::source::symbol_table<tree>> builtin_symbol_table()
|
||||||
{
|
{
|
||||||
return std::make_shared<elna::source::symbol_table<tree>>();
|
std::shared_ptr<elna::source::symbol_table<tree>> initial_table =
|
||||||
|
std::make_shared<elna::source::symbol_table<tree>>();
|
||||||
|
|
||||||
|
initial_table->enter("Int", source::make_info(integer_type_node));
|
||||||
|
initial_table->enter("Bool", source::make_info(boolean_type_node));
|
||||||
|
initial_table->enter("Float", source::make_info(double_type_node));
|
||||||
|
initial_table->enter("Char", source::make_info(elna_char_type_node));
|
||||||
|
initial_table->enter("String", source::make_info(elna_string_type_node));
|
||||||
|
|
||||||
|
return initial_table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ static void elna_parse_file(const char *filename)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elna::gcc::generic_visitor generic_visitor;
|
elna::gcc::generic_visitor generic_visitor{ elna::gcc::builtin_symbol_table() };
|
||||||
|
|
||||||
generic_visitor.visit(driver.tree.get());
|
generic_visitor.visit(driver.tree.get());
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ namespace gcc
|
|||||||
|
|
||||||
void visit(source::program *program) override;
|
void visit(source::program *program) override;
|
||||||
void visit(source::procedure_definition *definition) override;
|
void visit(source::procedure_definition *definition) override;
|
||||||
void visit(source::call_statement *statement) override;
|
void visit(source::call_expression *statement) override;
|
||||||
void visit(source::number_literal<std::int32_t> *literal) override;
|
void visit(source::number_literal<std::int32_t> *literal) override;
|
||||||
void visit(source::number_literal<double> *literal) override;
|
void visit(source::number_literal<double> *literal) override;
|
||||||
void visit(source::number_literal<bool> *boolean) override;
|
void visit(source::number_literal<bool> *boolean) override;
|
||||||
@ -57,6 +57,8 @@ namespace gcc
|
|||||||
void visit(source::assign_statement *statement) override;
|
void visit(source::assign_statement *statement) override;
|
||||||
void visit(source::if_statement *statement) override;
|
void visit(source::if_statement *statement) override;
|
||||||
void visit(source::while_statement *statement) override;
|
void visit(source::while_statement *statement) override;
|
||||||
|
void visit(source::expression_statement *statement) override;
|
||||||
|
void visit(source::return_statement *statement) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
|
||||||
|
#include "elna/source/symbol.h"
|
||||||
|
|
||||||
enum elna_tree_index
|
enum elna_tree_index
|
||||||
{
|
{
|
||||||
ELNA_TI_CHAR_TYPE,
|
ELNA_TI_CHAR_TYPE,
|
||||||
@ -25,7 +27,6 @@ namespace gcc
|
|||||||
void init_ttree();
|
void init_ttree();
|
||||||
bool is_pointer_type(tree type);
|
bool is_pointer_type(tree type);
|
||||||
bool is_string_type(tree type);
|
bool is_string_type(tree type);
|
||||||
bool is_array_type(tree type);
|
|
||||||
|
|
||||||
class tree_chain_base
|
class tree_chain_base
|
||||||
{
|
{
|
||||||
@ -58,6 +59,6 @@ namespace gcc
|
|||||||
tree block();
|
tree block();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<elna::source::symbol_table<tree>> builtin_symbol_table();
|
std::shared_ptr<source::symbol_table<tree>> builtin_symbol_table();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,13 @@ namespace source
|
|||||||
class constant_definition;
|
class constant_definition;
|
||||||
class procedure_definition;
|
class procedure_definition;
|
||||||
class type_definition;
|
class type_definition;
|
||||||
class call_statement;
|
class call_expression;
|
||||||
class compound_statement;
|
class compound_statement;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
class while_statement;
|
class while_statement;
|
||||||
|
class return_statement;
|
||||||
|
class expression_statement;
|
||||||
class block;
|
class block;
|
||||||
class program;
|
class program;
|
||||||
class binary_expression;
|
class binary_expression;
|
||||||
@ -71,11 +73,13 @@ namespace source
|
|||||||
virtual void visit(constant_definition *) = 0;
|
virtual void visit(constant_definition *) = 0;
|
||||||
virtual void visit(procedure_definition *) = 0;
|
virtual void visit(procedure_definition *) = 0;
|
||||||
virtual void visit(type_definition *) = 0;
|
virtual void visit(type_definition *) = 0;
|
||||||
virtual void visit(call_statement *) = 0;
|
virtual void visit(call_expression *) = 0;
|
||||||
|
virtual void visit(expression_statement *) = 0;
|
||||||
virtual void visit(compound_statement *) = 0;
|
virtual void visit(compound_statement *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
virtual void visit(if_statement *) = 0;
|
virtual void visit(if_statement *) = 0;
|
||||||
virtual void visit(while_statement *) = 0;
|
virtual void visit(while_statement *) = 0;
|
||||||
|
virtual void visit(return_statement *) = 0;
|
||||||
virtual void visit(block *) = 0;
|
virtual void visit(block *) = 0;
|
||||||
virtual void visit(program *) = 0;
|
virtual void visit(program *) = 0;
|
||||||
virtual void visit(binary_expression *) = 0;
|
virtual void visit(binary_expression *) = 0;
|
||||||
@ -105,11 +109,13 @@ namespace source
|
|||||||
virtual void visit(constant_definition *definition) override;
|
virtual void visit(constant_definition *definition) override;
|
||||||
virtual void visit(procedure_definition *definition) override;
|
virtual void visit(procedure_definition *definition) override;
|
||||||
virtual void visit(type_definition *definition) override;
|
virtual void visit(type_definition *definition) override;
|
||||||
virtual void visit(call_statement *statement) override;
|
virtual void visit(call_expression *statement) override;
|
||||||
|
virtual void visit(expression_statement *statement) override;
|
||||||
virtual void visit(compound_statement *statement) override;
|
virtual void visit(compound_statement *statement) override;
|
||||||
virtual void visit(assign_statement *statement) override;
|
virtual void visit(assign_statement *statement) override;
|
||||||
virtual void visit(if_statement *) override;
|
virtual void visit(if_statement *) override;
|
||||||
virtual void visit(while_statement *) override;
|
virtual void visit(while_statement *) override;
|
||||||
|
virtual void visit(return_statement *) override;
|
||||||
virtual void visit(block *block) override;
|
virtual void visit(block *block) override;
|
||||||
virtual void visit(program *program) override;
|
virtual void visit(program *program) override;
|
||||||
virtual void visit(binary_expression *expression) override;
|
virtual void visit(binary_expression *expression) override;
|
||||||
@ -403,6 +409,7 @@ namespace source
|
|||||||
*/
|
*/
|
||||||
class procedure_definition : public definition
|
class procedure_definition : public definition
|
||||||
{
|
{
|
||||||
|
type_expression *m_return_type{ nullptr };
|
||||||
block *m_body{ nullptr };
|
block *m_body{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -411,12 +418,16 @@ namespace source
|
|||||||
/**
|
/**
|
||||||
* \param position Source code position.
|
* \param position Source code position.
|
||||||
* \param identifier Procedure name.
|
* \param identifier Procedure name.
|
||||||
|
* \param parameters Procedure formal parameters.
|
||||||
|
* \param return_type Return type if any.
|
||||||
* \param body Procedure body.
|
* \param body Procedure body.
|
||||||
*/
|
*/
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, const std::string& identifier,
|
||||||
block *body = nullptr);
|
std::vector<variable_declaration *>&& parameters,
|
||||||
|
type_expression *return_type = nullptr, block *body = nullptr);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
type_expression *return_type();
|
||||||
block *body();
|
block *body();
|
||||||
|
|
||||||
virtual ~procedure_definition() override;
|
virtual ~procedure_definition() override;
|
||||||
@ -439,7 +450,7 @@ namespace source
|
|||||||
/**
|
/**
|
||||||
* Call statement.
|
* Call statement.
|
||||||
*/
|
*/
|
||||||
class call_statement : public statement
|
class call_expression : public expression
|
||||||
{
|
{
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::vector<expression *> m_arguments;
|
std::vector<expression *> m_arguments;
|
||||||
@ -449,16 +460,29 @@ namespace source
|
|||||||
* \param position Source code position.
|
* \param position Source code position.
|
||||||
* \param name Callable's name.
|
* \param name Callable's name.
|
||||||
*/
|
*/
|
||||||
call_statement(const struct position position, const std::string& name);
|
call_expression(const struct position position, const std::string& name);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
std::string& name();
|
std::string& name();
|
||||||
std::vector<expression *>& arguments();
|
std::vector<expression *>& arguments();
|
||||||
|
|
||||||
virtual ~call_statement() override;
|
virtual ~call_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class compound_statement : public statement
|
class expression_statement : public statement
|
||||||
|
{
|
||||||
|
expression *m_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
expression_statement(const struct position position, expression *body);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
expression& body();
|
||||||
|
|
||||||
|
virtual ~expression_statement() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class compound_statement : public node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<statement *> statements;
|
std::vector<statement *> statements;
|
||||||
@ -469,6 +493,19 @@ namespace source
|
|||||||
virtual ~compound_statement() override;
|
virtual ~compound_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class return_statement : public statement
|
||||||
|
{
|
||||||
|
expression *m_return_expression{ nullptr };
|
||||||
|
|
||||||
|
public:
|
||||||
|
return_statement(const struct position position, expression *return_expression);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
expression *return_expression();
|
||||||
|
|
||||||
|
virtual ~return_statement() override;
|
||||||
|
};
|
||||||
|
|
||||||
class designator_expression : public expression
|
class designator_expression : public expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -33,7 +33,7 @@ namespace source
|
|||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(call_statement *statement)
|
void empty_visitor::visit(call_expression *statement)
|
||||||
{
|
{
|
||||||
for (auto& argument : statement->arguments())
|
for (auto& argument : statement->arguments())
|
||||||
{
|
{
|
||||||
@ -41,6 +41,11 @@ namespace source
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(expression_statement *statement)
|
||||||
|
{
|
||||||
|
statement->body().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(compound_statement *statement)
|
void empty_visitor::visit(compound_statement *statement)
|
||||||
{
|
{
|
||||||
for (const auto nested_statement : statement->statements)
|
for (const auto nested_statement : statement->statements)
|
||||||
@ -66,6 +71,16 @@ namespace source
|
|||||||
statement->body().accept(this);
|
statement->body().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(return_statement *statement)
|
||||||
|
{
|
||||||
|
expression *return_expression = statement->return_expression();
|
||||||
|
|
||||||
|
if (return_expression != nullptr)
|
||||||
|
{
|
||||||
|
return_expression->accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(block *block)
|
void empty_visitor::visit(block *block)
|
||||||
{
|
{
|
||||||
for (const auto definition : block->value_definitions)
|
for (const auto definition : block->value_definitions)
|
||||||
@ -433,8 +448,8 @@ namespace source
|
|||||||
}
|
}
|
||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||||
block *body)
|
std::vector<variable_declaration *>&& parameters, type_expression *return_type, block *body)
|
||||||
: definition(position, identifier), m_body(body)
|
: definition(position, identifier), m_return_type(return_type), m_body(body), parameters(std::move(parameters))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +463,11 @@ namespace source
|
|||||||
return m_body;
|
return m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_expression *procedure_definition::return_type()
|
||||||
|
{
|
||||||
|
return m_return_type;
|
||||||
|
}
|
||||||
|
|
||||||
procedure_definition::~procedure_definition()
|
procedure_definition::~procedure_definition()
|
||||||
{
|
{
|
||||||
if (m_body != nullptr)
|
if (m_body != nullptr)
|
||||||
@ -768,27 +788,27 @@ namespace source
|
|||||||
delete m_operand;
|
delete m_operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_statement::call_statement(const struct position position, const std::string& name)
|
call_expression::call_expression(const struct position position, const std::string& name)
|
||||||
: statement(position), m_name(name)
|
: expression(position), m_name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_statement::accept(parser_visitor *visitor)
|
void call_expression::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string& call_statement::name()
|
std::string& call_expression::name()
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<expression *>& call_statement::arguments()
|
std::vector<expression *>& call_expression::arguments()
|
||||||
{
|
{
|
||||||
return m_arguments;
|
return m_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_statement::~call_statement()
|
call_expression::~call_expression()
|
||||||
{
|
{
|
||||||
for (auto argument : m_arguments)
|
for (auto argument : m_arguments)
|
||||||
{
|
{
|
||||||
@ -796,8 +816,28 @@ namespace source
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expression_statement::expression_statement(const struct position position, expression *body)
|
||||||
|
: statement(position), m_body(body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void expression_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
expression& expression_statement::body()
|
||||||
|
{
|
||||||
|
return *m_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_statement::~expression_statement()
|
||||||
|
{
|
||||||
|
delete m_body;
|
||||||
|
}
|
||||||
|
|
||||||
compound_statement::compound_statement(const struct position position, std::vector<statement *>&& statements)
|
compound_statement::compound_statement(const struct position position, std::vector<statement *>&& statements)
|
||||||
: statement(position), statements(std::move(statements))
|
: node(position), statements(std::move(statements))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,6 +854,29 @@ namespace source
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return_statement::return_statement(const struct position position, expression *return_expression)
|
||||||
|
: statement(position), m_return_expression(return_expression)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void return_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
expression *return_statement::return_expression()
|
||||||
|
{
|
||||||
|
return m_return_expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
return_statement::~return_statement()
|
||||||
|
{
|
||||||
|
if (m_return_expression != nullptr)
|
||||||
|
{
|
||||||
|
delete m_return_expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void assign_statement::accept(parser_visitor *visitor)
|
void assign_statement::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
|
@ -100,6 +100,9 @@ or {
|
|||||||
not {
|
not {
|
||||||
return yy::parser::make_NOT(this->location);
|
return yy::parser::make_NOT(this->location);
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
|
return yy::parser::make_RETURN(this->location);
|
||||||
|
}
|
||||||
[A-Za-z_][A-Za-z0-9_]* {
|
[A-Za-z_][A-Za-z0-9_]* {
|
||||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
%token <std::string> CHARACTER "character"
|
%token <std::string> CHARACTER "character"
|
||||||
%token <std::string> STRING "string"
|
%token <std::string> STRING "string"
|
||||||
%token <bool> BOOLEAN
|
%token <bool> BOOLEAN
|
||||||
%token IF WHILE DO THEN ELSE
|
%token IF WHILE DO THEN ELSE RETURN
|
||||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
||||||
%token BEGIN_BLOCK END_BLOCK EXTERN
|
%token BEGIN_BLOCK END_BLOCK EXTERN
|
||||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||||
@ -82,9 +82,10 @@
|
|||||||
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
|
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
|
||||||
%type <elna::source::designator_expression *> designator_expression;
|
%type <elna::source::designator_expression *> designator_expression;
|
||||||
%type <elna::source::assign_statement *> assign_statement;
|
%type <elna::source::assign_statement *> assign_statement;
|
||||||
%type <elna::source::call_statement *> call_statement;
|
%type <elna::source::call_expression *> call_expression;
|
||||||
%type <elna::source::while_statement *> while_statement;
|
%type <elna::source::while_statement *> while_statement;
|
||||||
%type <elna::source::if_statement *> if_statement;
|
%type <elna::source::if_statement *> if_statement;
|
||||||
|
%type <elna::source::return_statement *> return_statement;
|
||||||
%type <elna::source::statement *> statement;
|
%type <elna::source::statement *> statement;
|
||||||
%type <std::vector<elna::source::statement *>> statements optional_statements;
|
%type <std::vector<elna::source::statement *>> statements optional_statements;
|
||||||
%type <elna::source::procedure_definition *> procedure_definition;
|
%type <elna::source::procedure_definition *> procedure_definition;
|
||||||
@ -144,14 +145,22 @@ procedure_definition:
|
|||||||
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
||||||
{
|
{
|
||||||
$$ = new elna::source::procedure_definition(elna::source::position{},
|
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||||
std::move($2), $5);
|
$2, std::move($3), nullptr, $5);
|
||||||
std::swap($$->parameters, $3);
|
|
||||||
}
|
}
|
||||||
| PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON
|
| PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON
|
||||||
{
|
{
|
||||||
$$ = new elna::source::procedure_definition(elna::source::position{},
|
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||||
std::move($2));
|
$2, std::move($3), nullptr, nullptr);
|
||||||
std::swap($$->parameters, $3);
|
}
|
||||||
|
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON block SEMICOLON
|
||||||
|
{
|
||||||
|
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||||
|
$2, std::move($3), $5, $7);
|
||||||
|
}
|
||||||
|
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON EXTERN SEMICOLON
|
||||||
|
{
|
||||||
|
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||||
|
$2, std::move($3), $5, nullptr);
|
||||||
}
|
}
|
||||||
procedure_definitions:
|
procedure_definitions:
|
||||||
procedure_definition procedure_definitions
|
procedure_definition procedure_definitions
|
||||||
@ -167,9 +176,9 @@ assign_statement: designator_expression ASSIGNMENT expression
|
|||||||
{
|
{
|
||||||
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
|
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
|
||||||
}
|
}
|
||||||
call_statement: IDENTIFIER actual_parameter_list
|
call_expression: IDENTIFIER actual_parameter_list
|
||||||
{
|
{
|
||||||
$$ = new elna::source::call_statement(elna::source::make_position(@1), $1);
|
$$ = new elna::source::call_expression(elna::source::make_position(@1), $1);
|
||||||
std::swap($$->arguments(), $2);
|
std::swap($$->arguments(), $2);
|
||||||
}
|
}
|
||||||
while_statement: WHILE expression DO optional_statements END_BLOCK
|
while_statement: WHILE expression DO optional_statements END_BLOCK
|
||||||
@ -189,6 +198,11 @@ if_statement:
|
|||||||
auto _else = new elna::source::compound_statement(elna::source::make_position(@5), std::move($6));
|
auto _else = new elna::source::compound_statement(elna::source::make_position(@5), std::move($6));
|
||||||
$$ = new elna::source::if_statement(elna::source::make_position(@1), $2, then, _else);
|
$$ = new elna::source::if_statement(elna::source::make_position(@1), $2, then, _else);
|
||||||
}
|
}
|
||||||
|
return_statement:
|
||||||
|
RETURN expression
|
||||||
|
{
|
||||||
|
$$ = new elna::source::return_statement(elna::source::make_position(@1), $2);
|
||||||
|
}
|
||||||
literal:
|
literal:
|
||||||
INTEGER
|
INTEGER
|
||||||
{
|
{
|
||||||
@ -282,6 +296,7 @@ expression:
|
|||||||
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o');
|
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o');
|
||||||
}
|
}
|
||||||
| logical_operand { $$ = $1; }
|
| logical_operand { $$ = $1; }
|
||||||
|
| call_expression { $$ = $1; }
|
||||||
expressions:
|
expressions:
|
||||||
expression COMMA expressions
|
expression COMMA expressions
|
||||||
{
|
{
|
||||||
@ -308,9 +323,10 @@ designator_expression:
|
|||||||
}
|
}
|
||||||
statement:
|
statement:
|
||||||
assign_statement { $$ = $1; }
|
assign_statement { $$ = $1; }
|
||||||
| call_statement { $$ = $1; }
|
|
||||||
| while_statement { $$ = $1; }
|
| while_statement { $$ = $1; }
|
||||||
| if_statement { $$ = $1; }
|
| if_statement { $$ = $1; }
|
||||||
|
| return_statement { $$ = $1; }
|
||||||
|
| expression { $$ = new elna::source::expression_statement(elna::source::make_position(@1), $1); }
|
||||||
statements:
|
statements:
|
||||||
statement SEMICOLON statements
|
statement SEMICOLON statements
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user