Implement defer
This commit is contained in:
54
boot/ast.cc
54
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> *)
|
||||
{
|
||||
}
|
||||
|
||||
@ -377,8 +385,8 @@ namespace boot
|
||||
}
|
||||
|
||||
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
||||
type_expression *type)
|
||||
: definition(position, identifier), m_type(type)
|
||||
const bool exported, type_expression *type)
|
||||
: definition(position, identifier, exported), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
@ -397,19 +405,14 @@ namespace boot
|
||||
return *m_type;
|
||||
}
|
||||
|
||||
definition::definition(const struct position position, const std::string& identifier)
|
||||
: node(position), m_identifier(identifier)
|
||||
definition::definition(const struct position position, const std::string& identifier, const bool exported)
|
||||
: node(position), identifier(identifier), exported(exported)
|
||||
{
|
||||
}
|
||||
|
||||
std::string& definition::identifier()
|
||||
{
|
||||
return m_identifier;
|
||||
}
|
||||
|
||||
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
||||
literal *body)
|
||||
: definition(position, identifier), m_body(body)
|
||||
const bool exported, literal *body)
|
||||
: definition(position, identifier, exported), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
@ -429,8 +432,8 @@ namespace boot
|
||||
}
|
||||
|
||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||
std::vector<variable_declaration *>&& parameters, type_expression *return_type, block *body)
|
||||
: definition(position, identifier), m_return_type(return_type), m_body(body), parameters(std::move(parameters))
|
||||
const bool exported, type_expression *return_type)
|
||||
: definition(position, identifier, exported), m_return_type(return_type)
|
||||
{
|
||||
}
|
||||
|
||||
@ -444,6 +447,12 @@ namespace boot
|
||||
return m_body;
|
||||
}
|
||||
|
||||
procedure_definition *procedure_definition::add_body(block *procedure_body)
|
||||
{
|
||||
m_body = procedure_body;
|
||||
return this;
|
||||
}
|
||||
|
||||
type_expression *procedure_definition::return_type()
|
||||
{
|
||||
return m_return_type;
|
||||
@ -462,8 +471,8 @@ namespace boot
|
||||
}
|
||||
|
||||
type_definition::type_definition(const struct position position, const std::string& identifier,
|
||||
type_expression *body)
|
||||
: definition(position, identifier), m_body(body)
|
||||
const bool exported, type_expression *body)
|
||||
: definition(position, identifier, exported), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
@ -535,19 +544,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)
|
||||
|
@ -9,10 +9,11 @@ namespace boot
|
||||
{
|
||||
position make_position(const yy::location& location)
|
||||
{
|
||||
return position{
|
||||
static_cast<std::size_t>(location.begin.line),
|
||||
static_cast<std::size_t>(location.begin.column)
|
||||
};
|
||||
position result;
|
||||
result.line = static_cast<std::size_t>(location.begin.line);
|
||||
result.column = static_cast<std::size_t>(location.begin.column);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
syntax_error::syntax_error(const std::string& message,
|
||||
@ -33,7 +34,7 @@ namespace boot
|
||||
|
||||
void driver::error(const yy::location& loc, const std::string& message)
|
||||
{
|
||||
m_errors.emplace_back(std::make_unique<boot::syntax_error>(message, input_file, loc));
|
||||
m_errors.emplace_back(new boot::syntax_error(message, input_file, loc));
|
||||
}
|
||||
|
||||
const std::list<std::unique_ptr<struct error>>& driver::errors() const noexcept
|
||||
@ -41,36 +42,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
|
||||
@ -100,7 +100,7 @@
|
||||
%type <elna::boot::return_statement *> return_statement;
|
||||
%type <elna::boot::statement *> statement;
|
||||
%type <std::vector<elna::boot::statement *>> statements optional_statements;
|
||||
%type <elna::boot::procedure_definition *> procedure_definition;
|
||||
%type <elna::boot::procedure_definition *> procedure_definition procedure_heading;
|
||||
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
|
||||
%type <elna::boot::type_definition *> type_definition;
|
||||
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
||||
@ -109,6 +109,8 @@
|
||||
%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;
|
||||
%type <std::pair<std::string, bool>> identifier_definition;
|
||||
%%
|
||||
program:
|
||||
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||
@ -131,27 +133,31 @@ block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
|
||||
std::swap($$->variables, $2);
|
||||
std::swap($$->body, $4);
|
||||
}
|
||||
identifier_definition:
|
||||
IDENTIFIER MULTIPLICATION
|
||||
{
|
||||
$$ = std::make_pair($1, true);
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = std::make_pair($1, false);
|
||||
}
|
||||
procedure_heading:
|
||||
PROCEDURE identifier_definition formal_parameter_list SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2.first, $2.second);
|
||||
std::swap($3, $$->parameters);
|
||||
}
|
||||
| PROCEDURE identifier_definition formal_parameter_list COLON type_expression SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2.first, $2.second, $5);
|
||||
std::swap($3, $$->parameters);
|
||||
}
|
||||
procedure_definition:
|
||||
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2, std::move($3), nullptr, $5);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2, std::move($3), nullptr, nullptr);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON block SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2, std::move($3), $5, $7);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON EXTERN SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||
$2, std::move($3), $5, nullptr);
|
||||
}
|
||||
procedure_heading block SEMICOLON { $$ = $1->add_body($2); }
|
||||
| procedure_heading EXTERN SEMICOLON { $$ = $1; }
|
||||
procedure_definitions:
|
||||
procedure_definition procedure_definitions
|
||||
{
|
||||
@ -206,11 +212,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 +248,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 +377,7 @@ statement:
|
||||
{
|
||||
$$ = new elna::boot::call_statement(elna::boot::make_position(@1), $1);
|
||||
}
|
||||
| defer_statement { $$ = $1; }
|
||||
statements:
|
||||
statement SEMICOLON statements
|
||||
{
|
||||
@ -407,9 +418,9 @@ type_expression:
|
||||
{
|
||||
$$ = new elna::boot::basic_type_expression(elna::boot::make_position(@1), $1);
|
||||
}
|
||||
variable_declaration: IDENTIFIER COLON type_expression
|
||||
variable_declaration: identifier_definition COLON type_expression
|
||||
{
|
||||
$$ = new elna::boot::variable_declaration(elna::boot::make_position(@1), $1, $3);
|
||||
$$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1.first, $1.second, $3);
|
||||
}
|
||||
variable_declarations:
|
||||
variable_declaration COMMA variable_declarations
|
||||
@ -421,9 +432,9 @@ variable_declarations:
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
||||
constant_definition: IDENTIFIER EQUALS literal SEMICOLON
|
||||
constant_definition: identifier_definition EQUALS literal SEMICOLON
|
||||
{
|
||||
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1, $3);
|
||||
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||
}
|
||||
constant_definitions:
|
||||
constant_definition constant_definitions
|
||||
@ -436,9 +447,9 @@ constant_part:
|
||||
/* no constant definitions */ {}
|
||||
| CONST {}
|
||||
| CONST constant_definitions { std::swap($$, $2); }
|
||||
type_definition: IDENTIFIER EQUALS type_expression
|
||||
type_definition: identifier_definition EQUALS type_expression
|
||||
{
|
||||
$$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1, $3);
|
||||
$$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||
}
|
||||
type_definitions:
|
||||
type_definition COMMA type_definitions
|
||||
|
Reference in New Issue
Block a user