Support variable declaration initializer
This commit is contained in:
@@ -408,9 +408,10 @@ namespace elna::boot
|
||||
return this;
|
||||
}
|
||||
|
||||
variable_declaration::variable_declaration(const struct position position, identifier_definition identifier,
|
||||
std::shared_ptr<type_expression> variable_type)
|
||||
: declaration(position, identifier), m_variable_type(variable_type)
|
||||
variable_declaration::variable_declaration(const struct position position,
|
||||
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
|
||||
expression *body)
|
||||
: node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), body(body)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -53,7 +53,7 @@ namespace elna::boot
|
||||
|
||||
if (!declaration_visitor.errors().empty())
|
||||
{
|
||||
std::swap(outcome.errors(), parse_driver.errors());
|
||||
std::swap(outcome.errors(), declaration_visitor.errors());
|
||||
}
|
||||
outcome.unresolved = declaration_visitor.unresolved;
|
||||
|
||||
|
@@ -135,7 +135,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <std::vector<elna::boot::switch_case>> switch_cases;
|
||||
%type <elna::boot::constant_declaration *> constant_declaration;
|
||||
%type <std::vector<elna::boot::constant_declaration *>> constant_part constant_declarations;
|
||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration;
|
||||
%type <elna::boot::variable_declaration *> variable_declaration;
|
||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part;
|
||||
%type <elna::boot::type_expression *> type_expression;
|
||||
%type <std::vector<elna::boot::type_expression *>> type_expressions;
|
||||
%type <elna::boot::traits_expression *> traits_expression;
|
||||
@@ -501,24 +502,23 @@ identifiers:
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| IDENTIFIER { $$.emplace_back(std::move($1)); }
|
||||
variable_declaration: identifier_definitions ":" type_expression ";"
|
||||
variable_declaration:
|
||||
identifier_definitions ":" type_expression ";"
|
||||
{
|
||||
std::shared_ptr<boot::type_expression> shared_type{ $3 };
|
||||
|
||||
for (boot::identifier_definition& identifier : $1)
|
||||
{
|
||||
boot::variable_declaration *declaration = new boot::variable_declaration(
|
||||
boot::make_position(@2), std::move(identifier), shared_type);
|
||||
$$.push_back(declaration);
|
||||
}
|
||||
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type);
|
||||
}
|
||||
| identifier_definitions ":" type_expression ":=" expression ";"
|
||||
{
|
||||
std::shared_ptr<boot::type_expression> shared_type{ $3 };
|
||||
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type, $5);
|
||||
}
|
||||
variable_declarations:
|
||||
/* no variable declarations */ {}
|
||||
| variable_declaration variable_declarations
|
||||
{
|
||||
std::swap($$, $1);
|
||||
$$.reserve($$.size() + $2.size());
|
||||
$$.insert(std::end($$), std::begin($2), std::end($2));
|
||||
std::swap($$, $2);
|
||||
$$.insert(std::cbegin($$), $1);
|
||||
}
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
@@ -531,7 +531,7 @@ constant_declarations:
|
||||
constant_declaration constant_declarations
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.insert($$.cbegin(), $1);
|
||||
$$.insert(std::cbegin($$), $1);
|
||||
}
|
||||
| /* no constant definitions */ {}
|
||||
constant_part:
|
||||
|
@@ -83,6 +83,16 @@ namespace elna::boot
|
||||
return "Procedure '" + identifier + "' is expected to return, but does not have a return statement";
|
||||
}
|
||||
|
||||
variable_initializer_error::variable_initializer_error(const char *path, const struct position position)
|
||||
: error(path, position)
|
||||
{
|
||||
}
|
||||
|
||||
std::string variable_initializer_error::what() const
|
||||
{
|
||||
return "Only one variable can be initialized";
|
||||
}
|
||||
|
||||
type_analysis_visitor::type_analysis_visitor(const char *path)
|
||||
: error_container(path)
|
||||
{
|
||||
@@ -289,7 +299,10 @@ namespace elna::boot
|
||||
{
|
||||
declaration->variable_type().accept(this);
|
||||
|
||||
this->bag.enter(declaration->identifier.identifier, std::make_shared<variable_info>(this->current_type));
|
||||
for (const auto& variable_identifier : declaration->identifiers)
|
||||
{
|
||||
this->bag.enter(variable_identifier.identifier, std::make_shared<variable_info>(this->current_type));
|
||||
}
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(constant_declaration *definition)
|
||||
@@ -584,5 +597,33 @@ namespace elna::boot
|
||||
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
|
||||
}
|
||||
}
|
||||
for (variable_declaration *const variable : unit->variables)
|
||||
{
|
||||
variable->accept(this);
|
||||
}
|
||||
for (procedure_declaration *const procedure : unit->procedures)
|
||||
{
|
||||
procedure->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(variable_declaration *declaration)
|
||||
{
|
||||
if (declaration->body != nullptr && declaration->identifiers.size() > 1)
|
||||
{
|
||||
add_error<variable_initializer_error>(this->input_file, declaration->position());
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(procedure_declaration *definition)
|
||||
{
|
||||
if (!definition->body.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (boot::variable_declaration *const variable : definition->body.value().variables())
|
||||
{
|
||||
variable->accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user