Implement defer

This commit is contained in:
2025-02-07 22:12:59 +01:00
parent 077de53c74
commit 39f3337c69
12 changed files with 225 additions and 108 deletions

View File

@ -90,6 +90,14 @@ namespace boot
}
}
void empty_visitor::visit(defer_statement *defer)
{
for (statement *const body_statement : defer->statements)
{
body_statement->accept(this);
}
}
void empty_visitor::visit(block *block)
{
for (constant_definition *const constant : block->constants)
@ -204,7 +212,7 @@ namespace boot
{
}
void empty_visitor::visit(string_literal *)
void empty_visitor::visit(number_literal<std::string> *)
{
}
@ -535,19 +543,22 @@ namespace boot
{
}
string_literal::string_literal(const struct position position, const std::string& value)
: literal(position), m_string(value)
defer_statement::defer_statement(const struct position position)
: statement(position)
{
}
void string_literal::accept(parser_visitor *visitor)
void defer_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
const std::string& string_literal::string() const
defer_statement::~defer_statement()
{
return m_string;
for (statement *body_statement : statements)
{
delete body_statement;
}
}
designator_expression::designator_expression(const struct position position)

View File

@ -41,36 +41,36 @@ namespace boot
return m_errors;
}
std::optional<char> escape_char(char escape)
char escape_char(char escape)
{
switch (escape)
{
case 'n':
return std::make_optional<char>('\n');
return '\n';
case 'a':
return std::make_optional<char>('\a');
return '\a';
case 'b':
return std::make_optional<char>('\b');
return '\b';
case 't':
return std::make_optional<char>('\t');
return '\t';
case 'f':
return std::make_optional<char>('\f');
return '\f';
case 'r':
return std::make_optional<char>('\r');
return '\r';
case 'v':
return std::make_optional<char>('\v');
return '\v';
case '\\':
return std::make_optional<char>('\\');
return '\\';
case '\'':
return std::make_optional<char>('\'');
return '\'';
case '"':
return std::make_optional<char>('"');
return '"';
case '?':
return std::make_optional<char>('\?');
return '\?';
case '0':
return std::make_optional<char>('\0');
return '\0';
default:
return std::nullopt;
return escape_invalid_char;
}
}
}

View File

@ -127,6 +127,9 @@ as {
sizeof {
return yy::parser::make_SIZEOF(this->location);
}
defer {
return yy::parser::make_DEFER(this->location);
}
[A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location);
}
@ -155,15 +158,12 @@ sizeof {
return yy::parser::make_CHARACTER(std::string(&character, 1), this->location);
}
'\\[0nabtfrv\\'"?]' {
std::optional<char> escape = elna::boot::escape_char(yytext[2]);
if (escape.has_value())
{
return yy::parser::make_CHARACTER(std::string(&escape.value(), 1), this->location);
}
else
char escape = elna::boot::escape_char(yytext[2]);
if (escape == escape_invalid_char)
{
REJECT;
}
return yy::parser::make_CHARACTER(std::string(&escape, 1), this->location);
}
\"[[:print:]]*\" {
std::string result;
@ -191,15 +191,12 @@ sizeof {
{
++current_position;
std::optional<char> escape = elna::boot::escape_char(*current_position);
if (escape.has_value())
{
result.push_back(escape.value());
}
else
char escape = elna::boot::escape_char(*current_position);
if (escape == elna::boot::escape_invalid_char)
{
REJECT;
}
result.push_back(escape);
}
else
{

View File

@ -71,7 +71,7 @@
%token <bool> BOOLEAN
%token IF WHILE DO THEN ELSE ELSIF RETURN
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
%token BEGIN_BLOCK END_BLOCK EXTERN
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token AND OR NOT CAST AS SIZEOF
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
@ -109,6 +109,7 @@
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> field_list;
%type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list;
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
%%
program:
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
@ -206,11 +207,15 @@ if_statement:
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
std::swap($5, $$->branches);
}
return_statement:
RETURN expression
return_statement: RETURN expression
{
$$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
}
defer_statement: DEFER optional_statements END_BLOCK
{
$$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
std::swap($2, $$->statements);
}
literal:
INTEGER
{
@ -238,7 +243,7 @@ literal:
}
| STRING
{
$$ = new elna::boot::string_literal(elna::boot::make_position(@1), $1);
$$ = new elna::boot::number_literal<std::string>(elna::boot::make_position(@1), $1);
}
operand:
literal { $$ = $1; }
@ -367,6 +372,7 @@ statement:
{
$$ = new elna::boot::call_statement(elna::boot::make_position(@1), $1);
}
| defer_statement { $$ = $1; }
statements:
statement SEMICOLON statements
{