Allow declaring type synonyms

This commit is contained in:
2025-01-07 14:37:30 +01:00
parent ed1bb621d6
commit 2d61828903
13 changed files with 274 additions and 97 deletions

View File

@ -25,6 +25,11 @@ namespace source
definition->body().accept(this);
}
void empty_visitor::visit(type_definition *definition)
{
definition->body().accept(this);
}
void empty_visitor::visit(call_statement *statement)
{
for (auto& argument : statement->arguments())
@ -91,14 +96,21 @@ namespace source
{
}
void empty_visitor::visit(array_type_expression *)
void empty_visitor::visit(array_type_expression *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(variable_expression *)
{
}
void empty_visitor::visit(array_access_expression *expression)
{
expression->base().accept(this);
expression->index().accept(this);
}
void empty_visitor::visit(number_literal<std::int32_t> *)
{
}
@ -332,6 +344,27 @@ namespace source
}
}
type_definition::type_definition(const struct position position, const std::string& identifier,
type_expression *body)
: definition(position, identifier), m_body(body)
{
}
void type_definition::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
type_expression& type_definition::body()
{
return *m_body;
}
type_definition::~type_definition()
{
delete m_body;
}
block::block(const struct position position, std::vector<definition *>&& definitions,
std::vector<declaration *>&& declarations,
statement *body)
@ -415,8 +448,13 @@ namespace source
return m_string;
}
designator_expression::designator_expression(const struct position position)
: expression(position)
{
}
variable_expression::variable_expression(const struct position position, const std::string& name)
: expression(position), m_name(name)
: designator_expression(position), m_name(name)
{
}
@ -430,6 +468,42 @@ namespace source
return m_name;
}
variable_expression *variable_expression::is_variable()
{
return this;
}
array_access_expression::array_access_expression(const struct position position,
designator_expression *base, expression *index)
: designator_expression(position), m_base(base), m_index(index)
{
}
void array_access_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression& array_access_expression::index()
{
return *m_index;
}
designator_expression& array_access_expression::base()
{
return *m_base;
}
array_access_expression *array_access_expression::is_array_access()
{
return this;
}
array_access_expression::~array_access_expression()
{
delete m_base;
}
binary_expression::binary_expression(const struct position position, expression *lhs,
expression *rhs, const unsigned char operation)
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
@ -590,15 +664,25 @@ namespace source
visitor->visit(this);
}
assign_statement::assign_statement(const struct position position, const std::string& lvalue,
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
expression *rvalue)
: statement(position), m_lvalue(lvalue), m_rvalue(rvalue)
{
}
std::string& assign_statement::lvalue()
variable_expression *designator_expression::is_variable()
{
return m_lvalue;
return nullptr;
}
array_access_expression *designator_expression::is_array_access()
{
return nullptr;
}
designator_expression& assign_statement::lvalue()
{
return *m_lvalue;
}
expression& assign_statement::rvalue()

View File

@ -67,6 +67,10 @@ array {
of {
return yy::parser::make_OF(this->location);
}
type {
return yy::parser::make_TYPE(this->location);
}
true {
return yy::parser::make_BOOLEAN(true, this->location);
}

View File

@ -63,7 +63,7 @@
%token <std::string> STRING "string"
%token <bool> BOOLEAN
%token IF WHILE DO
%token CONST VAR PROCEDURE ARRAY OF
%token CONST VAR PROCEDURE ARRAY OF TYPE
%token BEGIN_BLOCK END_BLOCK
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
@ -87,6 +87,7 @@
%type <elna::source::expression *> expression pointer summand factor address comparand;
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
%type <elna::source::variable_expression *> variable_expression;
%type <elna::source::designator_expression *> designator_expression;
%type <elna::source::compound_statement *> compound_statement;
%type <elna::source::assign_statement *> assign_statement;
%type <elna::source::call_statement *> call_statement;
@ -95,26 +96,31 @@
%type <elna::source::statement *> statement;
%type <std::vector<elna::source::statement *>> statements optional_statements;
%type <elna::source::procedure_definition *> procedure_definition;
%type <std::vector<elna::source::procedure_definition *>> procedure_definitions
procedure_definition_part;
%type <std::vector<elna::source::procedure_definition *>> procedure_definitions procedure_definition_part;
%type <elna::source::type_definition *> type_definition;
%type <std::vector<elna::source::type_definition *>> type_definitions type_definition_part;
%type <elna::source::block *> block;
%%
program: constant_definition_part procedure_definition_part variable_declaration_part statement DOT
program:
type_definition_part constant_definition_part procedure_definition_part variable_declaration_part statement DOT
{
std::vector<elna::source::definition *> definitions($1.size() + $2.size());
std::vector<elna::source::definition *> definitions($1.size() + $2.size() + $3.size());
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
for (auto& constant : $1)
for (auto& type : $1)
{
*definition++ = type;
}
for (auto& constant : $2)
{
*definition++ = constant;
}
for (auto& procedure : $2)
for (auto& procedure : $3)
{
*definition++ = procedure;
}
driver.tree = std::make_unique<elna::source::program>(elna::source::position{},
std::move(definitions), std::move($3),
std::move($4));
std::move(definitions), std::move($4), std::move($5));
}
block: constant_definition_part variable_declaration_part statement
{
@ -170,7 +176,7 @@ compound_statement: BEGIN_BLOCK optional_statements END_BLOCK
$$ = new elna::source::compound_statement(elna::source::make_position(@1));
std::swap($$->statements(), $2);
}
assign_statement: IDENTIFIER ASSIGNMENT expression
assign_statement: designator_expression ASSIGNMENT expression
{
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
}
@ -201,7 +207,7 @@ pointer:
| boolean_literal { $$ = $1; }
| character_literal { $$ = $1; }
| string_literal { $$ = $1; }
| variable_expression { $$ = $1; }
| designator_expression { $$ = $1; }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
summand:
factor { $$ = std::move($1); }
@ -280,8 +286,14 @@ expressions:
$$.emplace($$.cbegin(), $1);
}
| expression { $$.emplace_back(std::move($1)); }
variable_expression: IDENTIFIER
{ $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); }
variable_expression:
IDENTIFIER { $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); }
designator_expression:
variable_expression LEFT_SQUARE expression RIGHT_SQUARE
{
$$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3);
}
| variable_expression { $$ = $1; }
statement:
compound_statement { $$ = $1; }
| assign_statement { $$ = $1; }
@ -324,9 +336,8 @@ variable_declaration_part:
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
constant_definition: IDENTIFIER EQUALS integer_literal
{
$$ = new elna::source::constant_definition(elna::source::make_position(@1),
$1, $3);
};
$$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3);
}
constant_definitions:
constant_definition COMMA constant_definitions
{
@ -336,7 +347,21 @@ constant_definitions:
| constant_definition { $$.emplace_back(std::move($1)); }
constant_definition_part:
/* no constant definitions */ {}
| CONST constant_definitions SEMICOLON { std::swap($$, $2); };
| CONST constant_definitions SEMICOLON { std::swap($$, $2); }
type_definition: IDENTIFIER EQUALS type_expression
{
$$ = new elna::source::type_definition(elna::source::make_position(@1), $1, $3);
}
type_definitions:
type_definition COMMA type_definitions
{
std::swap($$, $3);
$$.emplace($$.cbegin(), std::move($1));
}
| type_definition { $$.emplace_back(std::move($1)); }
type_definition_part:
/* no type definitions */ {}
| TYPE type_definitions SEMICOLON { std::swap($$, $2); }
formal_parameter_list:
LEFT_PAREN RIGHT_PAREN {}
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }

View File

@ -24,7 +24,7 @@ namespace source
name_collision::name_collision(const std::string& name, const char *path,
const struct position current, const struct position previous)
: error(path, current), name(name), previous(previous)
: error(path, current), previous(previous), name(name)
{
}
@ -32,16 +32,5 @@ namespace source
{
return "Name '" + name + "' was already defined";
}
type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind,
const char *path, const struct position position)
: error(path, position), kind(kind), got(got)
{
}
std::string type_mismatch::what() const
{
return "Type cannot be used here.";
}
}
}

View File

@ -48,7 +48,7 @@ namespace source
}
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
: arguments(std::move(arguments)), type(byte_size)
:type(byte_size), arguments(std::move(arguments))
{
}