From e8747a803fc63971d31edd1764f9d583b73160ce Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 5 Jan 2025 15:21:25 +0100 Subject: [PATCH] Construct the parse tree with raw pointers --- include/elna/source/ast.h | 104 ++++++++++++--------- source/ast.cc | 145 ++++++++++++++++++++++------- source/parser.yy | 186 +++++++++++++++++++------------------- 3 files changed, 269 insertions(+), 166 deletions(-) diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index e9afadb..4331ea6 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -262,7 +262,7 @@ namespace source */ class declaration : public definition { - std::unique_ptr m_type; + type_expression *m_type; public: /** @@ -273,10 +273,12 @@ namespace source * \param type Declared type. */ declaration(const struct position position, const std::string& identifier, - std::unique_ptr&& type); + type_expression *type); virtual void accept(parser_visitor *visitor) override; type_expression& type() noexcept; + + virtual ~declaration() override; }; /** @@ -284,7 +286,7 @@ namespace source */ class constant_definition : public definition { - std::unique_ptr> m_body; + number_literal *m_body; public: /** @@ -293,10 +295,12 @@ namespace source * \param body Constant value. */ constant_definition(const struct position position, const std::string& identifier, - std::unique_ptr>&& body); + number_literal *body); virtual void accept(parser_visitor *visitor) override; number_literal& body(); + + virtual ~constant_definition() override; }; /** @@ -304,8 +308,8 @@ namespace source */ class procedure_definition : public definition { - std::unique_ptr m_body; - std::vector> m_parameters; + block *m_body; + std::vector m_parameters; public: /** @@ -314,11 +318,13 @@ namespace source * \param body Procedure body. */ procedure_definition(const struct position position, const std::string& identifier, - std::unique_ptr&& body); + block *body); virtual void accept(parser_visitor *visitor) override; block& body(); - std::vector>& parameters() noexcept; + std::vector& parameters() noexcept; + + virtual ~procedure_definition() override; }; /** @@ -327,7 +333,7 @@ namespace source class call_statement : public statement { std::string m_name; - std::vector> m_arguments; + std::vector m_arguments; public: /** @@ -338,24 +344,28 @@ namespace source virtual void accept(parser_visitor *visitor) override; std::string& name() noexcept; - std::vector>& arguments() noexcept; + std::vector& arguments() noexcept; + + virtual ~call_statement() override; }; class compound_statement : public statement { - std::vector> m_statements; + std::vector m_statements; public: explicit compound_statement(const struct position position); virtual void accept(parser_visitor *visitor) override; - std::vector>& statements(); + std::vector& statements(); + + virtual ~compound_statement() override; }; class assign_statement : public statement { std::string m_lvalue; - std::unique_ptr m_rvalue; + expression *m_rvalue; public: /** @@ -364,11 +374,13 @@ namespace source * \param rvalue Assigned expression. */ assign_statement(const struct position position, const std::string& lvalue, - std::unique_ptr&& rvalue); + expression *rvalue); virtual void accept(parser_visitor *visitor) override; std::string& lvalue() noexcept; expression& rvalue(); + + virtual ~assign_statement() override; }; /** @@ -376,9 +388,9 @@ namespace source */ class if_statement : public statement { - std::unique_ptr m_prerequisite; - std::unique_ptr m_body; - std::unique_ptr m_alternative; + expression *m_prerequisite; + statement *m_body; + statement *m_alternative; public: /** @@ -387,13 +399,15 @@ namespace source * \param body Statement executed if the condition is met. * \param alternative Statement executed if the condition is not met. */ - if_statement(const struct position position, std::unique_ptr&& prerequisite, - std::unique_ptr&& body, std::unique_ptr&& alternative = nullptr); + if_statement(const struct position position, expression *prerequisite, + statement *body, statement *alternative = nullptr); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); statement& body(); - std::unique_ptr& alternative(); + statement *alternative(); + + virtual ~if_statement() override; }; /** @@ -401,8 +415,8 @@ namespace source */ class while_statement : public statement { - std::unique_ptr m_prerequisite; - std::unique_ptr m_body; + expression *m_prerequisite; + statement *m_body; public: /** @@ -410,37 +424,41 @@ namespace source * \param prerequisite Condition. * \param body Statement executed while the condition is met. */ - while_statement(const struct position position, std::unique_ptr&& prerequisite, - std::unique_ptr&& body); + while_statement(const struct position position, expression *prerequisite, + statement *body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); statement& body(); + + virtual ~while_statement() override; }; class block : public node { - std::vector> m_definitions; - std::vector> m_declarations; - std::unique_ptr m_body; + std::vector m_definitions; + std::vector m_declarations; + statement *m_body; public: - block(const struct position position, std::vector>&& definitions, - std::vector>&& declarations, - std::unique_ptr&& body); + block(const struct position position, std::vector&& definitions, + std::vector&& declarations, + statement *body); virtual void accept(parser_visitor *visitor) override; statement& body(); - std::vector>& definitions() noexcept; - std::vector>& declarations() noexcept; + std::vector& definitions() noexcept; + std::vector& declarations() noexcept; + + virtual ~block() override; }; class program : public block { public: - program(const struct position position, std::vector>&& definitions, - std::vector>&& declarations, - std::unique_ptr&& body); + program(const struct position position, std::vector&& definitions, + std::vector&& declarations, + statement *body); virtual void accept(parser_visitor *visitor) override; }; @@ -501,32 +519,36 @@ namespace source class binary_expression : public expression { - std::unique_ptr m_lhs; - std::unique_ptr m_rhs; + expression *m_lhs; + expression *m_rhs; binary_operator m_operator; public: - binary_expression(const struct position position, std::unique_ptr&& lhs, - std::unique_ptr&& rhs, const unsigned char operation); + binary_expression(const struct position position, expression *lhs, + expression *rhs, const unsigned char operation); virtual void accept(parser_visitor *visitor) override; expression& lhs(); expression& rhs(); binary_operator operation() const noexcept; + + virtual ~binary_expression() override; }; class unary_expression : public expression { - std::unique_ptr m_operand; + expression *m_operand; unary_operator m_operator; public: - unary_expression(const struct position position, std::unique_ptr&& operand, + unary_expression(const struct position position, expression *operand, const unsigned char operation); virtual void accept(parser_visitor *visitor) override; expression& operand(); unary_operator operation() const noexcept; + + virtual ~unary_expression() override; }; const char *print_binary_operator(const binary_operator operation); diff --git a/source/ast.cc b/source/ast.cc index e8d7eee..0021ea7 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -18,7 +18,7 @@ namespace source void empty_visitor::visit(procedure_definition *definition) { - for (auto& parameter : definition->parameters()) + for (auto parameter : definition->parameters()) { parameter->accept(this); } @@ -211,11 +211,16 @@ namespace source } declaration::declaration(const struct position position, const std::string& identifier, - std::unique_ptr&& type) - : definition(position, identifier), m_type(std::move(type)) + type_expression *type) + : definition(position, identifier), m_type(type) { } + declaration::~declaration() + { + delete m_type; + } + void declaration::accept(parser_visitor *visitor) { visitor->visit(this); @@ -237,8 +242,8 @@ namespace source } constant_definition::constant_definition(const struct position position, const std::string& identifier, - std::unique_ptr>&& body) - : definition(position, identifier), m_body(std::move(body)) + number_literal *body) + : definition(position, identifier), m_body(body) { } @@ -252,9 +257,14 @@ namespace source return *m_body; } + constant_definition::~constant_definition() + { + delete m_body; + } + procedure_definition::procedure_definition(const struct position position, const std::string& identifier, - std::unique_ptr&& body) - : definition(position, identifier), m_body(std::move(body)) + block *body) + : definition(position, identifier), m_body(body) { } @@ -268,14 +278,23 @@ namespace source return *m_body; } - std::vector>& procedure_definition::parameters() noexcept + std::vector& procedure_definition::parameters() noexcept { return m_parameters; } - block::block(const struct position position, std::vector>&& definitions, - std::vector>&& declarations, - std::unique_ptr&& body) + procedure_definition::~procedure_definition() + { + delete m_body; + for (auto parameter : m_parameters) + { + delete parameter; + } + } + + block::block(const struct position position, std::vector&& definitions, + std::vector&& declarations, + statement *body) : node(position), m_definitions(std::move(definitions)), m_declarations(std::move(declarations)), m_body(std::move(body)) { @@ -291,20 +310,33 @@ namespace source return *m_body; } - std::vector>& block::definitions() noexcept + std::vector& block::definitions() noexcept { return m_definitions; } - std::vector>& block::declarations() noexcept + std::vector& block::declarations() noexcept { return m_declarations; } - program::program(const struct position position, std::vector>&& definitions, - std::vector>&& declarations, - std::unique_ptr&& body) - : block(position, std::move(definitions), std::move(declarations), std::move(body)) + block::~block() + { + for (auto definition : m_definitions) + { + delete definition; + } + for (auto declaration : m_declarations) + { + delete declaration; + } + delete m_body; + } + + program::program(const struct position position, std::vector&& definitions, + std::vector&& declarations, + statement *body) + : block(position, std::move(definitions), std::move(declarations), body) { } @@ -358,8 +390,8 @@ namespace source return m_name; } - binary_expression::binary_expression(const struct position position, std::unique_ptr&& lhs, - std::unique_ptr&& rhs, const unsigned char operation) + 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)) { switch (operation) @@ -419,7 +451,13 @@ namespace source return m_operator; } - unary_expression::unary_expression(const struct position position, std::unique_ptr&& operand, + binary_expression::~binary_expression() + { + delete m_lhs; + delete m_rhs; + } + + unary_expression::unary_expression(const struct position position, expression *operand, const unsigned char operation) : expression(position), m_operand(std::move(operand)) { @@ -451,6 +489,11 @@ namespace source return this->m_operator; } + unary_expression::~unary_expression() + { + delete m_operand; + } + call_statement::call_statement(const struct position position, const std::string& name) : statement(position), m_name(name) { @@ -466,11 +509,19 @@ namespace source return m_name; } - std::vector>& call_statement::arguments() noexcept + std::vector& call_statement::arguments() noexcept { return m_arguments; } + call_statement::~call_statement() + { + for (auto argument : m_arguments) + { + delete argument; + } + } + compound_statement::compound_statement(const struct position position) : statement(position) { @@ -481,19 +532,27 @@ namespace source visitor->visit(this); } - std::vector>& compound_statement::statements() + std::vector& compound_statement::statements() { return m_statements; } + compound_statement::~compound_statement() + { + for (auto statement : m_statements) + { + delete statement; + } + } + void assign_statement::accept(parser_visitor *visitor) { visitor->visit(this); } assign_statement::assign_statement(const struct position position, const std::string& lvalue, - std::unique_ptr&& rvalue) - : statement(position), m_lvalue(lvalue), m_rvalue(std::move(rvalue)) + expression *rvalue) + : statement(position), m_lvalue(lvalue), m_rvalue(rvalue) { } @@ -507,10 +566,15 @@ namespace source return *m_rvalue; } - if_statement::if_statement(const struct position position, std::unique_ptr&& prerequisite, - std::unique_ptr&& body, std::unique_ptr&& alternative) - : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body)), - m_alternative(std::move(alternative)) + assign_statement::~assign_statement() + { + delete m_rvalue; + } + + if_statement::if_statement(const struct position position, expression *prerequisite, + statement *body, statement *alternative) + : statement(position), m_prerequisite(prerequisite), m_body(body), + m_alternative(alternative) { } @@ -529,14 +593,25 @@ namespace source return *m_body; } - std::unique_ptr& if_statement::alternative() + statement *if_statement::alternative() { return m_alternative; } - while_statement::while_statement(const struct position position, std::unique_ptr&& prerequisite, - std::unique_ptr&& body) - : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) + if_statement::~if_statement() + { + delete m_prerequisite; + delete m_body; + + if (m_alternative != nullptr) + { + delete m_alternative; + } + } + + while_statement::while_statement(const struct position position, expression *prerequisite, + statement *body) + : statement(position), m_prerequisite(prerequisite), m_body(body) { } @@ -555,6 +630,12 @@ namespace source return *m_body; } + while_statement::~while_statement() + { + delete m_prerequisite; + delete m_body; + } + const char *print_binary_operator(const binary_operator operation) { switch (operation) diff --git a/source/parser.yy b/source/parser.yy index 0761ef1..7e6180e 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -73,44 +73,44 @@ %precedence THEN %precedence ELSE -%type >> integer_literal; -%type >> float_literal; -%type >> boolean_literal; -%type > character_literal; -%type > string_literal; -%type > constant_definition; -%type >> constant_definition_part constant_definitions; -%type > variable_declaration; -%type >> variable_declarations variable_declaration_part +%type *> integer_literal; +%type *> float_literal; +%type *> boolean_literal; +%type character_literal; +%type string_literal; +%type constant_definition; +%type > constant_definition_part constant_definitions; +%type variable_declaration; +%type > variable_declarations variable_declaration_part formal_parameter_list; -%type > type_expression; -%type > expression pointer summand factor address comparand; -%type >> expressions actual_parameter_list; -%type > variable_expression; -%type > compound_statement; -%type > assign_statement; -%type > call_statement; -%type > while_statement; -%type > if_statement; -%type > statement; -%type >> statements optional_statements; -%type > procedure_definition; -%type >> procedure_definitions +%type type_expression; +%type expression pointer summand factor address comparand; +%type > expressions actual_parameter_list; +%type variable_expression; +%type compound_statement; +%type assign_statement; +%type call_statement; +%type while_statement; +%type if_statement; +%type statement; +%type > statements optional_statements; +%type procedure_definition; +%type > procedure_definitions procedure_definition_part; -%type > block; +%type block; %% program: constant_definition_part procedure_definition_part variable_declaration_part statement DOT { - std::vector> definitions($1.size() + $2.size()); - std::vector>::iterator definition = definitions.begin(); + std::vector definitions($1.size() + $2.size()); + std::vector::iterator definition = definitions.begin(); for (auto& constant : $1) { - *definition++ = std::move(constant); + *definition++ = constant; } for (auto& procedure : $2) { - *definition++ = std::move(procedure); + *definition++ = procedure; } driver.tree = std::make_unique(elna::source::position{}, std::move(definitions), std::move($3), @@ -118,21 +118,21 @@ program: constant_definition_part procedure_definition_part variable_declaration } block: constant_definition_part variable_declaration_part statement { - std::vector> definitions($1.size()); - std::vector>::iterator definition = definitions.begin(); + std::vector definitions($1.size()); + std::vector::iterator definition = definitions.begin(); for (auto& constant : $1) { - *definition++ = std::move(constant); + *definition++ = constant; } - $$ = std::make_unique(elna::source::position{}, + $$ = new elna::source::block(elna::source::position{}, std::move(definitions), std::move($2), std::move($3)); }; procedure_definition: PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON { - $$ = std::make_unique(elna::source::position{}, - std::move($2), std::move($5)); + $$ = new elna::source::procedure_definition(elna::source::position{}, + std::move($2), $5); std::swap($$->parameters(), $3); }; procedure_definitions: @@ -147,172 +147,172 @@ procedure_definition_part: | procedure_definitions { std::swap($$, $1); } integer_literal: INTEGER { - $$ = std::make_unique>(elna::source::make_position(@1), $1); + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); }; float_literal: FLOAT { - $$ = std::make_unique>(elna::source::make_position(@1), $1); + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); }; character_literal: CHARACTER { - $$ = std::make_unique(elna::source::make_position(@1), $1.at(0)); + $$ = new elna::source::char_literal(elna::source::make_position(@1), $1.at(0)); }; string_literal: STRING { - $$ = std::make_unique(elna::source::make_position(@1), $1); + $$ = new elna::source::string_literal(elna::source::make_position(@1), $1); }; boolean_literal: BOOLEAN { - $$ = std::make_unique>(elna::source::make_position(@1), $1); + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); }; compound_statement: BEGIN_BLOCK optional_statements END_BLOCK { - $$ = std::make_unique(elna::source::make_position(@1)); + $$ = new elna::source::compound_statement(elna::source::make_position(@1)); std::swap($$->statements(), $2); } assign_statement: IDENTIFIER ASSIGNMENT expression { - $$ = std::make_unique(elna::source::make_position(@1), $1, std::move($3)); + $$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3); } call_statement: IDENTIFIER actual_parameter_list { - $$ = std::make_unique(elna::source::make_position(@1), $1); + $$ = new elna::source::call_statement(elna::source::make_position(@1), $1); std::swap($$->arguments(), $2); } while_statement: WHILE expression DO statement { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($2), std::move($4)); + $$ = new elna::source::while_statement(elna::source::make_position(@1), + $2, $4); } if_statement: IF expression THEN statement { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($2), std::move($4)); + $$ = new elna::source::if_statement(elna::source::make_position(@1), + $2, $4); } | IF expression THEN statement ELSE statement { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($2), std::move($4), std::move($6)); + $$ = new elna::source::if_statement(elna::source::make_position(@1), + $2, $4, $6); } pointer: - integer_literal { $$ = std::move($1); } - | float_literal { $$ = std::move($1); } - | boolean_literal { $$ = std::move($1); } - | character_literal { $$ = std::move($1); } - | string_literal { $$ = std::move($1); } - | variable_expression { $$ = std::move($1); } + integer_literal { $$ = $1; } + | float_literal { $$ = $1; } + | boolean_literal { $$ = $1; } + | character_literal { $$ = $1; } + | string_literal { $$ = $1; } + | variable_expression { $$ = $1; } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } summand: factor { $$ = std::move($1); } | factor MULTIPLICATION factor { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '*'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '*'); } | factor DIVISION factor { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '/'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '/'); } address: pointer HAT { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), '^'); + $$ = new elna::source::unary_expression(elna::source::make_position(@1), + $1, '^'); } - | pointer { $$ = std::move($1); } + | pointer { $$ = $1; } factor: AT address { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($2), '@'); + $$ = new elna::source::unary_expression(elna::source::make_position(@1), + $2, '@'); } - | address { $$ = std::move($1); } + | address { $$ = $1; } comparand: summand PLUS summand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '+'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '+'); } | summand MINUS summand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '-'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '-'); } | summand { $$ = std::move($1); } expression: comparand EQUALS comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '='); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '='); } | comparand NOT_EQUAL comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), 'n'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, 'n'); } | comparand LESS_THAN comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '<'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '<'); } | comparand GREATER_THAN comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '>'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '>'); } | comparand LESS_EQUAL comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '<'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '<'); } | comparand GREATER_EQUAL comparand { - $$ = std::make_unique(elna::source::make_position(@1), - std::move($1), std::move($3), '>'); + $$ = new elna::source::binary_expression(elna::source::make_position(@1), + $1, $3, '>'); } | comparand { $$ = std::move($1); } expressions: expression COMMA expressions { std::swap($$, $3); - $$.emplace($$.cbegin(), std::move($1)); + $$.emplace($$.cbegin(), $1); } | expression { $$.emplace_back(std::move($1)); } variable_expression: IDENTIFIER - { $$ = std::make_unique(elna::source::make_position(@1), $1); } + { $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); } statement: - compound_statement { $$ = std::move($1); } - | assign_statement { $$ = std::move($1); } - | call_statement { $$ = std::move($1); } - | while_statement { $$ = std::move($1); } - | if_statement { $$ = std::move($1); } + compound_statement { $$ = $1; } + | assign_statement { $$ = $1; } + | call_statement { $$ = $1; } + | while_statement { $$ = $1; } + | if_statement { $$ = $1; } statements: statement SEMICOLON statements { std::swap($$, $3); $$.emplace($$.cbegin(), std::move($1)); } - | statement { $$.emplace_back(std::move($1)); } + | statement { $$.emplace_back($1); } optional_statements: statements { std::swap($$, $1); } | /* no statements */ {} type_expression: IDENTIFIER { - $$ = std::make_unique(elna::source::make_position(@1), $1); + $$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1); } variable_declaration: IDENTIFIER COLON type_expression { - $$ = std::make_unique(elna::source::make_position(@1), - $1, std::move($3)); + $$ = new elna::source::declaration(elna::source::make_position(@1), + $1, $3); }; variable_declarations: variable_declaration COMMA variable_declarations { std::swap($$, $3); - $$.emplace($$.cbegin(), std::move($1)); + $$.emplace($$.cbegin(), $1); } | variable_declaration { $$.emplace_back(std::move($1)); } variable_declaration_part: @@ -320,8 +320,8 @@ variable_declaration_part: | VAR variable_declarations SEMICOLON { std::swap($$, $2); } constant_definition: IDENTIFIER EQUALS integer_literal { - $$ = std::make_unique(elna::source::make_position(@1), - $1, std::move($3)); + $$ = new elna::source::constant_definition(elna::source::make_position(@1), + $1, $3); }; constant_definitions: constant_definition COMMA constant_definitions