Implement enumeration type
This commit is contained in:
67
boot/ast.cc
67
boot/ast.cc
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
|
Reference in New Issue
Block a user