Parse import declarations

This commit is contained in:
2025-05-16 23:16:19 +02:00
parent 981059e745
commit 573d812f1c
9 changed files with 333 additions and 227 deletions

View File

@ -308,8 +308,14 @@ namespace elna::boot
}
procedure_definition::procedure_definition(const struct position position, identifier_definition identifier,
procedure_type_expression *heading, block *body)
: definition(position, identifier), m_heading(heading), body(body)
procedure_type_expression *heading, block&& body)
: definition(position, identifier), m_heading(heading), body(std::move(body))
{
}
procedure_definition::procedure_definition(const struct position position, identifier_definition identifier,
procedure_type_expression *heading)
: definition(position, identifier), m_heading(heading), body(std::nullopt)
{
}
@ -326,7 +332,6 @@ namespace elna::boot
procedure_definition::~procedure_definition()
{
delete m_heading;
delete body;
}
type_definition::type_definition(const struct position position, identifier_definition identifier,
@ -350,34 +355,94 @@ namespace elna::boot
return *m_body;
}
block::block(const struct position position)
: node(position)
block::block(std::vector<constant_definition *>&& constants, std::vector<variable_declaration *>&& variables,
std::vector<statement *>&& body)
: m_variables(std::move(variables)), m_constants(std::move(constants)), m_body(std::move(body))
{
}
void block::accept(parser_visitor *visitor)
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))
{
visitor->visit(this);
}
block& block::operator=(block&& that)
{
std::swap(m_variables, that.m_variables);
std::swap(m_constants, that.m_constants);
std::swap(m_body, that.m_body);
return *this;
}
const std::vector<variable_declaration *>& block::variables()
{
return m_variables;
}
const std::vector<constant_definition *>& block::constants()
{
return m_constants;
}
const std::vector<statement *>& block::body()
{
return m_body;
}
block::~block()
{
for (statement *body_statement : this->body)
for (statement *body_statement : this->body())
{
delete body_statement;
}
for (variable_declaration *variable : this->variables)
for (variable_declaration *variable : this->variables())
{
delete variable;
}
for (constant_definition *constant : this->constants)
for (constant_definition *constant : this->constants())
{
delete constant;
}
}
unit::unit(const struct position position)
: node(position)
{
}
void unit::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
unit::~unit()
{
for (procedure_definition *procedure : this->procedures)
{
delete procedure;
}
for (variable_declaration *variable : this->variables)
{
delete variable;
}
for (type_definition *type : this->types)
{
delete type;
}
for (constant_definition *constant : this->constants)
{
delete constant;
}
for (import_declaration *declaration : this->imports)
{
delete declaration;
}
}
program::program(const struct position position)
: block(position)
: unit(position)
{
}
@ -388,13 +453,9 @@ namespace elna::boot
program::~program()
{
for (procedure_definition *procedure : this->procedures)
for (statement *body_statement : this->body)
{
delete procedure;
}
for (type_definition *type : this->types)
{
delete type;
delete body_statement;
}
}
@ -837,13 +898,12 @@ namespace elna::boot
delete this->alternative;
}
escape_statement::escape_statement(const struct position position,
escape_direction direction, const std::string& label)
: node(position), direction(direction), label(label)
import_declaration::import_declaration(const struct position position, std::vector<std::string>&& segments)
: node(position), segments(std::move(segments))
{
}
void escape_statement::accept(parser_visitor *visitor)
void import_declaration::accept(parser_visitor *visitor)
{
visitor->visit(this);
}

View File

@ -125,12 +125,15 @@ or {
return {
return yy::parser::make_RETURN(this->location);
}
break {
return yy::parser::make_BREAK(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);
}
cast {
return yy::parser::make_CAST(this->location);
}

View File

@ -109,7 +109,8 @@ along with GCC; see the file COPYING3. If not see
ELSIF "elsif"
RETURN "return"
PROGRAM "program"
BREAK "break"
MODULE "module"
IMPORT "import"
BEGIN_BLOCK "begin"
END_BLOCK "end"
DEFER "defer"
@ -154,7 +155,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
%type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block;
%type <std::unique_ptr<elna::boot::block>> block;
%type <elna::boot::field_declaration> field_declaration formal_parameter;
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>>
optional_fields required_fields formal_parameters;
@ -163,28 +164,38 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::identifier_definition> identifier_definition;
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions;
%type <std::vector<std::string>> identifiers;
%type <std::vector<std::string>> identifiers import_declaration;
%type <std::vector<elna::boot::import_declaration *>> import_declarations import_part;
%%
program:
"program" constant_part type_part variable_part procedure_part "begin" statements "end" "."
"program" import_part constant_part type_part variable_part procedure_part "begin" statements "end" "."
{
auto tree = new boot::program(boot::make_position(@6));
auto tree = new boot::program(boot::make_position(@7));
std::swap(tree->constants, $2);
std::swap(tree->types , $3);
std::swap(tree->variables, $4);
std::swap(tree->procedures, $5);
std::swap(tree->body, $7);
std::swap(tree->imports, $2);
std::swap(tree->constants, $3);
std::swap(tree->types , $4);
std::swap(tree->variables, $5);
std::swap(tree->procedures, $6);
std::swap(tree->body, $8);
driver.tree.reset(tree);
}
| "module" import_part constant_part type_part variable_part procedure_part "end" "."
{
auto tree = new boot::program(boot::make_position(@7));
std::swap(tree->imports, $2);
std::swap(tree->constants, $3);
std::swap(tree->types , $4);
std::swap(tree->variables, $5);
std::swap(tree->procedures, $6);
driver.tree.reset(tree);
}
block: constant_part variable_part "begin" statements "end"
{
$$ = new boot::block(boot::make_position(@3));
std::swap($$->constants, $1);
std::swap($$->variables, $2);
std::swap($$->body, $4);
$$ = std::make_unique<boot::block>(std::move($1), std::move($2), std::move($4));
}
identifier_definition:
IDENTIFIER "*" { $$ = boot::identifier_definition{ $1, true }; }
@ -211,12 +222,12 @@ procedure_heading:
}
}
procedure_definition:
"proc" identifier_definition procedure_heading block
"proc" identifier_definition procedure_heading ";" block
{
$$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second, $4);
$$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second, std::move(*$5));
std::swap($3.first, $$->parameter_names);
}
| "proc" identifier_definition procedure_heading "extern"
| "proc" identifier_definition procedure_heading ";" "extern"
{
$$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second);
std::swap($3.first, $$->parameter_names);
@ -417,8 +428,6 @@ statement:
$$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6);
}
| return_statement { $$ = $1; }
| "break" IDENTIFIER
{ $$ = new boot::escape_statement(boot::make_position(@1), boot::escape_direction::end, $2); }
| call_expression { $$ = $1; }
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
| "case" expression "of" switch_cases else_statements "end"
@ -532,6 +541,27 @@ constant_definitions:
constant_part:
/* no constant definitions */ {}
| "const" constant_definitions { std::swap($$, $2); }
import_declaration:
IDENTIFIER "." import_declaration
{
std::swap($$, $3);
$$.emplace($$.cbegin(), std::move($1));
}
| IDENTIFIER { $$.emplace_back(std::move($1)); }
import_declarations:
/* no import declarations */ {}
| import_declaration "," import_declarations
{
std::swap($$, $3);
$$.emplace($$.cbegin(), new boot::import_declaration(boot::make_position(@1), std::move($1)));
}
| import_declaration
{
$$.emplace_back(new boot::import_declaration(boot::make_position(@1), std::move($1)));
}
import_part:
/* no import declarations */ {}
| "import" import_declarations { std::swap($$, $2); }
type_definition: identifier_definition "=" type_expression
{
$$ = new boot::type_definition(boot::make_position(@1), std::move($1), $3);

View File

@ -75,33 +75,8 @@ namespace elna::boot
void declaration_visitor::visit(program *program)
{
for (type_definition *const type : program->types)
{
const std::string& type_identifier = type->identifier.identifier;
visit(static_cast<unit *>(program));
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second
|| this->symbols->contains(type_identifier))
{
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
}
}
for (type_definition *const type : program->types)
{
type->accept(this);
}
for (auto& unresolved : this->unresolved)
{
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
this->symbols->enter(std::move(unresolved.first), info);
}
for (variable_declaration *const variable : program->variables)
{
variable->accept(this);
}
for (procedure_definition *const procedure : program->procedures)
{
procedure->accept(this);
}
for (statement *const statement : program->body)
{
statement->accept(this);
@ -205,9 +180,20 @@ namespace elna::boot
build_procedure(definition->heading()), definition->parameter_names);
this->symbols->enter(definition->identifier.identifier, info);
if (definition->body != nullptr)
if (definition->body.has_value())
{
definition->body->accept(this);
for (constant_definition *const constant : definition->body.value().constants())
{
constant->accept(this);
}
for (variable_declaration *const variable : definition->body.value().variables())
{
variable->accept(this);
}
for (statement *const statement : definition->body.value().body())
{
statement->accept(this);
}
}
}
@ -242,7 +228,7 @@ namespace elna::boot
}
}
void declaration_visitor::visit(escape_statement *)
void declaration_visitor::visit(import_declaration *)
{
}
@ -305,19 +291,34 @@ namespace elna::boot
}
}
void declaration_visitor::visit(block *block)
void declaration_visitor::visit(unit *unit)
{
for (constant_definition *const constant : block->constants)
for (type_definition *const type : unit->types)
{
constant->accept(this);
const std::string& type_identifier = type->identifier.identifier;
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second
|| this->symbols->contains(type_identifier))
{
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
}
}
for (variable_declaration *const variable : block->variables)
for (type_definition *const type : unit->types)
{
type->accept(this);
}
for (auto& unresolved : this->unresolved)
{
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
this->symbols->enter(std::move(unresolved.first), info);
}
for (variable_declaration *const variable : unit->variables)
{
variable->accept(this);
}
for (statement *const statement : block->body)
for (procedure_definition *const procedure : unit->procedures)
{
statement->accept(this);
procedure->accept(this);
}
}