Implement enumeration type

This commit is contained in:
2025-04-04 22:48:12 +02:00
parent 50970f3289
commit 18c4e79012
14 changed files with 612 additions and 416 deletions

View File

@ -103,7 +103,7 @@ namespace elna::boot
{
}
primitive_type_expression *type_expression::is_primitive()
named_type_expression *type_expression::is_named()
{
return nullptr;
}
@ -133,17 +133,22 @@ namespace elna::boot
return nullptr;
}
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
enumeration_type_expression *type_expression::is_enumeration()
{
return nullptr;
}
named_type_expression::named_type_expression(const struct position position, const std::string& name)
: type_expression(position), name(name)
{
}
void primitive_type_expression::accept(parser_visitor *visitor)
void named_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
primitive_type_expression *primitive_type_expression::is_primitive()
named_type_expression *named_type_expression::is_named()
{
return this;
}
@ -312,6 +317,26 @@ namespace elna::boot
visitor->visit(this);
}
procedure_type_expression *procedure_type_expression::is_procedure()
{
return this;
}
enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members)
: type_expression(position), members(members)
{
}
void enumeration_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
enumeration_type_expression *enumeration_type_expression::is_enumeration()
{
return this;
}
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, procedure_type_expression *heading, block *body)
: definition(position, identifier, exported), m_heading(heading), body(body)
@ -323,11 +348,6 @@ namespace elna::boot
visitor->visit(this);
}
procedure_type_expression *procedure_type_expression::is_procedure()
{
return this;
}
procedure_type_expression& procedure_definition::heading()
{
return *m_heading;
@ -417,8 +437,8 @@ namespace elna::boot
return this;
}
defer_statement::defer_statement(const struct position position)
: node(position)
defer_statement::defer_statement(const struct position position, std::vector<statement *>&& statements)
: node(position), statements(std::move(statements))
{
}
@ -754,7 +774,7 @@ namespace elna::boot
}
return_statement::return_statement(const struct position position, expression *return_expression)
: node(position), m_return_expression(return_expression)
: node(position), return_expression(return_expression)
{
}
@ -768,14 +788,25 @@ namespace elna::boot
return this;
}
expression *return_statement::return_expression()
{
return m_return_expression;
}
return_statement::~return_statement()
{
delete m_return_expression;
delete this->return_expression;
}
case_statement::case_statement(const struct position position,
expression *condition, std::vector<switch_case>&& cases)
: node(position), m_condition(condition), cases(std::move(cases))
{
}
void case_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression& case_statement::condition()
{
return *m_condition;
}
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,

View File

@ -113,9 +113,12 @@ nil {
xor {
return yy::parser::make_XOR(this->location);
}
\| {
or {
return yy::parser::make_OR(this->location);
}
\| {
return yy::parser::make_PIPE(this->location);
}
\~ {
return yy::parser::make_NOT(this->location);
}
@ -128,6 +131,12 @@ cast {
defer {
return yy::parser::make_DEFER(this->location);
}
case {
return yy::parser::make_CASE(this->location);
}
of {
return yy::parser::make_OF(this->location);
}
[A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location);
}

View File

@ -111,31 +111,37 @@ along with GCC; see the file COPYING3. If not see
BEGIN_BLOCK "begin"
END_BLOCK "end"
DEFER "defer"
%token OR "|" AND "&" XOR "xor"
CASE "case"
OF "of"
PIPE "|"
%token OR "or" AND "&" XOR "xor"
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
PLUS "+" MINUS "-"
MULTIPLICATION "*" DIVISION "/" REMAINDER "%"
%left "|" "&" "xor"
%left "or" "&" "xor"
%left "=" "<>" "<" ">" "<=" ">="
%left "<<" ">>"
%left "+" "-"
%left "*" "/" "%"
%type <elna::boot::literal_expression *> literal;
%type <std::vector<elna::boot::literal_expression *>> case_labels;
%type <elna::boot::switch_case> switch_case;
%type <std::vector<elna::boot::switch_case>> switch_cases;
%type <elna::boot::constant_definition *> constant_definition;
%type <std::vector<elna::boot::constant_definition *>> constant_part constant_definitions;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration;
%type <elna::boot::type_expression *> type_expression;
%type <std::vector<elna::boot::type_expression *>> type_expressions;
%type <elna::boot::traits_expression *> traits_expression;
%type <elna::boot::expression *> expression operand qualident;
%type <elna::boot::expression *> expression operand simple_expression;
%type <elna::boot::field_access_expression *> qualident;
%type <elna::boot::unary_expression *> unary_expression;
%type <elna::boot::binary_expression *> binary_expression;
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
%type <elna::boot::designator_expression *> designator_expression;
%type <elna::boot::assign_statement *> assign_statement;
%type <elna::boot::procedure_call*> call_expression;
%type <elna::boot::while_statement *> while_statement;
%type <elna::boot::if_statement *> if_statement;
@ -154,9 +160,9 @@ along with GCC; see the file COPYING3. If not see
optional_fields required_fields formal_parameters;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
%type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
%type <std::vector<std::string>> identifiers;
%%
program:
constant_part type_part variable_part procedure_part "begin" statements "end" "."
@ -230,10 +236,6 @@ procedure_definitions:
procedure_part:
/* no procedure definitions */ {}
| procedure_definitions { std::swap($$, $1); }
assign_statement: designator_expression ":=" expression
{
$$ = new boot::assign_statement(boot::make_position(@1), $1, $3);
}
call_expression: designator_expression actual_parameter_list
{
$$ = new boot::procedure_call(boot::make_position(@1), $1);
@ -293,11 +295,6 @@ return_statement:
{
$$ = new boot::return_statement(boot::make_position(@1));
}
defer_statement: DEFER statements "end"
{
$$ = new boot::defer_statement(boot::make_position(@1));
std::swap($2, $$->statements);
}
literal:
INTEGER
{
@ -333,7 +330,7 @@ traits_expression:
$$ = new boot::traits_expression(boot::make_position(@1), $1);
std::swap($3, $$->parameters);
}
qualident:
simple_expression:
literal { $$ = $1; }
| designator_expression { $$ = $1; }
| traits_expression { $$ = $1; }
@ -342,7 +339,7 @@ qualident:
| "(" expression ")" { $$ = $2; }
operand:
unary_expression { $$ = $1; }
| qualident { $$ = $1; }
| simple_expression { $$ = $1; }
expression:
binary_expression { $$ = $1; }
| operand { $$ = $1; }
@ -396,7 +393,7 @@ binary_expression:
{
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::conjunction);
}
| expression "|" expression
| expression "or" expression
{
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::disjunction);
}
@ -441,15 +438,12 @@ type_expressions:
}
| type_expression { $$.push_back($1); }
designator_expression:
qualident "[" expression "]"
simple_expression "[" expression "]"
{
$$ = new boot::array_access_expression(boot::make_position(@2), $1, $3);
}
| qualident "." IDENTIFIER
{
$$ = new boot::field_access_expression(boot::make_position(@2), $1, $3);
}
| qualident "^"
| qualident { $$ = $1; }
| simple_expression "^"
{
$$ = new boot::dereference_expression(boot::make_position(@1), $1);
}
@ -457,13 +451,37 @@ designator_expression:
{
$$ = new boot::variable_expression(boot::make_position(@1), $1);
}
qualident: simple_expression "." IDENTIFIER
{
$$ = new boot::field_access_expression(boot::make_position(@2), $1, $3);
}
statement:
assign_statement { $$ = $1; }
designator_expression ":=" expression
{
$$ = new boot::assign_statement(boot::make_position(@1), $1, $3);
}
| while_statement { $$ = $1; }
| if_statement { $$ = $1; }
| return_statement { $$ = $1; }
| call_expression { $$ = $1; }
| defer_statement { $$ = $1; }
| DEFER statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
| CASE expression "of" switch_cases "end"
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4)); }
switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
switch_cases:
switch_case "|" switch_cases
{
std::swap($$, $3);
$$.emplace($$.cbegin(), $1);
}
| switch_case { $$.push_back($1); }
case_labels:
literal "," case_labels
{
std::swap($$, $3);
$$.emplace($$.cbegin(), $1);
}
| literal { $$.push_back($1); }
statements:
statement ";" statements
{
@ -507,10 +525,21 @@ type_expression:
std::swap(result->parameters, $3);
$$ = result;
}
| "(" identifiers ")"
{
$$ = new boot::enumeration_type_expression(boot::make_position(@1), std::move($2));
}
| IDENTIFIER
{
$$ = new boot::primitive_type_expression(boot::make_position(@1), $1);
$$ = new boot::named_type_expression(boot::make_position(@1), $1);
}
identifiers:
IDENTIFIER "," identifiers
{
std::swap($$, $3);
$$.emplace($$.cbegin(), std::move($1));
}
| IDENTIFIER { $$.emplace_back(std::move($1)); }
variable_declaration: identifier_definitions ":" type_expression
{
std::shared_ptr<boot::type_expression> shared_type{ $3 };
@ -561,16 +590,14 @@ type_definitions:
type_part:
/* no type definitions */ {}
| "type" type_definitions { std::swap($$, $2); }
formal_parameter: IDENTIFIER ":" type_expression
{
$$ = std::make_pair($1, $3);
}
formal_parameter:
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
formal_parameters:
/* no formal parameters */ {}
| formal_parameter "," formal_parameters
{
std::swap($$, $3);
$$.emplace($$.cbegin(), $1);
$$.emplace($$.cbegin(), std::move($1));
}
| formal_parameter { $$.emplace_back(std::move($1)); }
actual_parameter_list:

View File

@ -114,7 +114,7 @@ namespace elna::boot
unresolved_declaration->reference = this->current_type;
}
void declaration_visitor::visit(primitive_type_expression *type_expression)
void declaration_visitor::visit(named_type_expression *type_expression)
{
auto unresolved_alias = this->unresolved.find(type_expression->name);
@ -177,13 +177,23 @@ namespace elna::boot
this->current_type = type(result_type);
}
void declaration_visitor::visit(enumeration_type_expression *type_expression)
{
std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members);
this->current_type = type(result_type);
}
void declaration_visitor::visit(variable_declaration *declaration)
{
declaration->variable_type().accept(this);
}
void declaration_visitor::visit(constant_definition *)
void declaration_visitor::visit(constant_definition *definition)
{
definition->body().accept(this);
this->symbols->enter(definition->identifier, std::make_shared<constant_info>(this->current_literal));
}
void declaration_visitor::visit(procedure_definition *definition)
@ -249,9 +259,9 @@ namespace elna::boot
void declaration_visitor::visit(return_statement *statement)
{
if (statement->return_expression() != nullptr)
if (statement->return_expression != nullptr)
{
statement->return_expression()->accept(this);
statement->return_expression->accept(this);
}
}
@ -263,6 +273,22 @@ namespace elna::boot
}
}
void declaration_visitor::visit(case_statement *statement)
{
statement->condition().accept(this);
for (const switch_case& case_block : statement->cases)
{
for (literal_expression *const case_label : case_block.labels)
{
case_label->accept(this);
}
for (struct statement *const statement : case_block.statements)
{
statement->accept(this);
}
}
}
void declaration_visitor::visit(procedure_call *call)
{
call->callable().accept(this);
@ -333,31 +359,38 @@ namespace elna::boot
expression->base().accept(this);
}
void declaration_visitor::visit(literal<std::int32_t> *)
void declaration_visitor::visit(literal<std::int32_t> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<std::uint32_t> *)
void declaration_visitor::visit(literal<std::uint32_t> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<double> *)
void declaration_visitor::visit(literal<double> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<bool> *)
void declaration_visitor::visit(literal<bool> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<unsigned char> *)
void declaration_visitor::visit(literal<unsigned char> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<std::nullptr_t> *)
void declaration_visitor::visit(literal<std::nullptr_t> *literal)
{
this->current_literal = literal->value;
}
void declaration_visitor::visit(literal<std::string> *)
void declaration_visitor::visit(literal<std::string> *literal)
{
this->current_literal = literal->value;
}
}

View File

@ -58,6 +58,11 @@ namespace elna::boot
{
}
type::type(std::shared_ptr<enumeration_type> enumeration)
: tag(type_tag::enumeration), enumeration(enumeration)
{
}
void type::copy(const type& other)
{
switch (other.tag)
@ -85,6 +90,9 @@ namespace elna::boot
case type_tag::procedure:
new (&procedure) std::shared_ptr<procedure_type>(other.procedure);
break;
case type_tag::enumeration:
new (&enumeration) std::shared_ptr<enumeration_type>(other.enumeration);
break;
}
}
@ -121,6 +129,9 @@ namespace elna::boot
case type_tag::procedure:
new (&procedure) std::shared_ptr<procedure_type>(std::move(other.procedure));
break;
case type_tag::enumeration:
new (&enumeration) std::shared_ptr<enumeration_type>(std::move(other.enumeration));
break;
}
}
@ -178,6 +189,9 @@ namespace elna::boot
case type_tag::procedure:
this->procedure.~shared_ptr<procedure_type>();
break;
case type_tag::enumeration:
this->enumeration.~shared_ptr<enumeration_type>();
break;
}
}
@ -223,6 +237,12 @@ namespace elna::boot
return tag == type_tag::procedure ? this->procedure : nullptr;
}
template<>
std::shared_ptr<enumeration_type> type::get<enumeration_type>() const
{
return tag == type_tag::enumeration ? this->enumeration : nullptr;
}
bool type::empty() const
{
return tag == type_tag::empty;
@ -253,6 +273,11 @@ namespace elna::boot
{
}
enumeration_type::enumeration_type(const std::vector<std::string>& members)
: members(members)
{
}
info::~info()
{
}
@ -287,6 +312,11 @@ namespace elna::boot
return std::static_pointer_cast<procedure_info>(shared_from_this());
}
constant_info::constant_info(const variant& symbol)
: symbol(symbol)
{
}
std::shared_ptr<symbol_table> builtin_symbol_table()
{
auto result = std::make_shared<symbol_table>();