Support while … else

This commit is contained in:
Eugen Wissner 2025-04-13 18:40:49 +02:00
parent 8ec407515a
commit 1cd44508c3
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
6 changed files with 145 additions and 135 deletions

View File

@ -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)
{ {
} }

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::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 */ {}

View File

@ -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);

View File

@ -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;
} }

View File

@ -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();

View File

@ -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;