aboutsummaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/ast.cc86
-rw-r--r--frontend/lexer.ll6
-rw-r--r--frontend/parser.yy97
-rw-r--r--frontend/semantic.cc88
4 files changed, 162 insertions, 115 deletions
diff --git a/frontend/ast.cc b/frontend/ast.cc
index e067937..9a1f96b 100644
--- a/frontend/ast.cc
+++ b/frontend/ast.cc
@@ -24,7 +24,7 @@ namespace elna::frontend
__builtin_unreachable();
}
- void empty_visitor::visit(named_type_expression *)
+ void empty_visitor::visit(type_expression *)
{
not_implemented();
}
@@ -149,7 +149,7 @@ namespace elna::frontend
not_implemented();
}
- void empty_visitor::visit(variable_expression *)
+ void empty_visitor::visit(named_expression *)
{
not_implemented();
}
@@ -253,12 +253,7 @@ namespace elna::frontend
return nullptr;
}
- type_expression::type_expression(const struct position position)
- : node(position)
- {
- }
-
- named_type_expression *type_expression::is_named()
+ named_expression *type_expression::is_named()
{
return nullptr;
}
@@ -293,24 +288,46 @@ namespace elna::frontend
return nullptr;
}
- named_type_expression::named_type_expression(const struct position position, const std::string& name)
- : type_expression(position), name(name)
+ void type_expression::accept(parser_visitor *visitor)
{
+ if (named_expression *node = is_named())
+ {
+ return visitor->visit(node);
+ }
+ else if (array_type_expression *node = is_array())
+ {
+ return visitor->visit(node);
+ }
+ else if (pointer_type_expression *node = is_pointer())
+ {
+ return visitor->visit(node);
+ }
+ else if (record_type_expression *node = is_record())
+ {
+ return visitor->visit(node);
+ }
+ else if (union_type_expression *node = is_union())
+ {
+ return visitor->visit(node);
+ }
+ else if (procedure_type_expression *node = is_procedure())
+ {
+ return visitor->visit(node);
+ }
+ else if (enumeration_type_expression *node = is_enumeration())
+ {
+ return visitor->visit(node);
+ }
+ __builtin_unreachable();
}
- void named_type_expression::accept(parser_visitor *visitor)
- {
- visitor->visit(this);
- }
-
- named_type_expression *named_type_expression::is_named()
+ type_expression::~type_expression()
{
- return this;
}
array_type_expression::array_type_expression(const struct position position,
type_expression *base, const std::uint32_t size)
- : type_expression(position), m_base(base), size(size)
+ : node(position), m_base(base), size(size)
{
}
@@ -336,7 +353,7 @@ namespace elna::frontend
pointer_type_expression::pointer_type_expression(const struct position position,
type_expression *base)
- : type_expression(position), m_base(base)
+ : node(position), m_base(base)
{
}
@@ -362,7 +379,7 @@ namespace elna::frontend
record_type_expression::record_type_expression(const struct position position,
std::vector<field_declaration>&& fields)
- : type_expression(position), fields(std::move(fields))
+ : node(position), fields(std::move(fields))
{
}
@@ -386,7 +403,7 @@ namespace elna::frontend
union_type_expression::union_type_expression(const struct position position,
std::vector<field_declaration>&& fields)
- : type_expression(position), fields(std::move(fields))
+ : node(position), fields(std::move(fields))
{
}
@@ -464,7 +481,7 @@ namespace elna::frontend
}
procedure_type_expression::procedure_type_expression(const struct position position, return_t return_type)
- : type_expression(position), return_type(return_type)
+ : node(position), return_type(return_type)
{
}
@@ -491,7 +508,7 @@ namespace elna::frontend
}
enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members)
- : type_expression(position), members(members)
+ : node(position), members(members)
{
}
@@ -559,6 +576,11 @@ namespace elna::frontend
{
}
+ block::block(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables)
+ : m_variables(std::move(variables)), m_constants(std::move(constants))
+ {
+ }
+
block::block(block&& that)
: m_variables(std::move(that.m_variables)), m_constants(std::move(that.m_constants)),
m_body(std::move(that.m_body))
@@ -657,10 +679,6 @@ namespace elna::frontend
}
}
- literal_expression::literal_expression()
- {
- }
-
literal_expression *literal_expression::is_literal()
{
return this;
@@ -684,10 +702,6 @@ namespace elna::frontend
}
}
- designator_expression::designator_expression()
- {
- }
-
designator_expression::~designator_expression()
{
}
@@ -699,7 +713,7 @@ namespace elna::frontend
void designator_expression::accept(parser_visitor *visitor)
{
- if (variable_expression *node = is_variable())
+ if (named_expression *node = is_named())
{
return visitor->visit(node);
}
@@ -718,17 +732,17 @@ namespace elna::frontend
__builtin_unreachable();
}
- variable_expression::variable_expression(const struct position position, const std::string& name)
+ named_expression::named_expression(const struct position position, const std::string& name)
: node(position), name(name)
{
}
- void variable_expression::accept(parser_visitor *visitor)
+ void named_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
- variable_expression *variable_expression::is_variable()
+ named_expression *named_expression::is_named()
{
return this;
}
@@ -1039,7 +1053,7 @@ namespace elna::frontend
visitor->visit(this);
}
- variable_expression *designator_expression::is_variable()
+ named_expression *designator_expression::is_named()
{
return nullptr;
}
diff --git a/frontend/lexer.ll b/frontend/lexer.ll
index f14497b..7c18b32 100644
--- a/frontend/lexer.ll
+++ b/frontend/lexer.ll
@@ -130,12 +130,6 @@ or {
return {
return yy::parser::make_RETURN(this->location);
}
-module {
- return yy::parser::make_MODULE(this->location);
-}
-program {
- return yy::parser::make_PROGRAM(this->location);
-}
import {
return yy::parser::make_IMPORT(this->location);
}
diff --git a/frontend/parser.yy b/frontend/parser.yy
index bace8d7..5e3837b 100644
--- a/frontend/parser.yy
+++ b/frontend/parser.yy
@@ -102,8 +102,6 @@ along with GCC; see the file COPYING3. If not see
ELSE "else"
ELSIF "elsif"
RETURN "return"
- PROGRAM "program"
- MODULE "module"
IMPORT "import"
BEGIN_BLOCK "begin"
END_BLOCK "end"
@@ -142,11 +140,12 @@ along with GCC; see the file COPYING3. If not see
%type <elna::frontend::procedure_call*> call_expression;
%type <elna::frontend::return_statement *> return_statement;
%type <elna::frontend::statement *> statement;
-%type <std::vector<elna::frontend::statement *>> required_statements optional_statements statement_part;
+%type <std::vector<elna::frontend::statement *>> required_statements optional_statements;
+%type <std::unique_ptr<std::vector<elna::frontend::statement *>>> statement_part;
%type <elna::frontend::procedure_declaration *> procedure_declaration;
%type <std::pair<std::vector<std::string>, elna::frontend::procedure_type_expression *>> procedure_heading;
%type <elna::frontend::procedure_type_expression::return_t> return_declaration;
-%type <std::vector<elna::frontend::procedure_declaration *>> procedure_declarations procedure_part;
+%type <std::vector<elna::frontend::procedure_declaration *>> procedure_part;
%type <elna::frontend::type_declaration *> type_declaration;
%type <std::vector<elna::frontend::type_declaration *>> type_declarations type_part;
%type <std::unique_ptr<elna::frontend::block>> block;
@@ -162,43 +161,47 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::frontend::import_declaration *>> import_declarations import_part;
%%
program:
- "program" ";" import_part constant_part type_part variable_part procedure_part statement_part "end" "."
+ import_part constant_part type_part variable_part procedure_part statement_part "end" "."
{
- auto tree = new frontend::program(frontend::make_position(@1));
-
- std::swap(tree->imports, $3);
- std::swap(tree->constants, $4);
- std::swap(tree->types , $5);
- std::swap(tree->variables, $6);
- std::swap(tree->procedures, $7);
- std::swap(tree->body, $8);
-
- driver.tree.reset(tree);
- }
- | "module" ";" import_part constant_part type_part variable_part procedure_part "end" "."
- {
- auto tree = new frontend::unit(frontend::make_position(@1));
-
- std::swap(tree->imports, $3);
- std::swap(tree->constants, $4);
- std::swap(tree->types , $5);
- std::swap(tree->variables, $6);
- std::swap(tree->procedures, $7);
+ if ($6)
+ {
+ frontend::program *tree = new frontend::program(frontend::make_position(@1));
+ std::swap(tree->body, *$6.release());
- driver.tree.reset(tree);
+ driver.tree.reset(tree);
+ }
+ else
+ {
+ driver.tree.reset(new frontend::unit(frontend::make_position(@1)));
+ }
+ std::swap(driver.tree->imports, $1);
+ std::swap(driver.tree->constants, $2);
+ std::swap(driver.tree->types , $3);
+ std::swap(driver.tree->variables, $4);
+ std::swap(driver.tree->procedures, $5);
}
block: constant_part variable_part statement_part "end"
{
- $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move($3));
+ if ($3)
+ {
+ $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move(*$3.release()));
+ }
+ else
+ {
+ $$ = std::make_unique<frontend::block>(std::move($1), std::move($2));
+ }
}
statement_part:
/* no statements */ {}
- | "begin" required_statements { std::swap($$, $2); }
- | return_statement { $$.push_back($1); }
+ | "begin" required_statements { $$ = std::make_unique<std::vector<frontend::statement *>>(std::move($2));; }
+ | return_statement
+ {
+ $$ = std::make_unique<std::vector<frontend::statement *>>(std::vector<frontend::statement *>{ $1 });
+ }
| "begin" required_statements ";" return_statement
{
- std::swap($$, $2);
- $$.push_back($4);
+ $$ = std::make_unique<std::vector<frontend::statement *>>(std::move($2));
+ $$->push_back($4);
}
identifier_definition:
IDENTIFIER "*" { $$ = frontend::identifier_definition{ $1, true }; }
@@ -224,26 +227,24 @@ procedure_heading: formal_parameter_list return_declaration
}
}
procedure_declaration:
- "proc" identifier_definition procedure_heading ";" block ";"
+ "proc" identifier_definition procedure_heading block
{
- $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, std::move(*$5));
+ $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second,
+ std::move(*$4));
std::swap($3.first, $$->parameter_names);
}
- | "proc" identifier_definition procedure_heading ";" "extern" ";"
+ | "proc" identifier_definition procedure_heading "extern"
{
$$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second);
std::swap($3.first, $$->parameter_names);
}
-procedure_declarations:
- procedure_declaration procedure_declarations
+procedure_part:
+ /* no procedure declarations */ {}
+ | procedure_declaration procedure_part
{
std::swap($$, $2);
$$.emplace($$.cbegin(), std::move($1));
}
- | procedure_declaration { $$.emplace_back(std::move($1)); }
-procedure_part:
- /* no procedure definitions */ {}
- | procedure_declarations { std::swap($$, $1); }
call_expression: designator_expression actual_parameter_list
{
$$ = new frontend::procedure_call(frontend::make_position(@1), $1);
@@ -401,7 +402,7 @@ designator_expression:
| simple_expression "^"
{ $$ = new frontend::dereference_expression(frontend::make_position(@1), $1); }
| IDENTIFIER
- { $$ = new frontend::variable_expression(frontend::make_position(@1), $1); }
+ { $$ = new frontend::named_expression(frontend::make_position(@1), $1); }
statement:
designator_expression ":=" expression
{ $$ = new frontend::assign_statement(frontend::make_position(@1), $1, $3); }
@@ -487,7 +488,7 @@ type_expression:
}
| IDENTIFIER
{
- $$ = new frontend::named_type_expression(frontend::make_position(@1), $1);
+ $$ = new frontend::named_expression(frontend::make_position(@1), $1);
}
identifiers:
IDENTIFIER "," identifiers
@@ -497,18 +498,18 @@ identifiers:
}
| IDENTIFIER { $$.emplace_back(std::move($1)); }
variable_declaration:
- identifier_definitions ":" type_expression ";"
+ identifier_definitions ":" type_expression
{
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type);
}
- | identifier_definitions ":" type_expression ":=" "extern" ";"
+ | identifier_definitions ":" type_expression ":=" "extern"
{
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type,
std::monostate{});
}
- | identifier_definitions ":" type_expression ":=" expression ";"
+ | identifier_definitions ":" type_expression ":=" expression
{
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, $5);
@@ -523,7 +524,7 @@ variable_declarations:
variable_part:
/* no variable declarations */ {}
| "var" variable_declarations { std::swap($$, $2); }
-constant_declaration: identifier_definition ":=" expression ";"
+constant_declaration: identifier_definition ":=" expression
{
$$ = new frontend::constant_declaration(frontend::make_position(@1), std::move($1), $3);
}
@@ -556,8 +557,8 @@ import_declarations:
}
import_part:
/* no import declarations */ {}
- | "import" import_declarations ";" { std::swap($$, $2); }
-type_declaration: identifier_definition "=" type_expression ";"
+ | "import" import_declarations { std::swap($$, $2); }
+type_declaration: identifier_definition "=" type_expression
{
$$ = new frontend::type_declaration(frontend::make_position(@1), std::move($1), $3);
}
diff --git a/frontend/semantic.cc b/frontend/semantic.cc
index 36c75b8..ee18492 100644
--- a/frontend/semantic.cc
+++ b/frontend/semantic.cc
@@ -223,10 +223,20 @@ namespace elna::frontend
{
visit(static_cast<unit *>(program));
+ this->bag.enter();
+ auto variable_type = this->bag.lookup("Int")->is_type()->symbol;
+ this->bag.enter("count", std::make_shared<variable_info>(variable_type, false));
+
+ variable_type = this->bag.lookup("Char")->is_type()->symbol;
+ variable_type = type(std::make_shared<pointer_type>(variable_type));
+ variable_type = type(std::make_shared<pointer_type>(variable_type));
+ this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false));
+
for (statement *const statement : program->body)
{
statement->accept(this);
}
+ this->bag.leave();
}
void name_analysis_visitor::visit(type_declaration *definition)
@@ -239,23 +249,8 @@ namespace elna::frontend
this->bag.enter(definition->identifier.name, info);
}
- void name_analysis_visitor::visit(named_type_expression *type_expression)
+ void name_analysis_visitor::visit(type_expression *)
{
- auto unresolved_alias = this->bag.declared(type_expression->name);
-
- if (unresolved_alias != nullptr)
- {
- this->current_type = type(unresolved_alias);
- }
- else if (auto from_symbol_table = this->bag.lookup(type_expression->name))
- {
- this->current_type = from_symbol_table->is_type()->symbol;
- }
- else
- {
- add_error<undeclared_error>(type_expression->name, this->input_file, type_expression->position());
- this->current_type = type();
- }
}
void name_analysis_visitor::visit(pointer_type_expression *type_expression)
@@ -267,7 +262,9 @@ namespace elna::frontend
void name_analysis_visitor::visit(array_type_expression *type_expression)
{
type_expression->base().accept(this);
- this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size));
+ auto result_type{ std::make_shared<array_type>(this->current_type, type_expression->size) };
+
+ this->current_type = type(result_type);
}
std::vector<type_field> name_analysis_visitor::build_composite_type(const std::vector<field_declaration>& fields)
@@ -324,20 +321,27 @@ namespace elna::frontend
this->current_type = type(result_type);
}
+ std::shared_ptr<variable_info> name_analysis_visitor::register_variable(const std::string& name,
+ const bool is_extern, const struct position position)
+ {
+ auto variable_symbol = std::make_shared<variable_info>(this->current_type, is_extern);
+
+ if (!this->bag.enter(name, variable_symbol))
+ {
+ add_error<already_declared_error>(name, this->input_file, position);
+ }
+ return variable_symbol;
+ }
+
void name_analysis_visitor::visit(variable_declaration *declaration)
{
declaration->variable_type().accept(this);
for (const auto& variable_identifier : declaration->identifiers)
{
- auto variable_symbol = std::make_shared<variable_info>(this->current_type, declaration->is_extern);
-
+ auto variable_symbol = register_variable(variable_identifier.name, declaration->is_extern,
+ declaration->position());
variable_symbol->exported = variable_identifier.exported;
- if (!this->bag.enter(variable_identifier.name, variable_symbol))
- {
- add_error<already_declared_error>(variable_identifier.name, this->input_file,
- declaration->position());
- }
}
}
@@ -358,7 +362,19 @@ namespace elna::frontend
if (definition->body.has_value())
{
info = std::make_shared<procedure_info>(heading, definition->parameter_names, this->bag.enter());
+ auto name_iterator = std::cbegin(definition->parameter_names);
+ auto type_iterator = std::cbegin(heading.parameters);
+ while (name_iterator != std::cend(definition->parameter_names)
+ && type_iterator != std::cend(heading.parameters))
+ {
+ this->current_type = *type_iterator;
+ auto variable_symbol = register_variable(*name_iterator, false, definition->heading().position());
+ variable_symbol->exported = false;
+
+ ++name_iterator;
+ ++type_iterator;
+ }
for (constant_declaration *const constant : definition->body.value().constants())
{
constant->accept(this);
@@ -489,6 +505,10 @@ namespace elna::frontend
{
variable->accept(this);
}
+ for (constant_declaration *const constant : unit->constants)
+ {
+ constant->accept(this);
+ }
for (procedure_declaration *const procedure : unit->procedures)
{
procedure->accept(this);
@@ -522,8 +542,26 @@ namespace elna::frontend
expression->operand().accept(this);
}
- void name_analysis_visitor::visit(variable_expression *)
+ void name_analysis_visitor::visit(named_expression *type_expression)
{
+ auto unresolved_alias = this->bag.declared(type_expression->name);
+
+ if (unresolved_alias != nullptr)
+ {
+ this->current_type = type(unresolved_alias);
+ }
+ else if (auto from_symbol_table = this->bag.lookup(type_expression->name))
+ {
+ if (auto type_symbol = from_symbol_table->is_type())
+ {
+ this->current_type = type_symbol->symbol;
+ }
+ }
+ else
+ {
+ add_error<undeclared_error>(type_expression->name, this->input_file, type_expression->position());
+ this->current_type = type();
+ }
}
void name_analysis_visitor::visit(array_access_expression *expression)