Parse import declarations
This commit is contained in:
102
boot/ast.cc
102
boot/ast.cc
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user