Support while … else

This commit is contained in:
2025-04-13 18:40:49 +02:00
parent 8ec407515a
commit 1cd44508c3
6 changed files with 145 additions and 135 deletions

View File

@@ -223,9 +223,9 @@ namespace elna::boot
return this;
}
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<type_expression> variable_type, const bool exported)
: definition(position, identifier, exported), m_variable_type(variable_type)
variable_declaration::variable_declaration(const struct position position, identifier_definition identifier,
std::shared_ptr<type_expression> variable_type)
: definition(position, identifier), m_variable_type(variable_type)
{
}
@@ -239,14 +239,14 @@ namespace elna::boot
return *m_variable_type;
}
definition::definition(const struct position position, const std::string& identifier, const bool exported)
: node(position), identifier(identifier), exported(exported)
definition::definition(const struct position position, identifier_definition identifier)
: node(position), identifier(identifier)
{
}
constant_definition::constant_definition(const struct position position, const std::string& identifier,
const bool exported, expression *body)
: definition(position, identifier, exported), m_body(body)
constant_definition::constant_definition(const struct position position, identifier_definition identifier,
expression *body)
: definition(position, identifier), m_body(body)
{
}
@@ -307,9 +307,9 @@ namespace elna::boot
return this;
}
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, procedure_type_expression *heading, block *body)
: definition(position, identifier, exported), m_heading(heading), body(body)
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)
{
}
@@ -329,9 +329,9 @@ namespace elna::boot
delete body;
}
type_definition::type_definition(const struct position position, const std::string& identifier,
const bool exported, type_expression *body)
: definition(position, identifier, exported), m_body(body)
type_definition::type_definition(const struct position position, identifier_definition identifier,
type_expression *body)
: definition(position, identifier), m_body(body)
{
}
@@ -811,8 +811,9 @@ namespace elna::boot
}
if_statement::if_statement(const struct position position, conditional_statements *body,
std::vector<conditional_statements *>&& branches,
std::vector<statement *> *alternative)
: node(position), m_body(body), alternative(alternative)
: node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
{
}
@@ -848,14 +849,15 @@ namespace elna::boot
}
while_statement::while_statement(const struct position position, conditional_statements *body,
std::vector<conditional_statements *>&& branches)
: node(position), m_body(body), branches(std::move(branches))
std::vector<conditional_statements *>&& branches, std::vector<statement *> *alternative)
: node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
{
}
while_statement::while_statement(const struct position position, conditional_statements *body,
std::vector<conditional_statements *>&& branches, const std::string& label)
: node(position), m_body(body), branches(std::move(branches)), label(label)
std::vector<conditional_statements *>&& branches, const std::string& label,
std::vector<statement *> *alternative)
: node(position), m_body(body), branches(std::move(branches)), label(label), alternative(alternative)
{
}

View File

@@ -161,8 +161,8 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <std::vector<elna::boot::statement *> *> else_statements;
%type <elna::boot::cast_expression *> cast_expression;
%type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
%type <elna::boot::identifier_definition> identifier_definition;
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions;
%type <std::vector<std::string>> identifiers;
%%
program:
@@ -187,14 +187,8 @@ block: constant_part variable_part "begin" statements "end"
std::swap($$->body, $4);
}
identifier_definition:
IDENTIFIER "*"
{
$$ = std::make_pair($1, true);
}
| IDENTIFIER
{
$$ = std::make_pair($1, false);
}
IDENTIFIER "*" { $$ = boot::identifier_definition{ $1, true }; }
| IDENTIFIER { $$ = boot::identifier_definition{ $1, false }; }
identifier_definitions:
identifier_definition "," identifier_definitions
{
@@ -219,12 +213,12 @@ procedure_heading:
procedure_definition:
"proc" identifier_definition procedure_heading ";" block
{
$$ = new boot::procedure_definition(boot::make_position(@1), $2.first, $2.second, $3.second, $5);
$$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second, $5);
std::swap($3.first, $$->parameter_names);
}
| "proc" identifier_definition procedure_heading ";" "extern"
{
$$ = new boot::procedure_definition(boot::make_position(@1), $2.first, $2.second, $3.second);
$$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second);
std::swap($3.first, $$->parameter_names);
}
procedure_definitions:
@@ -243,9 +237,7 @@ call_expression: designator_expression actual_parameter_list
std::swap($$->arguments, $2);
}
cast_expression: "cast" "(" expression ":" type_expression ")"
{
$$ = new boot::cast_expression(boot::make_position(@1), $5, $3);
}
{ $$ = new boot::cast_expression(boot::make_position(@1), $5, $3); }
elsif_do_statements:
"elsif" expression "do" statements elsif_do_statements
{
@@ -258,15 +250,15 @@ else_statements:
"else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
| { $$ = nullptr; }
while_statement:
"while" expression "do" statements elsif_do_statements "end"
"while" expression "do" statements elsif_do_statements else_statements "end"
{
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5));
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5), $6);
}
| "while" expression "," IDENTIFIER "do" statements elsif_do_statements "end"
| "while" expression "," IDENTIFIER "do" statements elsif_do_statements else_statements "end"
{
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($6));
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($7), $4);
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($7), $4, $8);
}
elsif_then_statements:
"elsif" expression "then" statements elsif_then_statements
@@ -422,9 +414,7 @@ statement:
| "if" expression "then" statements elsif_then_statements else_statements "end"
{
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
auto result = new boot::if_statement(boot::make_position(@1), then, $6);
std::swap($5, result->branches);
$$ = result;
$$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6);
}
| return_statement { $$ = $1; }
| "break" IDENTIFIER
@@ -512,32 +502,32 @@ variable_declaration: identifier_definitions ":" type_expression
{
std::shared_ptr<boot::type_expression> shared_type{ $3 };
for (const std::pair<std::string, bool>& identifier : $1)
for (boot::identifier_definition& identifier : $1)
{
boot::variable_declaration *declaration = new boot::variable_declaration(
boot::make_position(@2), identifier.first, shared_type, identifier.second);
boot::make_position(@2), std::move(identifier), shared_type);
$$.push_back(declaration);
}
}
variable_declarations:
variable_declaration ";" variable_declarations
/* no variable declarations */ {}
| variable_declaration variable_declarations
{
std::swap($$, $1);
$$.reserve($$.size() + $3.size());
$$.insert(std::end($$), std::begin($3), std::end($3));
$$.reserve($$.size() + $2.size());
$$.insert(std::end($$), std::begin($2), std::end($2));
}
| /* no variable declarations */ {}
variable_part:
/* no variable declarations */ {}
| "var" variable_declarations { std::swap($$, $2); }
constant_definition: identifier_definition ":=" expression
{
$$ = new boot::constant_definition(boot::make_position(@1), $1.first, $1.second, $3);
$$ = new boot::constant_definition(boot::make_position(@1), std::move($1), $3);
}
constant_definitions:
constant_definition ";" constant_definitions
constant_definition constant_definitions
{
std::swap($$, $3);
std::swap($$, $2);
$$.insert($$.cbegin(), $1);
}
| /* no constant definitions */ {}
@@ -546,12 +536,12 @@ constant_part:
| "const" constant_definitions { std::swap($$, $2); }
type_definition: identifier_definition "=" type_expression
{
$$ = new boot::type_definition(boot::make_position(@1), $1.first, $1.second, $3);
$$ = new boot::type_definition(boot::make_position(@1), std::move($1), $3);
}
type_definitions:
type_definition ";" type_definitions
type_definition type_definitions
{
std::swap($$, $3);
std::swap($$, $2);
$$.insert($$.cbegin(), $1);
}
| /* no type definitions */ {}

View File

@@ -77,10 +77,12 @@ namespace elna::boot
{
for (type_definition *const type : program->types)
{
if (!this->unresolved.insert({ type->identifier, std::make_shared<alias_type>(type->identifier) }).second
|| this->symbols->contains(type->identifier))
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, this->input_file, type->position());
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
}
}
for (type_definition *const type : program->types)
@@ -109,7 +111,7 @@ namespace elna::boot
void declaration_visitor::visit(type_definition *definition)
{
definition->body().accept(this);
auto unresolved_declaration = this->unresolved.at(definition->identifier);
auto unresolved_declaration = this->unresolved.at(definition->identifier.identifier);
unresolved_declaration->reference = this->current_type;
}
@@ -193,7 +195,8 @@ namespace elna::boot
{
definition->body().accept(this);
this->symbols->enter(definition->identifier, std::make_shared<constant_info>(this->current_literal));
this->symbols->enter(definition->identifier.identifier,
std::make_shared<constant_info>(this->current_literal));
}
void declaration_visitor::visit(procedure_definition *definition)
@@ -201,7 +204,7 @@ namespace elna::boot
std::shared_ptr<procedure_info> info = std::make_shared<procedure_info>(
build_procedure(definition->heading()), definition->parameter_names);
this->symbols->enter(definition->identifier, info);
this->symbols->enter(definition->identifier.identifier, info);
if (definition->body != nullptr)
{
definition->body->accept(this);