Revert "Allow only one return"

This reverts commit 18602d00a118e69d4ccc45287e89a16b86c1d92e.
This commit is contained in:
Eugen Wissner 2025-03-02 10:45:54 +01:00
parent 75561fd18a
commit 09f204bd16
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
10 changed files with 231 additions and 79 deletions

View File

@ -86,6 +86,24 @@ namespace boot
} }
} }
void empty_visitor::visit(return_statement *statement)
{
expression *return_expression = statement->return_expression();
if (return_expression != nullptr)
{
return_expression->accept(this);
}
}
void empty_visitor::visit(defer_statement *defer)
{
for (statement *const body_statement : defer->statements)
{
body_statement->accept(this);
}
}
void empty_visitor::visit(block *block) void empty_visitor::visit(block *block)
{ {
for (constant_definition *const constant : block->constants) for (constant_definition *const constant : block->constants)
@ -370,9 +388,8 @@ namespace boot
} }
procedure_definition::procedure_definition(const struct position position, const std::string& identifier, procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type> heading, const bool exported, std::shared_ptr<procedure_type> heading, block *body)
block *const body, expression *const returning) : definition(position, identifier, exported), m_heading(heading), body(body)
: definition(position, identifier, exported), m_heading(heading), body(body), returning(returning)
{ {
} }
@ -389,7 +406,6 @@ namespace boot
procedure_definition::~procedure_definition() procedure_definition::~procedure_definition()
{ {
delete body; delete body;
delete returning;
} }
type_definition::type_definition(const struct position position, const std::string& identifier, type_definition::type_definition(const struct position position, const std::string& identifier,
@ -460,6 +476,24 @@ namespace boot
{ {
} }
defer_statement::defer_statement(const struct position position)
: node(position)
{
}
void defer_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
defer_statement::~defer_statement()
{
for (statement *body_statement : statements)
{
delete body_statement;
}
}
designator_expression::designator_expression() designator_expression::designator_expression()
{ {
} }
@ -711,6 +745,26 @@ namespace boot
} }
} }
return_statement::return_statement(const struct position position, expression *return_expression)
: node(position), m_return_expression(return_expression)
{
}
void return_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression *return_statement::return_expression()
{
return m_return_expression;
}
return_statement::~return_statement()
{
delete m_return_expression;
}
void assign_statement::accept(parser_visitor *visitor) void assign_statement::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);

View File

@ -125,6 +125,9 @@ return {
cast { cast {
return yy::parser::make_CAST(this->location); return yy::parser::make_CAST(this->location);
} }
defer {
return yy::parser::make_DEFER(this->location);
}
[A-Za-z_][A-Za-z0-9_]* { [A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location); return yy::parser::make_IDENTIFIER(yytext, this->location);
} }

View File

@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see
RETURN "return" RETURN "return"
BEGIN_BLOCK "begin" BEGIN_BLOCK "begin"
END_BLOCK "end" END_BLOCK "end"
DEFER "defer"
%token OR "or" AND "and" XOR "xor" %token OR "or" AND "and" XOR "xor"
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">=" EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
SHIFT_LEFT "<<" SHIFT_RIGHT ">>" SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
@ -135,12 +136,12 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::procedure_call*> call_expression; %type <elna::boot::procedure_call*> call_expression;
%type <elna::boot::while_statement *> while_statement; %type <elna::boot::while_statement *> while_statement;
%type <elna::boot::if_statement *> if_statement; %type <elna::boot::if_statement *> if_statement;
%type <elna::boot::expression *> return_statement; %type <elna::boot::return_statement *> return_statement;
%type <elna::boot::statement *> statement; %type <elna::boot::statement *> statement;
%type <std::vector<elna::boot::statement *>> statements statement_part; %type <std::vector<elna::boot::statement *>> statements;
%type <elna::boot::procedure_definition *> procedure_definition; %type <elna::boot::procedure_definition *> procedure_definition;
%type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading; %type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions; %type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
%type <elna::boot::type_definition *> type_definition; %type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part; %type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block; %type <elna::boot::block *> block;
@ -148,11 +149,12 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields; %type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields;
%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 <elna::boot::cast_expression *> cast_expression; %type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
%type <std::pair<std::string, bool>> identifier_definition; %type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions; %type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
%% %%
program: program:
constant_part type_part variable_part procedure_definitions "begin" statements "end" "." constant_part type_part variable_part procedure_part "begin" statements "end" "."
{ {
auto tree = new elna::boot::program(elna::boot::make_position(@5)); auto tree = new elna::boot::program(elna::boot::make_position(@5));
@ -164,13 +166,13 @@ program:
driver.tree.reset(tree); driver.tree.reset(tree);
} }
block: constant_part variable_part statement_part block: constant_part variable_part "begin" statements "end"
{ {
$$ = new elna::boot::block(elna::boot::make_position(@1)); $$ = new elna::boot::block(elna::boot::make_position(@3));
std::swap($$->constants, $1); std::swap($$->constants, $1);
std::swap($$->variables, $2); std::swap($$->variables, $2);
std::swap($$->body, $3); std::swap($$->body, $4);
} }
identifier_definition: identifier_definition:
IDENTIFIER "*" IDENTIFIER "*"
@ -205,10 +207,9 @@ procedure_heading:
std::swap($1, $$->parameters); std::swap($1, $$->parameters);
} }
procedure_definition: procedure_definition:
"proc" identifier_definition procedure_heading ";" block return_statement "end" "proc" identifier_definition procedure_heading ";" block
{ {
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
$3, $5, $6);
} }
| "proc" identifier_definition procedure_heading ";" "extern" | "proc" identifier_definition procedure_heading ";" "extern"
{ {
@ -220,7 +221,10 @@ procedure_definitions:
std::swap($$, $2); std::swap($$, $2);
$$.emplace($$.cbegin(), std::move($1)); $$.emplace($$.cbegin(), std::move($1));
} }
| /* no procedure definitions */ {} | procedure_definition { $$.emplace_back(std::move($1)); }
procedure_part:
/* no procedure definitions */ {}
| procedure_definitions { std::swap($$, $1); }
assign_statement: designator_expression ":=" expression assign_statement: designator_expression ":=" expression
{ {
$$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3); $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
@ -275,12 +279,15 @@ if_statement:
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else); $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
std::swap($5, $$->branches); std::swap($5, $$->branches);
} }
return_statement: return_statement: "return" expression
"return" expression
{ {
$$ = $2; $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
}
defer_statement: DEFER statements "end"
{
$$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
std::swap($2, $$->statements);
} }
| /* no return statement */ { $$ = nullptr; }
literal: literal:
INTEGER INTEGER
{ {
@ -451,21 +458,17 @@ statement:
assign_statement { $$ = $1; } assign_statement { $$ = $1; }
| while_statement { $$ = $1; } | while_statement { $$ = $1; }
| if_statement { $$ = $1; } | if_statement { $$ = $1; }
| return_statement { $$ = $1; }
| call_expression { $$ = $1; } | call_expression { $$ = $1; }
| defer_statement { $$ = $1; }
statements: statements:
statement ";" statements statement ";" statements
{ {
std::swap($$, $3); std::swap($$, $3);
$$.emplace($$.cbegin(), $1); $$.insert($$.cbegin(), $1);
}
| statement
{
$$.push_back($1);
} }
| statement { $$.push_back($1); }
| /* no statements */ {} | /* no statements */ {}
statement_part:
"begin" statements { std::swap($$, $2); }
| {}
field_declaration: field_declaration:
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); } IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
required_fields: required_fields:

View File

@ -294,7 +294,6 @@ namespace gcc
if (definition->body != nullptr) if (definition->body != nullptr)
{ {
definition->body->accept(this); definition->body->accept(this);
visit_return(definition->returning);
tree mapping = leave_scope(); tree mapping = leave_scope();
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl; BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
@ -335,7 +334,7 @@ namespace gcc
{ {
BLOCK_SUPERCONTEXT(it) = new_block; BLOCK_SUPERCONTEXT(it) = new_block;
} }
tree bind_expr = build3(BIND_EXPR, void_type_node, variables, f_binding_level->statement_list, new_block); tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
this->symbol_map = this->symbol_map->scope(); this->symbol_map = this->symbol_map->scope();
f_binding_level = f_binding_level->level_chain; f_binding_level = f_binding_level->level_chain;
@ -1085,8 +1084,10 @@ namespace gcc
} }
} }
void generic_visitor::visit_return(boot::expression *const return_expression) void generic_visitor::visit(boot::return_statement *statement)
{ {
boot::expression *return_expression = statement->return_expression();
if (return_expression == nullptr) if (return_expression == nullptr)
{ {
return; return;
@ -1206,5 +1207,11 @@ namespace gcc
this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true); this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
} }
void generic_visitor::visit(boot::defer_statement *statement)
{
enter_scope();
visit_statements(statement->statements);
defer(leave_scope());
}
} }
} }

View File

@ -91,7 +91,40 @@ namespace gcc
void append_statement(tree statement_tree) void append_statement(tree statement_tree)
{ {
append_to_statement_list(statement_tree, &f_binding_level->statement_list); if (!vec_safe_is_empty(f_binding_level->defers))
{
append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
}
else
{
append_to_statement_list(statement_tree, &f_binding_level->statement_list);
}
}
void defer(tree statement_tree)
{
defer_scope new_defer{ statement_tree, alloc_stmt_list() };
vec_safe_insert(f_binding_level->defers, 0, new_defer);
}
tree chain_defer()
{
if (vec_safe_is_empty(f_binding_level->defers))
{
return f_binding_level->statement_list;
}
defer_scope *defer_iterator = f_binding_level->defers->begin();
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
defer_iterator->try_statements, defer_iterator->defer_block);
int i;
FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
{
append_to_statement_list(defer_tree, &defer_iterator->try_statements);
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
defer_iterator->try_statements, defer_iterator->defer_block);
}
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
} }
tree build_field(location_t location, tree record_type, const std::string name, tree type) tree build_field(location_t location, tree record_type, const std::string name, tree type)

View File

@ -63,6 +63,7 @@ namespace boot
class assign_statement; class assign_statement;
class if_statement; class if_statement;
class while_statement; class while_statement;
class return_statement;
class traits_expression; class traits_expression;
class block; class block;
class program; class program;
@ -80,6 +81,7 @@ namespace boot
class dereference_expression; class dereference_expression;
template<typename T> template<typename T>
class number_literal; class number_literal;
class defer_statement;
/** /**
* Interface for AST visitors. * Interface for AST visitors.
@ -96,6 +98,8 @@ namespace boot
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(while_statement *) = 0; virtual void visit(while_statement *) = 0;
virtual void visit(return_statement *) = 0;
virtual void visit(defer_statement *) = 0;
virtual void visit(block *) = 0; virtual void visit(block *) = 0;
virtual void visit(program *) = 0; virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0; virtual void visit(binary_expression *) = 0;
@ -134,6 +138,8 @@ namespace boot
virtual void visit(assign_statement *statement) override; virtual void visit(assign_statement *statement) override;
virtual void visit(if_statement *) override; virtual void visit(if_statement *) override;
virtual void visit(while_statement *) override; virtual void visit(while_statement *) override;
virtual void visit(return_statement *) override;
virtual void visit(defer_statement *defer) override;
virtual void visit(block *block) override; virtual void visit(block *block) override;
virtual void visit(program *program) override; virtual void visit(program *program) override;
virtual void visit(binary_expression *expression) override; virtual void visit(binary_expression *expression) override;
@ -360,11 +366,9 @@ namespace boot
public: public:
block *const body; block *const body;
expression *const returning;
procedure_definition(const struct position position, const std::string& identifier, procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type> heading, const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr);
block *const body = nullptr, expression *const returning = nullptr);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
procedure_type& heading(); procedure_type& heading();
@ -435,6 +439,19 @@ namespace boot
virtual ~conditional_statements(); virtual ~conditional_statements();
}; };
class return_statement : public statement
{
expression *m_return_expression{ nullptr };
public:
return_statement(const struct position position, expression *return_expression);
virtual void accept(parser_visitor *visitor) override;
expression *return_expression();
virtual ~return_statement() override;
};
class designator_expression : public expression class designator_expression : public expression
{ {
public: public:
@ -627,6 +644,17 @@ namespace boot
} }
}; };
class defer_statement : public statement
{
public:
std::vector<statement *> statements;
defer_statement(const struct position position);
virtual void accept(parser_visitor *visitor) override;
virtual ~defer_statement() override;
};
class binary_expression : public expression class binary_expression : public expression
{ {
expression *m_lhs; expression *m_lhs;

View File

@ -60,42 +60,43 @@ namespace gcc
void build_record_call(location_t call_location, void build_record_call(location_t call_location,
tree symbol, const std::vector<boot::expression *>& arguments); tree symbol, const std::vector<boot::expression *>& arguments);
void visit_statements(const std::vector<boot::statement *>& statements); void visit_statements(const std::vector<boot::statement *>& statements);
void visit_return(boot::expression *const return_expression);
public: public:
generic_visitor(std::shared_ptr<symbol_table> symbol_table); generic_visitor(std::shared_ptr<symbol_table> symbol_table);
virtual void visit(boot::program *program) override; void visit(boot::program *program) override;
virtual void visit(boot::procedure_definition *definition) override; void visit(boot::procedure_definition *definition) override;
virtual void visit(boot::procedure_call *call) override; void visit(boot::procedure_call *call) override;
virtual void visit(boot::cast_expression *expression) override; void visit(boot::cast_expression *expression) override;
virtual void visit(boot::traits_expression *trait) override; void visit(boot::traits_expression *trait) override;
virtual void visit(boot::number_literal<std::int32_t> *literal) override; void visit(boot::number_literal<std::int32_t> *literal) override;
virtual void visit(boot::number_literal<std::uint32_t> *literal) override; void visit(boot::number_literal<std::uint32_t> *literal) override;
virtual void visit(boot::number_literal<double> *literal) override; void visit(boot::number_literal<double> *literal) override;
virtual void visit(boot::number_literal<bool> *boolean) override; void visit(boot::number_literal<bool> *boolean) override;
virtual void visit(boot::number_literal<unsigned char> *character) override; void visit(boot::number_literal<unsigned char> *character) override;
virtual void visit(boot::number_literal<std::nullptr_t> *) override; void visit(boot::number_literal<std::nullptr_t> *) override;
virtual void visit(boot::number_literal<std::string> *string) override; void visit(boot::number_literal<std::string> *string) override;
virtual void visit(boot::binary_expression *expression) override; void visit(boot::binary_expression *expression) override;
virtual void visit(boot::unary_expression *expression) override; void visit(boot::unary_expression *expression) override;
virtual void visit(boot::constant_definition *definition) override; void visit(boot::constant_definition *definition) override;
virtual void visit(boot::type_definition *definition) override; void visit(boot::type_definition *definition) override;
virtual void visit(boot::variable_declaration *declaration) override; void visit(boot::variable_declaration *declaration) override;
virtual void visit(boot::variable_expression *expression) override; void visit(boot::variable_expression *expression) override;
virtual void visit(boot::array_access_expression *expression) override; void visit(boot::array_access_expression *expression) override;
virtual void visit(boot::field_access_expression *expression) override; void visit(boot::field_access_expression *expression) override;
virtual void visit(boot::dereference_expression *expression) override; void visit(boot::dereference_expression *expression) override;
virtual void visit(boot::block *block) override; void visit(boot::block *block) override;
virtual void visit(boot::assign_statement *statement) override; void visit(boot::assign_statement *statement) override;
virtual void visit(boot::if_statement *statement) override; void visit(boot::if_statement *statement) override;
virtual void visit(boot::while_statement *statement) override; void visit(boot::while_statement *statement) override;
virtual void visit(boot::basic_type *type) override; void visit(boot::basic_type *type) override;
virtual void visit(boot::array_type *type) override; void visit(boot::array_type *type) override;
virtual void visit(boot::pointer_type *type) override; void visit(boot::pointer_type *type) override;
virtual void visit(boot::record_type *type) override; void visit(boot::record_type *type) override;
virtual void visit(boot::union_type *type) override; void visit(boot::union_type *type) override;
virtual void visit(boot::procedure_type *type) override; void visit(boot::procedure_type *type) override;
void visit(boot::return_statement *statement) override;
void visit(boot::defer_statement *statement) override;
}; };
} }
} }

View File

@ -72,6 +72,8 @@ namespace gcc
bool is_assignable_from(tree assignee, tree assignment); bool is_assignable_from(tree assignee, tree assignment);
void append_statement(tree statement_tree); void append_statement(tree statement_tree);
void defer(tree statement_tree);
tree chain_defer();
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right); tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
tree build_binary_operation(bool condition, boot::binary_expression *expression, tree build_binary_operation(bool condition, boot::binary_expression *expression,

View File

@ -58,6 +58,12 @@ struct GTY (()) lang_decl
{ {
}; };
struct GTY (()) defer_scope
{
tree defer_block;
tree try_statements;
};
struct GTY ((chain_next ("%h.level_chain"))) binding_level struct GTY ((chain_next ("%h.level_chain"))) binding_level
{ {
// A block chain is needed to call defer statements beloning to each block. // A block chain is needed to call defer statements beloning to each block.
@ -68,6 +74,9 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level
// Statements before the first defer has been seen. // Statements before the first defer has been seen.
tree statement_list; tree statement_list;
// Defer statement coupled with statements following it.
vec<defer_scope, va_gc> *defers;
}; };
struct GTY (()) language_function struct GTY (()) language_function

View File

@ -140,6 +140,7 @@ proc exit(code: Int) -> !; extern
Standard procedures. Standard procedures.
*) *)
proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte; proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte;
begin
return realloc(ptr, n * size) return realloc(ptr, n * size)
end end
@ -197,26 +198,32 @@ begin
end end
proc is_digit(c: Char) -> Bool; proc is_digit(c: Char) -> Bool;
begin
return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int) return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int)
end end
proc is_alpha(c: Char) -> Bool; proc is_alpha(c: Char) -> Bool;
begin
return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int) return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int)
end end
proc is_alnum(c: Char) -> Bool; proc is_alnum(c: Char) -> Bool;
begin
return is_digit(c) or is_alpha(c) return is_digit(c) or is_alpha(c)
end end
proc is_space(c: Char) -> Bool; proc is_space(c: Char) -> Bool;
begin
return c = ' ' or c = '\n' or c = '\t' return c = ' ' or c = '\n' or c = '\t'
end end
proc substring(string: String, start: Word, count: Word) -> String; proc substring(string: String, start: Word, count: Word) -> String;
begin
return String(string.ptr + start, count) return String(string.ptr + start, count)
end end
proc open_substring(string: String, start: Word) -> String; proc open_substring(string: String, start: Word) -> String;
begin
return substring(string, start, string.length - start) return substring(string, start, string.length - start)
end end
@ -270,6 +277,7 @@ end
*) *)
proc make_position() -> Position; proc make_position() -> Position;
begin
return Position(1u, 1u) return Position(1u, 1u)
end end
@ -285,7 +293,7 @@ begin
result^.handle := file_handle; result^.handle := file_handle;
result^.size := 0u; result^.size := 0u;
result^.index := 1u result^.index := 1u
end end;
return result return result
end end
@ -344,7 +352,7 @@ begin
if source_file^.index > source_file^.size then if source_file^.index > source_file^.size then
source_file^.size := fread(cast(@source_file^.buffer: ^Byte), 1u, 1024u, source_file^.handle); source_file^.size := fread(cast(@source_file^.buffer: ^Byte), 1u, 1024u, source_file^.handle);
source_file^.index := 1u source_file^.index := 1u
end end;
return source_file^.size = 0u return source_file^.size = 0u
end end
@ -368,10 +376,12 @@ begin
end end
proc source_code_empty(source_code: ^SourceCode) -> Bool; proc source_code_empty(source_code: ^SourceCode) -> Bool;
begin
return source_code^.empty(source_code^.input) return source_code^.empty(source_code^.input)
end end
proc source_code_head(source_code: SourceCode) -> Char; proc source_code_head(source_code: SourceCode) -> Char;
begin
return source_code.head(source_code.input) return source_code.head(source_code.input)
end end
@ -388,6 +398,7 @@ begin
end end
proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool; proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool;
begin
return not source_code_empty(source_code) and source_code_head(source_code^) = expected return not source_code_empty(source_code) and source_code_head(source_code^) = expected
end end
@ -402,6 +413,7 @@ begin
end end
proc is_ident(char: Char) -> Bool; proc is_ident(char: Char) -> Bool;
begin
return is_alnum(char) or char = '_' return is_alnum(char) or char = '_'
end end
@ -433,7 +445,7 @@ begin
trailing := 0u trailing := 0u
end; end;
source_code_advance(source_code) source_code_advance(source_code)
end end;
return trailing = 2u return trailing = 2u
end end
@ -456,7 +468,7 @@ begin
end; end;
if successful then if successful then
source_code_advance(source_code) source_code_advance(source_code)
end end;
return successful return successful
end end
@ -481,7 +493,7 @@ begin
source_code_advance(source_code) source_code_advance(source_code)
else else
is_valid := false is_valid := false
end end;
return is_valid return is_valid
end end
@ -710,7 +722,7 @@ begin
else else
current_token.kind := TOKEN_IDENTIFIER; current_token.kind := TOKEN_IDENTIFIER;
current_token.value.string := string_dup(token_content) current_token.value.string := string_dup(token_content)
end end;
return current_token return current_token
end end
@ -887,7 +899,7 @@ begin
write_c(first_char); write_c(first_char);
write_s("\".\n") write_s("\".\n")
end end
end end;
return tokens return tokens
end end
@ -904,7 +916,7 @@ begin
result^.syntax_tree := false; result^.syntax_tree := false;
result^.input := nil; result^.input := nil;
while i < argc and result <> nil do while i < argc do
parameter := argv + i; parameter := argv + i;
if strcmp(parameter^, "--tokenize\0".ptr) = 0 then if strcmp(parameter^, "--tokenize\0".ptr) = 0 then
@ -920,15 +932,15 @@ begin
write_z(parameter^); write_z(parameter^);
write_s(".\n"); write_s(".\n");
result := nil return nil
end; end;
i := i + 1 i := i + 1
end; end;
if result <> nil and result^.input = nil then if result^.input = nil then
write_s("Fatal error: no input files.\n"); write_s("Fatal error: no input files.\n");
result := nil return nil
end end;
return result return result
end end
@ -969,7 +981,7 @@ begin
if command_line^.tokenize then if command_line^.tokenize then
print_tokens(tokens, tokens_size) print_tokens(tokens, tokens_size)
end end
end end;
return return_code return return_code
end end