Label loops
This commit is contained in:
parent
6fd1bda112
commit
8ec407515a
86
boot/ast.cc
86
boot/ast.cc
@ -33,36 +33,6 @@ namespace elna::boot
|
|||||||
return this->source_position;
|
return this->source_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
assign_statement *statement::is_assign()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if_statement *statement::is_if()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
while_statement *statement::is_while()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return_statement *statement::is_return()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
defer_statement *statement::is_defer()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
procedure_call *statement::is_call_statement()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
cast_expression *expression::is_cast()
|
cast_expression *expression::is_cast()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -447,11 +417,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
defer_statement *defer_statement::is_defer()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
defer_statement::~defer_statement()
|
defer_statement::~defer_statement()
|
||||||
{
|
{
|
||||||
for (statement *body_statement : statements)
|
for (statement *body_statement : statements)
|
||||||
@ -676,11 +641,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_call *procedure_call::is_call_statement()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
procedure_call *procedure_call::is_call_expression()
|
procedure_call *procedure_call::is_call_expression()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -754,8 +714,8 @@ namespace elna::boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional_statements::conditional_statements(expression *prerequisite)
|
conditional_statements::conditional_statements(expression *prerequisite, std::vector<statement *>&& statements)
|
||||||
: m_prerequisite(prerequisite)
|
: m_prerequisite(prerequisite), statements(std::move(statements))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,11 +743,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_statement *return_statement::is_return()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
return_statement::~return_statement()
|
return_statement::~return_statement()
|
||||||
{
|
{
|
||||||
delete this->return_expression;
|
delete this->return_expression;
|
||||||
@ -820,11 +775,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
assign_statement *assign_statement::is_assign()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
variable_expression *designator_expression::is_variable()
|
variable_expression *designator_expression::is_variable()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -871,11 +821,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if_statement *if_statement::is_if()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_statements& if_statement::body()
|
conditional_statements& if_statement::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
@ -891,8 +836,26 @@ namespace elna::boot
|
|||||||
delete this->alternative;
|
delete this->alternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
while_statement::while_statement(const struct position position, conditional_statements *body)
|
escape_statement::escape_statement(const struct position position,
|
||||||
: node(position), m_body(body)
|
escape_direction direction, const std::string& label)
|
||||||
|
: node(position), direction(direction), label(label)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void escape_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,11 +864,6 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
while_statement *while_statement::is_while()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_statements& while_statement::body()
|
conditional_statements& while_statement::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
|
@ -125,6 +125,12 @@ or {
|
|||||||
return {
|
return {
|
||||||
return yy::parser::make_RETURN(this->location);
|
return yy::parser::make_RETURN(this->location);
|
||||||
}
|
}
|
||||||
|
break {
|
||||||
|
return yy::parser::make_BREAK(this->location);
|
||||||
|
}
|
||||||
|
repeat {
|
||||||
|
return yy::parser::make_REPEAT(this->location);
|
||||||
|
}
|
||||||
cast {
|
cast {
|
||||||
return yy::parser::make_CAST(this->location);
|
return yy::parser::make_CAST(this->location);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,8 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
ELSE "else"
|
ELSE "else"
|
||||||
ELSIF "elsif"
|
ELSIF "elsif"
|
||||||
RETURN "return"
|
RETURN "return"
|
||||||
|
REPEAT "repeat"
|
||||||
|
BREAK "break"
|
||||||
BEGIN_BLOCK "begin"
|
BEGIN_BLOCK "begin"
|
||||||
END_BLOCK "end"
|
END_BLOCK "end"
|
||||||
DEFER "defer"
|
DEFER "defer"
|
||||||
@ -247,8 +249,7 @@ cast_expression: "cast" "(" expression ":" type_expression ")"
|
|||||||
elsif_do_statements:
|
elsif_do_statements:
|
||||||
"elsif" expression "do" statements elsif_do_statements
|
"elsif" expression "do" statements elsif_do_statements
|
||||||
{
|
{
|
||||||
boot::conditional_statements *branch = new boot::conditional_statements($2);
|
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
|
||||||
std::swap(branch->statements, $4);
|
|
||||||
std::swap($5, $$);
|
std::swap($5, $$);
|
||||||
$$.emplace($$.begin(), branch);
|
$$.emplace($$.begin(), branch);
|
||||||
}
|
}
|
||||||
@ -256,18 +257,21 @@ elsif_do_statements:
|
|||||||
else_statements:
|
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" expression "do" statements elsif_do_statements "end"
|
while_statement:
|
||||||
|
"while" expression "do" statements elsif_do_statements "end"
|
||||||
{
|
{
|
||||||
auto body = new boot::conditional_statements($2);
|
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
|
||||||
std::swap($4, body->statements);
|
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5));
|
||||||
$$ = new boot::while_statement(boot::make_position(@1), body);
|
}
|
||||||
std::swap($5, $$->branches);
|
| "while" expression "," IDENTIFIER "do" statements elsif_do_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);
|
||||||
}
|
}
|
||||||
elsif_then_statements:
|
elsif_then_statements:
|
||||||
"elsif" expression "then" statements elsif_then_statements
|
"elsif" expression "then" statements elsif_then_statements
|
||||||
{
|
{
|
||||||
boot::conditional_statements *branch = new boot::conditional_statements($2);
|
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
|
||||||
std::swap(branch->statements, $4);
|
|
||||||
std::swap($5, $$);
|
std::swap($5, $$);
|
||||||
$$.emplace($$.begin(), branch);
|
$$.emplace($$.begin(), branch);
|
||||||
}
|
}
|
||||||
@ -417,13 +421,16 @@ statement:
|
|||||||
| while_statement { $$ = $1; }
|
| while_statement { $$ = $1; }
|
||||||
| "if" expression "then" statements elsif_then_statements else_statements "end"
|
| "if" expression "then" statements elsif_then_statements else_statements "end"
|
||||||
{
|
{
|
||||||
auto then = new boot::conditional_statements($2);
|
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
|
||||||
std::swap($4, then->statements);
|
|
||||||
auto result = new boot::if_statement(boot::make_position(@1), then, $6);
|
auto result = new boot::if_statement(boot::make_position(@1), then, $6);
|
||||||
std::swap($5, result->branches);
|
std::swap($5, result->branches);
|
||||||
$$ = result;
|
$$ = result;
|
||||||
}
|
}
|
||||||
| return_statement { $$ = $1; }
|
| return_statement { $$ = $1; }
|
||||||
|
| "break" IDENTIFIER
|
||||||
|
{ $$ = new boot::escape_statement(boot::make_position(@1), boot::escape_direction::end, $2); }
|
||||||
|
| "repeat" IDENTIFIER
|
||||||
|
{ $$ = new boot::escape_statement(boot::make_position(@1), boot::escape_direction::begin, $2); }
|
||||||
| call_expression { $$ = $1; }
|
| call_expression { $$ = $1; }
|
||||||
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
||||||
| "case" expression "of" switch_cases else_statements "end"
|
| "case" expression "of" switch_cases else_statements "end"
|
||||||
@ -523,7 +530,7 @@ 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), $1.first, $1.second, $3);
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,10 @@ namespace elna::boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void declaration_visitor::visit(escape_statement *)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void declaration_visitor::visit(while_statement *statement)
|
void declaration_visitor::visit(while_statement *statement)
|
||||||
{
|
{
|
||||||
statement->body().prerequisite().accept(this);
|
statement->body().prerequisite().accept(this);
|
||||||
|
@ -1174,7 +1174,7 @@ namespace elna::gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::if_statement *statement)
|
void generic_visitor::visit(boot::if_statement *statement)
|
||||||
{
|
{
|
||||||
tree endif_label_decl = build_label_decl("endif", UNKNOWN_LOCATION);
|
tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION);
|
||||||
tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
|
tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
|
||||||
|
|
||||||
make_if_branch(statement->body(), goto_endif);
|
make_if_branch(statement->body(), goto_endif);
|
||||||
@ -1202,7 +1202,7 @@ namespace elna::gcc
|
|||||||
if (TREE_TYPE(this->current_expression) != elna_bool_type_node)
|
if (TREE_TYPE(this->current_expression) != elna_bool_type_node)
|
||||||
{
|
{
|
||||||
error_at(get_location(&branch.prerequisite().position()),
|
error_at(get_location(&branch.prerequisite().position()),
|
||||||
"expected expression of boolean type but its type is %s",
|
"Expected expression of boolean type but its type is %s",
|
||||||
print_type(TREE_TYPE(this->current_expression)).c_str());
|
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
@ -1229,13 +1229,46 @@ namespace elna::gcc
|
|||||||
append_statement(else_label_expr);
|
append_statement(else_label_expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(boot::escape_statement *statement)
|
||||||
|
{
|
||||||
|
for (const auto& [begin, end] : this->loops)
|
||||||
|
{
|
||||||
|
if (statement->label == IDENTIFIER_POINTER(DECL_NAME(begin)))
|
||||||
|
{
|
||||||
|
tree target_declaration{ NULL_TREE };
|
||||||
|
|
||||||
|
switch (statement->direction)
|
||||||
|
{
|
||||||
|
case boot::escape_direction::begin:
|
||||||
|
target_declaration = begin;
|
||||||
|
break;
|
||||||
|
case boot::escape_direction::end:
|
||||||
|
target_declaration = end;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gcc_unreachable();
|
||||||
|
}
|
||||||
|
tree goto_expression = build1(GOTO_EXPR, void_type_node, target_declaration);
|
||||||
|
TREE_USED(target_declaration) = 1;
|
||||||
|
append_statement(goto_expression);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error_at(get_location(&statement->position()), "Unknown loop labeled '%s'", statement->label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::while_statement *statement)
|
void generic_visitor::visit(boot::while_statement *statement)
|
||||||
{
|
{
|
||||||
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
|
std::string loop_identifier = statement->label.value_or("while");
|
||||||
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
|
location_t prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||||
|
tree prerequisite_label_decl = build_label_decl(loop_identifier.c_str(), prerequisite_location);
|
||||||
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
|
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
|
||||||
void_type_node, prerequisite_label_decl);
|
void_type_node, prerequisite_label_decl);
|
||||||
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
|
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
|
||||||
|
tree branch_end_declaration = build_label_decl(loop_identifier.c_str(), UNKNOWN_LOCATION);
|
||||||
|
tree branch_end_expression = build1_loc(UNKNOWN_LOCATION, LABEL_EXPR, void_type_node, branch_end_declaration);
|
||||||
|
|
||||||
|
this->loops.push_front({ prerequisite_label_decl, branch_end_declaration });
|
||||||
|
|
||||||
append_statement(prerequisite_label_expr);
|
append_statement(prerequisite_label_expr);
|
||||||
make_if_branch(statement->body(), goto_check);
|
make_if_branch(statement->body(), goto_check);
|
||||||
@ -1244,6 +1277,7 @@ namespace elna::gcc
|
|||||||
{
|
{
|
||||||
make_if_branch(*branch, goto_check);
|
make_if_branch(*branch, goto_check);
|
||||||
}
|
}
|
||||||
|
append_statement(branch_end_expression);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
#include "elna/boot/result.h"
|
#include "elna/boot/result.h"
|
||||||
|
|
||||||
namespace elna::boot
|
namespace elna::boot
|
||||||
@ -52,6 +53,12 @@ namespace elna::boot
|
|||||||
minus
|
minus
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class escape_direction
|
||||||
|
{
|
||||||
|
begin,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
|
||||||
class variable_declaration;
|
class variable_declaration;
|
||||||
class constant_definition;
|
class constant_definition;
|
||||||
class procedure_definition;
|
class procedure_definition;
|
||||||
@ -60,6 +67,7 @@ namespace elna::boot
|
|||||||
class cast_expression;
|
class cast_expression;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
|
class escape_statement;
|
||||||
class while_statement;
|
class while_statement;
|
||||||
class return_statement;
|
class return_statement;
|
||||||
class case_statement;
|
class case_statement;
|
||||||
@ -99,6 +107,7 @@ namespace elna::boot
|
|||||||
virtual void visit(traits_expression *) = 0;
|
virtual void visit(traits_expression *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
virtual void visit(if_statement *) = 0;
|
virtual void visit(if_statement *) = 0;
|
||||||
|
virtual void visit(escape_statement *) = 0;
|
||||||
virtual void visit(while_statement *) = 0;
|
virtual void visit(while_statement *) = 0;
|
||||||
virtual void visit(return_statement *) = 0;
|
virtual void visit(return_statement *) = 0;
|
||||||
virtual void visit(defer_statement *) = 0;
|
virtual void visit(defer_statement *) = 0;
|
||||||
@ -152,13 +161,6 @@ namespace elna::boot
|
|||||||
|
|
||||||
class statement : public virtual node
|
class statement : public virtual node
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
virtual assign_statement *is_assign();
|
|
||||||
virtual if_statement *is_if();
|
|
||||||
virtual while_statement *is_while();
|
|
||||||
virtual return_statement *is_return();
|
|
||||||
virtual defer_statement *is_defer();
|
|
||||||
virtual procedure_call *is_call_statement();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class expression : public virtual node
|
class expression : public virtual node
|
||||||
@ -428,9 +430,9 @@ namespace elna::boot
|
|||||||
expression *m_prerequisite;
|
expression *m_prerequisite;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<statement *> statements;
|
const std::vector<statement *> statements;
|
||||||
|
|
||||||
conditional_statements(expression *prerequisite);
|
conditional_statements(expression *prerequisite, std::vector<statement *>&& statements);
|
||||||
|
|
||||||
expression& prerequisite();
|
expression& prerequisite();
|
||||||
|
|
||||||
@ -444,7 +446,6 @@ namespace elna::boot
|
|||||||
|
|
||||||
return_statement(const struct position position, expression *return_expression = nullptr);
|
return_statement(const struct position position, expression *return_expression = nullptr);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
virtual return_statement *is_return() override;
|
|
||||||
|
|
||||||
virtual ~return_statement() override;
|
virtual ~return_statement() override;
|
||||||
};
|
};
|
||||||
@ -558,7 +559,6 @@ namespace elna::boot
|
|||||||
|
|
||||||
procedure_call(const struct position position, designator_expression *callable);
|
procedure_call(const struct position position, designator_expression *callable);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
virtual procedure_call *is_call_statement() override;
|
|
||||||
virtual procedure_call *is_call_expression() override;
|
virtual procedure_call *is_call_expression() override;
|
||||||
|
|
||||||
designator_expression& callable();
|
designator_expression& callable();
|
||||||
@ -585,7 +585,6 @@ namespace elna::boot
|
|||||||
expression& rvalue();
|
expression& rvalue();
|
||||||
|
|
||||||
virtual ~assign_statement() override;
|
virtual ~assign_statement() override;
|
||||||
assign_statement *is_assign() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -602,13 +601,23 @@ namespace elna::boot
|
|||||||
if_statement(const struct position position, conditional_statements *body,
|
if_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<statement *> *alternative = nullptr);
|
std::vector<statement *> *alternative = nullptr);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
virtual if_statement *is_if() override;
|
|
||||||
|
|
||||||
conditional_statements& body();
|
conditional_statements& body();
|
||||||
|
|
||||||
virtual ~if_statement() override;
|
virtual ~if_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class escape_statement : public statement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const escape_direction direction;
|
||||||
|
const std::string label;
|
||||||
|
|
||||||
|
escape_statement(const struct position position,
|
||||||
|
escape_direction direction, const std::string& label);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* While-statement.
|
* While-statement.
|
||||||
*/
|
*/
|
||||||
@ -617,10 +626,14 @@ namespace elna::boot
|
|||||||
conditional_statements *m_body;
|
conditional_statements *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<conditional_statements *> branches;
|
const std::vector<conditional_statements *> branches;
|
||||||
while_statement(const struct position position, conditional_statements *body);
|
const std::optional<std::string> label;
|
||||||
|
|
||||||
|
while_statement(const struct position position, conditional_statements *body,
|
||||||
|
std::vector<conditional_statements *>&& branches);
|
||||||
|
while_statement(const struct position position, conditional_statements *body,
|
||||||
|
std::vector<conditional_statements *>&& branches, const std::string& label);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
while_statement *is_while() override;
|
|
||||||
|
|
||||||
conditional_statements& body();
|
conditional_statements& body();
|
||||||
|
|
||||||
@ -676,7 +689,6 @@ namespace elna::boot
|
|||||||
|
|
||||||
defer_statement(const struct position position, std::vector<statement *>&& statements);
|
defer_statement(const struct position position, std::vector<statement *>&& statements);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
defer_statement *is_defer() override;
|
|
||||||
|
|
||||||
virtual ~defer_statement() override;
|
virtual ~defer_statement() override;
|
||||||
};
|
};
|
||||||
|
@ -75,6 +75,7 @@ namespace elna::boot
|
|||||||
void visit(procedure_definition *definition) override;
|
void visit(procedure_definition *definition) override;
|
||||||
void visit(assign_statement *statement) override;
|
void visit(assign_statement *statement) override;
|
||||||
void visit(if_statement *statement) override;
|
void visit(if_statement *statement) override;
|
||||||
|
void visit(escape_statement *) override;
|
||||||
void visit(while_statement *statement) override;
|
void visit(while_statement *statement) override;
|
||||||
void visit(return_statement *statement) override;
|
void visit(return_statement *statement) override;
|
||||||
void visit(defer_statement *statement) override;
|
void visit(defer_statement *statement) override;
|
||||||
|
@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
#include "tree-iterator.h"
|
#include "tree-iterator.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <forward_list>
|
||||||
|
|
||||||
namespace elna::gcc
|
namespace elna::gcc
|
||||||
{
|
{
|
||||||
@ -45,6 +46,7 @@ namespace elna::gcc
|
|||||||
tree current_expression{ NULL_TREE };
|
tree current_expression{ NULL_TREE };
|
||||||
std::shared_ptr<symbol_table> symbols;
|
std::shared_ptr<symbol_table> symbols;
|
||||||
std::unordered_map<std::string, tree> unresolved;
|
std::unordered_map<std::string, tree> unresolved;
|
||||||
|
std::forward_list<std::pair<tree, tree>> loops;
|
||||||
|
|
||||||
void declare_procedure(boot::procedure_definition *const definition);
|
void declare_procedure(boot::procedure_definition *const definition);
|
||||||
tree build_procedure_type(boot::procedure_type_expression& type);
|
tree build_procedure_type(boot::procedure_type_expression& type);
|
||||||
@ -100,6 +102,7 @@ namespace elna::gcc
|
|||||||
void visit(boot::block *block) override;
|
void visit(boot::block *block) override;
|
||||||
void visit(boot::assign_statement *statement) override;
|
void visit(boot::assign_statement *statement) override;
|
||||||
void visit(boot::if_statement *statement) override;
|
void visit(boot::if_statement *statement) override;
|
||||||
|
void visit(boot::escape_statement *statement) override;
|
||||||
void visit(boot::while_statement *statement) override;
|
void visit(boot::while_statement *statement) override;
|
||||||
void visit(boot::named_type_expression *type) override;
|
void visit(boot::named_type_expression *type) override;
|
||||||
void visit(boot::array_type_expression *type) override;
|
void visit(boot::array_type_expression *type) override;
|
||||||
|
16
source.elna
16
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* = (
|
||||||
@ -404,9 +404,15 @@ begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
proc skip_spaces(source_code: ^SourceCode);
|
proc skip_spaces(source_code: ^SourceCode);
|
||||||
|
var
|
||||||
|
current: Char;
|
||||||
begin
|
begin
|
||||||
while ~source_code_empty(source_code) & is_space(source_code_head(source_code^)) do
|
while ~source_code_empty(source_code), loop do
|
||||||
if source_code_head(source_code^) = '\n' then
|
current := source_code_head(source_code^);
|
||||||
|
|
||||||
|
if ~is_space(current) then
|
||||||
|
break loop
|
||||||
|
elsif current = '\n' then
|
||||||
source_code_break(source_code)
|
source_code_break(source_code)
|
||||||
end;
|
end;
|
||||||
source_code_advance(source_code)
|
source_code_advance(source_code)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user