Support while … else
This commit is contained in:
parent
8ec407515a
commit
1cd44508c3
40
boot/ast.cc
40
boot/ast.cc
@ -223,9 +223,9 @@ namespace elna::boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration::variable_declaration(const struct position position, identifier_definition identifier,
|
||||||
std::shared_ptr<type_expression> variable_type, const bool exported)
|
std::shared_ptr<type_expression> variable_type)
|
||||||
: definition(position, identifier, exported), m_variable_type(variable_type)
|
: definition(position, identifier), m_variable_type(variable_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,14 +239,14 @@ namespace elna::boot
|
|||||||
return *m_variable_type;
|
return *m_variable_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
definition::definition(const struct position position, const std::string& identifier, const bool exported)
|
definition::definition(const struct position position, identifier_definition identifier)
|
||||||
: node(position), identifier(identifier), exported(exported)
|
: node(position), identifier(identifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
constant_definition::constant_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, expression *body)
|
expression *body)
|
||||||
: definition(position, identifier, exported), m_body(body)
|
: definition(position, identifier), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,9 +307,9 @@ namespace elna::boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition::procedure_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, procedure_type_expression *heading, block *body)
|
procedure_type_expression *heading, block *body)
|
||||||
: definition(position, identifier, exported), m_heading(heading), body(body)
|
: definition(position, identifier), m_heading(heading), body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,9 +329,9 @@ namespace elna::boot
|
|||||||
delete body;
|
delete body;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_definition::type_definition(const struct position position, const std::string& identifier,
|
type_definition::type_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, type_expression *body)
|
type_expression *body)
|
||||||
: definition(position, identifier, exported), m_body(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,
|
if_statement::if_statement(const struct position position, conditional_statements *body,
|
||||||
|
std::vector<conditional_statements *>&& branches,
|
||||||
std::vector<statement *> *alternative)
|
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,
|
while_statement::while_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<conditional_statements *>&& branches)
|
std::vector<conditional_statements *>&& branches, std::vector<statement *> *alternative)
|
||||||
: node(position), m_body(body), branches(std::move(branches))
|
: node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
while_statement::while_statement(const struct position position, conditional_statements *body,
|
while_statement::while_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<conditional_statements *>&& branches, const std::string& label)
|
std::vector<conditional_statements *>&& branches, const std::string& label,
|
||||||
: node(position), m_body(body), branches(std::move(branches)), label(label)
|
std::vector<statement *> *alternative)
|
||||||
|
: node(position), m_body(body), branches(std::move(branches)), label(label), alternative(alternative)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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::conditional_statements *>> elsif_then_statements elsif_do_statements;
|
||||||
%type <std::vector<elna::boot::statement *> *> else_statements;
|
%type <std::vector<elna::boot::statement *> *> else_statements;
|
||||||
%type <elna::boot::cast_expression *> cast_expression;
|
%type <elna::boot::cast_expression *> cast_expression;
|
||||||
%type <std::pair<std::string, bool>> identifier_definition;
|
%type <elna::boot::identifier_definition> identifier_definition;
|
||||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
|
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions;
|
||||||
%type <std::vector<std::string>> identifiers;
|
%type <std::vector<std::string>> identifiers;
|
||||||
%%
|
%%
|
||||||
program:
|
program:
|
||||||
@ -187,14 +187,8 @@ block: constant_part variable_part "begin" statements "end"
|
|||||||
std::swap($$->body, $4);
|
std::swap($$->body, $4);
|
||||||
}
|
}
|
||||||
identifier_definition:
|
identifier_definition:
|
||||||
IDENTIFIER "*"
|
IDENTIFIER "*" { $$ = boot::identifier_definition{ $1, true }; }
|
||||||
{
|
| IDENTIFIER { $$ = boot::identifier_definition{ $1, false }; }
|
||||||
$$ = std::make_pair($1, true);
|
|
||||||
}
|
|
||||||
| IDENTIFIER
|
|
||||||
{
|
|
||||||
$$ = std::make_pair($1, false);
|
|
||||||
}
|
|
||||||
identifier_definitions:
|
identifier_definitions:
|
||||||
identifier_definition "," identifier_definitions
|
identifier_definition "," identifier_definitions
|
||||||
{
|
{
|
||||||
@ -219,12 +213,12 @@ procedure_heading:
|
|||||||
procedure_definition:
|
procedure_definition:
|
||||||
"proc" identifier_definition procedure_heading ";" block
|
"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);
|
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), $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);
|
std::swap($3.first, $$->parameter_names);
|
||||||
}
|
}
|
||||||
procedure_definitions:
|
procedure_definitions:
|
||||||
@ -243,9 +237,7 @@ call_expression: designator_expression actual_parameter_list
|
|||||||
std::swap($$->arguments, $2);
|
std::swap($$->arguments, $2);
|
||||||
}
|
}
|
||||||
cast_expression: "cast" "(" expression ":" type_expression ")"
|
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_do_statements:
|
||||||
"elsif" expression "do" statements 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)); }
|
"else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
|
||||||
| { $$ = nullptr; }
|
| { $$ = nullptr; }
|
||||||
while_statement:
|
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));
|
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));
|
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_then_statements:
|
||||||
"elsif" expression "then" statements 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"
|
| "if" expression "then" statements elsif_then_statements else_statements "end"
|
||||||
{
|
{
|
||||||
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
|
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
|
||||||
auto result = new boot::if_statement(boot::make_position(@1), then, $6);
|
$$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6);
|
||||||
std::swap($5, result->branches);
|
|
||||||
$$ = result;
|
|
||||||
}
|
}
|
||||||
| return_statement { $$ = $1; }
|
| return_statement { $$ = $1; }
|
||||||
| "break" IDENTIFIER
|
| "break" IDENTIFIER
|
||||||
@ -512,32 +502,32 @@ variable_declaration: identifier_definitions ":" type_expression
|
|||||||
{
|
{
|
||||||
std::shared_ptr<boot::type_expression> shared_type{ $3 };
|
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::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);
|
$$.push_back(declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variable_declarations:
|
variable_declarations:
|
||||||
variable_declaration ";" variable_declarations
|
/* no variable declarations */ {}
|
||||||
|
| variable_declaration variable_declarations
|
||||||
{
|
{
|
||||||
std::swap($$, $1);
|
std::swap($$, $1);
|
||||||
$$.reserve($$.size() + $3.size());
|
$$.reserve($$.size() + $2.size());
|
||||||
$$.insert(std::end($$), std::begin($3), std::end($3));
|
$$.insert(std::end($$), std::begin($2), std::end($2));
|
||||||
}
|
}
|
||||||
| /* no variable declarations */ {}
|
|
||||||
variable_part:
|
variable_part:
|
||||||
/* no variable declarations */ {}
|
/* no variable declarations */ {}
|
||||||
| "var" variable_declarations { std::swap($$, $2); }
|
| "var" variable_declarations { std::swap($$, $2); }
|
||||||
constant_definition: identifier_definition ":=" expression
|
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_definitions:
|
||||||
constant_definition ";" constant_definitions
|
constant_definition constant_definitions
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $2);
|
||||||
$$.insert($$.cbegin(), $1);
|
$$.insert($$.cbegin(), $1);
|
||||||
}
|
}
|
||||||
| /* no constant definitions */ {}
|
| /* no constant definitions */ {}
|
||||||
@ -546,12 +536,12 @@ constant_part:
|
|||||||
| "const" constant_definitions { std::swap($$, $2); }
|
| "const" constant_definitions { std::swap($$, $2); }
|
||||||
type_definition: identifier_definition "=" type_expression
|
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_definitions:
|
||||||
type_definition ";" type_definitions
|
type_definition type_definitions
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $2);
|
||||||
$$.insert($$.cbegin(), $1);
|
$$.insert($$.cbegin(), $1);
|
||||||
}
|
}
|
||||||
| /* no type definitions */ {}
|
| /* no type definitions */ {}
|
||||||
|
@ -77,10 +77,12 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
for (type_definition *const type : program->types)
|
for (type_definition *const type : program->types)
|
||||||
{
|
{
|
||||||
if (!this->unresolved.insert({ type->identifier, std::make_shared<alias_type>(type->identifier) }).second
|
const std::string& type_identifier = type->identifier.identifier;
|
||||||
|| this->symbols->contains(type->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)
|
for (type_definition *const type : program->types)
|
||||||
@ -109,7 +111,7 @@ namespace elna::boot
|
|||||||
void declaration_visitor::visit(type_definition *definition)
|
void declaration_visitor::visit(type_definition *definition)
|
||||||
{
|
{
|
||||||
definition->body().accept(this);
|
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;
|
unresolved_declaration->reference = this->current_type;
|
||||||
}
|
}
|
||||||
@ -193,7 +195,8 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
definition->body().accept(this);
|
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)
|
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>(
|
std::shared_ptr<procedure_info> info = std::make_shared<procedure_info>(
|
||||||
build_procedure(definition->heading()), definition->parameter_names);
|
build_procedure(definition->heading()), definition->parameter_names);
|
||||||
|
|
||||||
this->symbols->enter(definition->identifier, info);
|
this->symbols->enter(definition->identifier.identifier, info);
|
||||||
if (definition->body != nullptr)
|
if (definition->body != nullptr)
|
||||||
{
|
{
|
||||||
definition->body->accept(this);
|
definition->body->accept(this);
|
||||||
|
@ -267,8 +267,8 @@ namespace elna::gcc
|
|||||||
void generic_visitor::declare_procedure(boot::procedure_definition *const definition)
|
void generic_visitor::declare_procedure(boot::procedure_definition *const definition)
|
||||||
{
|
{
|
||||||
tree declaration_type = build_procedure_type(definition->heading());
|
tree declaration_type = build_procedure_type(definition->heading());
|
||||||
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
tree fndecl = build_fn_decl(definition->identifier.identifier.c_str(), declaration_type);
|
||||||
this->symbols->enter(definition->identifier, fndecl);
|
this->symbols->enter(definition->identifier.identifier, fndecl);
|
||||||
|
|
||||||
if (definition->heading().return_type.no_return)
|
if (definition->heading().return_type.no_return)
|
||||||
{
|
{
|
||||||
@ -296,7 +296,7 @@ namespace elna::gcc
|
|||||||
++parameter_name;
|
++parameter_name;
|
||||||
}
|
}
|
||||||
DECL_ARGUMENTS(fndecl) = argument_chain;
|
DECL_ARGUMENTS(fndecl) = argument_chain;
|
||||||
TREE_PUBLIC(fndecl) = definition->exported;
|
TREE_PUBLIC(fndecl) = definition->identifier.exported;
|
||||||
TREE_ADDRESSABLE(fndecl) = 1;
|
TREE_ADDRESSABLE(fndecl) = 1;
|
||||||
DECL_EXTERNAL(fndecl) = definition->body == nullptr;
|
DECL_EXTERNAL(fndecl) = definition->body == nullptr;
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ namespace elna::gcc
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tree fndecl = this->symbols->lookup(definition->identifier);
|
tree fndecl = this->symbols->lookup(definition->identifier.identifier);
|
||||||
|
|
||||||
push_struct_function(fndecl, false);
|
push_struct_function(fndecl, false);
|
||||||
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
|
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
|
||||||
@ -778,15 +778,15 @@ namespace elna::gcc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||||
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
|
get_identifier(definition->identifier.identifier.c_str()), TREE_TYPE(this->current_expression));
|
||||||
auto result = this->symbols->enter(definition->identifier, definition_tree);
|
auto result = this->symbols->enter(definition->identifier.identifier, definition_tree);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
DECL_INITIAL(definition_tree) = this->current_expression;
|
DECL_INITIAL(definition_tree) = this->current_expression;
|
||||||
TREE_CONSTANT(definition_tree) = 1;
|
TREE_CONSTANT(definition_tree) = 1;
|
||||||
TREE_READONLY(definition_tree) = 1;
|
TREE_READONLY(definition_tree) = 1;
|
||||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
TREE_PUBLIC(definition_tree) = definition->identifier.exported;
|
||||||
|
|
||||||
if (!lang_hooks.decls.global_bindings_p())
|
if (!lang_hooks.decls.global_bindings_p())
|
||||||
{
|
{
|
||||||
@ -798,7 +798,7 @@ namespace elna::gcc
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(definition_location, "Variable '%s' already declared in this scope",
|
error_at(definition_location, "Variable '%s' already declared in this scope",
|
||||||
definition->identifier.c_str());
|
definition->identifier.identifier.c_str());
|
||||||
}
|
}
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
@ -806,16 +806,16 @@ namespace elna::gcc
|
|||||||
void generic_visitor::visit(boot::type_definition *definition)
|
void generic_visitor::visit(boot::type_definition *definition)
|
||||||
{
|
{
|
||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
this->current_expression = this->unresolved.at(definition->identifier);
|
this->current_expression = this->unresolved.at(definition->identifier.identifier);
|
||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
|
|
||||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||||
get_identifier(definition->identifier.c_str()), this->current_expression);
|
get_identifier(definition->identifier.identifier.c_str()), this->current_expression);
|
||||||
|
|
||||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
TREE_PUBLIC(definition_tree) = definition->identifier.exported;
|
||||||
TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
|
TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.identifier.c_str());
|
||||||
|
|
||||||
auto result = this->symbols->enter(definition->identifier, definition_tree);
|
auto result = this->symbols->enter(definition->identifier.identifier, definition_tree);
|
||||||
gcc_assert(result);
|
gcc_assert(result);
|
||||||
|
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
@ -878,8 +878,8 @@ namespace elna::gcc
|
|||||||
|
|
||||||
location_t declaration_location = get_location(&declaration->position());
|
location_t declaration_location = get_location(&declaration->position());
|
||||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||||
get_identifier(declaration->identifier.c_str()), this->current_expression);
|
get_identifier(declaration->identifier.identifier.c_str()), this->current_expression);
|
||||||
bool result = this->symbols->enter(declaration->identifier, declaration_tree);
|
bool result = this->symbols->enter(declaration->identifier.identifier, declaration_tree);
|
||||||
|
|
||||||
if (POINTER_TYPE_P(this->current_expression))
|
if (POINTER_TYPE_P(this->current_expression))
|
||||||
{
|
{
|
||||||
@ -889,7 +889,7 @@ namespace elna::gcc
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||||
declaration->identifier.c_str());
|
declaration->identifier.identifier.c_str());
|
||||||
}
|
}
|
||||||
else if (lang_hooks.decls.global_bindings_p())
|
else if (lang_hooks.decls.global_bindings_p())
|
||||||
{
|
{
|
||||||
@ -1277,6 +1277,13 @@ namespace elna::gcc
|
|||||||
{
|
{
|
||||||
make_if_branch(*branch, goto_check);
|
make_if_branch(*branch, goto_check);
|
||||||
}
|
}
|
||||||
|
if (statement->alternative != nullptr)
|
||||||
|
{
|
||||||
|
enter_scope();
|
||||||
|
visit_statements(*statement->alternative);
|
||||||
|
tree mapping = leave_scope();
|
||||||
|
append_statement(mapping);
|
||||||
|
}
|
||||||
append_statement(branch_end_expression);
|
append_statement(branch_end_expression);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
@ -175,17 +175,22 @@ namespace elna::boot
|
|||||||
virtual literal_expression *is_literal();
|
virtual literal_expression *is_literal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct identifier_definition
|
||||||
|
{
|
||||||
|
std::string identifier;
|
||||||
|
bool exported;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol definition.
|
* Symbol definition.
|
||||||
*/
|
*/
|
||||||
class definition : public node
|
class definition : public node
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
definition(const struct position position, const std::string& identifier, const bool exported);
|
definition(const struct position position, identifier_definition identifier);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::string identifier;
|
const identifier_definition identifier;
|
||||||
const bool exported;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,8 +303,8 @@ namespace elna::boot
|
|||||||
std::shared_ptr<type_expression> m_variable_type;
|
std::shared_ptr<type_expression> m_variable_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration(const struct position position, identifier_definition identifier,
|
||||||
std::shared_ptr<type_expression> variable_type, const bool exported = false);
|
std::shared_ptr<type_expression> variable_type);
|
||||||
|
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
@ -326,8 +331,8 @@ namespace elna::boot
|
|||||||
expression *m_body;
|
expression *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constant_definition(const struct position position, const std::string& identifier,
|
constant_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, expression *body);
|
expression *body);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
expression& body();
|
expression& body();
|
||||||
@ -364,8 +369,8 @@ namespace elna::boot
|
|||||||
block *const body;
|
block *const body;
|
||||||
std::vector<std::string> parameter_names;
|
std::vector<std::string> parameter_names;
|
||||||
|
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, procedure_type_expression *heading, block *body = nullptr);
|
procedure_type_expression *heading, block *body = nullptr);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
procedure_type_expression& heading();
|
procedure_type_expression& heading();
|
||||||
@ -381,8 +386,8 @@ namespace elna::boot
|
|||||||
type_expression *m_body;
|
type_expression *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
type_definition(const struct position position, const std::string& identifier,
|
type_definition(const struct position position, identifier_definition identifier,
|
||||||
const bool exported, type_expression *expression);
|
type_expression *expression);
|
||||||
~type_definition();
|
~type_definition();
|
||||||
|
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
@ -595,10 +600,11 @@ namespace elna::boot
|
|||||||
conditional_statements *m_body;
|
conditional_statements *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<conditional_statements *> branches;
|
const std::vector<conditional_statements *> branches;
|
||||||
const std::vector<statement *> *alternative;
|
const std::vector<statement *> *alternative;
|
||||||
|
|
||||||
if_statement(const struct position position, conditional_statements *body,
|
if_statement(const struct position position, conditional_statements *body,
|
||||||
|
std::vector<conditional_statements *>&& branches,
|
||||||
std::vector<statement *> *alternative = nullptr);
|
std::vector<statement *> *alternative = nullptr);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
@ -628,11 +634,13 @@ namespace elna::boot
|
|||||||
public:
|
public:
|
||||||
const std::vector<conditional_statements *> branches;
|
const std::vector<conditional_statements *> branches;
|
||||||
const std::optional<std::string> label;
|
const std::optional<std::string> label;
|
||||||
|
const std::vector<statement *> *alternative;
|
||||||
|
|
||||||
while_statement(const struct position position, conditional_statements *body,
|
while_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<conditional_statements *>&& branches);
|
std::vector<conditional_statements *>&& branches, std::vector<statement *> *alternative = nullptr);
|
||||||
while_statement(const struct position position, conditional_statements *body,
|
while_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<conditional_statements *>&& branches, const std::string& label);
|
std::vector<conditional_statements *>&& branches, const std::string& label,
|
||||||
|
std::vector<statement *> *alternative = nullptr);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
conditional_statements& body();
|
conditional_statements& body();
|
||||||
|
92
source.elna
92
source.elna
@ -1,7 +1,7 @@
|
|||||||
const
|
const
|
||||||
SEEK_SET* := 0;
|
SEEK_SET* := 0
|
||||||
SEEK_CUR* := 1;
|
SEEK_CUR* := 1
|
||||||
SEEK_END* := 2;
|
SEEK_END* := 2
|
||||||
|
|
||||||
type
|
type
|
||||||
TokenKind* = (
|
TokenKind* = (
|
||||||
@ -65,27 +65,27 @@ type
|
|||||||
_defer,
|
_defer,
|
||||||
exclamation,
|
exclamation,
|
||||||
arrow
|
arrow
|
||||||
);
|
)
|
||||||
Position* = record
|
Position* = record
|
||||||
line: Word;
|
line: Word;
|
||||||
column: Word
|
column: Word
|
||||||
end;
|
end
|
||||||
Location* = record
|
Location* = record
|
||||||
first: Position;
|
first: Position;
|
||||||
last: Position
|
last: Position
|
||||||
end;
|
end
|
||||||
SourceFile* = record
|
SourceFile* = record
|
||||||
buffer: [1024]Char;
|
buffer: [1024]Char;
|
||||||
handle: ^FILE;
|
handle: ^FILE;
|
||||||
size: Word;
|
size: Word;
|
||||||
index: Word
|
index: Word
|
||||||
end;
|
end
|
||||||
FILE* = record end;
|
FILE* = record end
|
||||||
StringBuffer* = record
|
StringBuffer* = record
|
||||||
data: ^Byte;
|
data: ^Byte;
|
||||||
size: Word;
|
size: Word;
|
||||||
capacity: Word
|
capacity: Word
|
||||||
end;
|
end
|
||||||
SourceCode = record
|
SourceCode = record
|
||||||
position: Position;
|
position: Position;
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ type
|
|||||||
empty: proc(^Byte) -> Bool;
|
empty: proc(^Byte) -> Bool;
|
||||||
advance: proc(^Byte);
|
advance: proc(^Byte);
|
||||||
head: proc(^Byte) -> Char
|
head: proc(^Byte) -> Char
|
||||||
end;
|
end
|
||||||
Token* = record
|
Token* = record
|
||||||
kind: TokenKind;
|
kind: TokenKind;
|
||||||
value: union
|
value: union
|
||||||
@ -103,12 +103,12 @@ type
|
|||||||
char_value: Char
|
char_value: Char
|
||||||
end;
|
end;
|
||||||
location: Location
|
location: Location
|
||||||
end;
|
end
|
||||||
CommandLine* = record
|
CommandLine* = record
|
||||||
input: ^Char;
|
input: ^Char;
|
||||||
tokenize: Bool;
|
tokenize: Bool;
|
||||||
syntax_tree: Bool
|
syntax_tree: Bool
|
||||||
end;
|
end
|
||||||
|
|
||||||
(*
|
(*
|
||||||
External procedures.
|
External procedures.
|
||||||
@ -171,9 +171,9 @@ end
|
|||||||
|
|
||||||
proc write_i(value: Int);
|
proc write_i(value: Int);
|
||||||
var
|
var
|
||||||
digit: Int;
|
digit: Int
|
||||||
n: Word;
|
n: Word
|
||||||
buffer: [10]Char;
|
buffer: [10]Char
|
||||||
begin
|
begin
|
||||||
n := 10u;
|
n := 10u;
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ end
|
|||||||
|
|
||||||
proc string_dup(origin: String) -> String;
|
proc string_dup(origin: String) -> String;
|
||||||
var
|
var
|
||||||
copy: ^Char;
|
copy: ^Char
|
||||||
begin
|
begin
|
||||||
copy := cast(malloc(origin.length): ^Char);
|
copy := cast(malloc(origin.length): ^Char);
|
||||||
strncpy(copy, origin.ptr, origin.length);
|
strncpy(copy, origin.ptr, origin.length);
|
||||||
@ -240,7 +240,7 @@ end
|
|||||||
|
|
||||||
proc string_buffer_new() -> StringBuffer;
|
proc string_buffer_new() -> StringBuffer;
|
||||||
var
|
var
|
||||||
result: StringBuffer;
|
result: StringBuffer
|
||||||
begin
|
begin
|
||||||
result.capacity := 64u;
|
result.capacity := 64u;
|
||||||
result.data := malloc(result.capacity);
|
result.data := malloc(result.capacity);
|
||||||
@ -266,7 +266,7 @@ end
|
|||||||
|
|
||||||
proc string_buffer_clear(buffer: ^StringBuffer) -> String;
|
proc string_buffer_clear(buffer: ^StringBuffer) -> String;
|
||||||
var
|
var
|
||||||
result: String;
|
result: String
|
||||||
begin
|
begin
|
||||||
result := String(cast(buffer^.data: ^Char), buffer^.size);
|
result := String(cast(buffer^.data: ^Char), buffer^.size);
|
||||||
buffer^.size := 0u;
|
buffer^.size := 0u;
|
||||||
@ -284,8 +284,8 @@ end
|
|||||||
|
|
||||||
proc read_source(filename: ^Char) -> ^SourceFile;
|
proc read_source(filename: ^Char) -> ^SourceFile;
|
||||||
var
|
var
|
||||||
result: ^SourceFile;
|
result: ^SourceFile
|
||||||
file_handle: ^FILE;
|
file_handle: ^FILE
|
||||||
begin
|
begin
|
||||||
file_handle := fopen(filename, "rb\0".ptr);
|
file_handle := fopen(filename, "rb\0".ptr);
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ end
|
|||||||
|
|
||||||
proc escape_char(escape: Char, result: ^Char) -> Bool;
|
proc escape_char(escape: Char, result: ^Char) -> Bool;
|
||||||
var
|
var
|
||||||
successful: Bool;
|
successful: Bool
|
||||||
begin
|
begin
|
||||||
if escape = 'n' then
|
if escape = 'n' then
|
||||||
result^ := '\n';
|
result^ := '\n';
|
||||||
@ -346,7 +346,7 @@ end
|
|||||||
|
|
||||||
proc source_file_empty(source_input: ^Byte) -> Bool;
|
proc source_file_empty(source_input: ^Byte) -> Bool;
|
||||||
var
|
var
|
||||||
source_file: ^SourceFile;
|
source_file: ^SourceFile
|
||||||
begin
|
begin
|
||||||
source_file := cast(source_input: ^SourceFile);
|
source_file := cast(source_input: ^SourceFile);
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ end
|
|||||||
|
|
||||||
proc source_file_head(source_input: ^Byte) -> Char;
|
proc source_file_head(source_input: ^Byte) -> Char;
|
||||||
var
|
var
|
||||||
source_file: ^SourceFile;
|
source_file: ^SourceFile
|
||||||
begin
|
begin
|
||||||
source_file := cast(source_input: ^SourceFile);
|
source_file := cast(source_input: ^SourceFile);
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ end
|
|||||||
|
|
||||||
proc source_file_advance(source_input: ^Byte);
|
proc source_file_advance(source_input: ^Byte);
|
||||||
var
|
var
|
||||||
source_file: ^SourceFile;
|
source_file: ^SourceFile
|
||||||
begin
|
begin
|
||||||
source_file := cast(source_input: ^SourceFile);
|
source_file := cast(source_input: ^SourceFile);
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ end
|
|||||||
|
|
||||||
proc skip_spaces(source_code: ^SourceCode);
|
proc skip_spaces(source_code: ^SourceCode);
|
||||||
var
|
var
|
||||||
current: Char;
|
current: Char
|
||||||
begin
|
begin
|
||||||
while ~source_code_empty(source_code), loop do
|
while ~source_code_empty(source_code), loop do
|
||||||
current := source_code_head(source_code^);
|
current := source_code_head(source_code^);
|
||||||
@ -426,7 +426,7 @@ end
|
|||||||
|
|
||||||
proc lex_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
|
proc lex_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
|
||||||
var
|
var
|
||||||
content_length: Word;
|
content_length: Word
|
||||||
begin
|
begin
|
||||||
while ~source_code_empty(source_code) & is_ident(source_code_head(source_code^)) do
|
while ~source_code_empty(source_code) & is_ident(source_code_head(source_code^)) do
|
||||||
string_buffer_push(token_content, source_code_head(source_code^));
|
string_buffer_push(token_content, source_code_head(source_code^));
|
||||||
@ -436,7 +436,7 @@ end
|
|||||||
|
|
||||||
proc lex_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
|
proc lex_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
|
||||||
var
|
var
|
||||||
trailing: Word;
|
trailing: Word
|
||||||
begin
|
begin
|
||||||
trailing := 0u;
|
trailing := 0u;
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ end
|
|||||||
|
|
||||||
proc lex_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
|
proc lex_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
|
||||||
var
|
var
|
||||||
successful: Bool;
|
successful: Bool
|
||||||
begin
|
begin
|
||||||
successful := ~source_code_empty(source_code);
|
successful := ~source_code_empty(source_code);
|
||||||
|
|
||||||
@ -481,10 +481,10 @@ end
|
|||||||
|
|
||||||
proc lex_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
|
proc lex_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
|
||||||
var
|
var
|
||||||
token_end, constructed_string: ^Char;
|
token_end, constructed_string: ^Char
|
||||||
token_length: Word;
|
token_length: Word
|
||||||
is_valid: Bool;
|
is_valid: Bool
|
||||||
next_char: Char;
|
next_char: Char
|
||||||
begin
|
begin
|
||||||
is_valid := true;
|
is_valid := true;
|
||||||
|
|
||||||
@ -517,8 +517,8 @@ end
|
|||||||
|
|
||||||
proc print_tokens(tokens: ^Token, tokens_size: Word);
|
proc print_tokens(tokens: ^Token, tokens_size: Word);
|
||||||
var
|
var
|
||||||
current_token: ^Token;
|
current_token: ^Token
|
||||||
i: Word;
|
i: Word
|
||||||
begin
|
begin
|
||||||
i := 0u;
|
i := 0u;
|
||||||
while i < tokens_size do
|
while i < tokens_size do
|
||||||
@ -667,7 +667,7 @@ end
|
|||||||
|
|
||||||
proc categorize_identifier(token_content: String) -> Token;
|
proc categorize_identifier(token_content: String) -> Token;
|
||||||
var
|
var
|
||||||
current_token: Token;
|
current_token: Token
|
||||||
begin
|
begin
|
||||||
if "if" = token_content then
|
if "if" = token_content then
|
||||||
current_token.kind := TokenKind._if
|
current_token.kind := TokenKind._if
|
||||||
@ -737,9 +737,9 @@ end
|
|||||||
|
|
||||||
proc tokenize(source_code: SourceCode, tokens_size: ^Word) -> ^Token;
|
proc tokenize(source_code: SourceCode, tokens_size: ^Word) -> ^Token;
|
||||||
var
|
var
|
||||||
tokens, current_token: ^Token;
|
tokens, current_token: ^Token
|
||||||
first_char: Char;
|
first_char: Char
|
||||||
token_buffer: StringBuffer;
|
token_buffer: StringBuffer
|
||||||
begin
|
begin
|
||||||
tokens_size^ := 0u;
|
tokens_size^ := 0u;
|
||||||
tokens := nil;
|
tokens := nil;
|
||||||
@ -914,9 +914,9 @@ end
|
|||||||
|
|
||||||
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
|
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
|
||||||
var
|
var
|
||||||
parameter: ^^Char;
|
parameter: ^^Char
|
||||||
i: Int;
|
i: Int
|
||||||
result: ^CommandLine;
|
result: ^CommandLine
|
||||||
begin
|
begin
|
||||||
i := 1;
|
i := 1;
|
||||||
result := cast(malloc(#size(CommandLine)): ^CommandLine);
|
result := cast(malloc(#size(CommandLine)): ^CommandLine);
|
||||||
@ -955,11 +955,11 @@ end
|
|||||||
|
|
||||||
proc process(argc: Int, argv: ^^Char) -> Int;
|
proc process(argc: Int, argv: ^^Char) -> Int;
|
||||||
var
|
var
|
||||||
tokens: ^Token;
|
tokens: ^Token
|
||||||
tokens_size: Word;
|
tokens_size: Word
|
||||||
source_code: SourceCode;
|
source_code: SourceCode
|
||||||
command_line: ^CommandLine;
|
command_line: ^CommandLine
|
||||||
return_code: Int;
|
return_code: Int
|
||||||
begin
|
begin
|
||||||
return_code := 0;
|
return_code := 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user