Implement defer
This commit is contained in:
23
boot/ast.cc
23
boot/ast.cc
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
Reference in New Issue
Block a user