From cf4b6b7ccc306c3217c06827fc8669b2fe195ce3 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 8 Jan 2025 23:23:27 +0100 Subject: [PATCH] Add pointer and field access nodes --- include/elna/source/ast.h | 93 ++++++++++++++++++--- include/elna/source/result.h | 18 ----- source/ast.cc | 151 +++++++++++++++++++++++++++++++++++ source/lexer.ll | 4 +- source/parser.yy | 9 ++- source/result.cc | 11 --- 6 files changed, 242 insertions(+), 44 deletions(-) diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index efd573b..8ecc548 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -49,8 +49,12 @@ namespace source class unary_expression; class basic_type_expression; class array_type_expression; + class pointer_type_expression; + class record_type_expression; class variable_expression; class array_access_expression; + class field_access_expression; + class dereference_expression; template class number_literal; class char_literal; @@ -76,8 +80,12 @@ namespace source virtual void visit(unary_expression *) = 0; virtual void visit(basic_type_expression *) = 0; virtual void visit(array_type_expression *) = 0; + virtual void visit(pointer_type_expression *) = 0; + virtual void visit(record_type_expression *) = 0; virtual void visit(variable_expression *) = 0; virtual void visit(array_access_expression *) = 0; + virtual void visit(field_access_expression *is_field_access) = 0; + virtual void visit(dereference_expression *is_dereference) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; @@ -105,8 +113,12 @@ namespace source virtual void visit(unary_expression *expression) override; virtual void visit(basic_type_expression *) override; virtual void visit(array_type_expression *expression) override; + virtual void visit(pointer_type_expression *) override; + virtual void visit(record_type_expression *expression) override; virtual void visit(variable_expression *) override; virtual void visit(array_access_expression *expression) override; + virtual void visit(field_access_expression *is_field_access) override; + virtual void visit(dereference_expression *is_dereference) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; @@ -240,6 +252,8 @@ namespace source virtual const std::string& base_name() = 0; virtual basic_type_expression *is_basic(); virtual array_type_expression *is_array(); + virtual pointer_type_expression *is_pointer(); + virtual record_type_expression *is_record(); protected: type_expression(const struct position position); @@ -270,22 +284,11 @@ namespace source type_expression *m_base; public: - /** - * Array size. - */ const std::uint32_t size; - /** - * \param position Source code position. - * \param name Array base type. - * \param name Array size. - */ array_type_expression(const struct position position, type_expression *base, const std::uint32_t size); virtual void accept(parser_visitor *visitor) override; - /** - * \return Array base type. - */ type_expression& base(); const std::string& base_name() override; @@ -294,6 +297,39 @@ namespace source virtual ~array_type_expression() override; }; + class pointer_type_expression : public type_expression + { + type_expression *m_base; + + public: + pointer_type_expression(const struct position position, type_expression *base); + virtual void accept(parser_visitor *visitor) override; + + type_expression& base(); + const std::string& base_name() override; + + pointer_type_expression *is_pointer() override; + + virtual ~pointer_type_expression() override; + }; + + class record_type_expression : public type_expression + { + public: + using field_t = std::pair; + using fields_t = std::vector; + + record_type_expression(const struct position position, fields_t&& fields); + virtual void accept(parser_visitor *visitor) override; + + fields_t& fields(); + + record_type_expression *is_record() override; + + private: + fields_t m_fields; + }; + /** * Variable declaration. */ @@ -418,6 +454,8 @@ namespace source public: virtual variable_expression *is_variable(); virtual array_access_expression *is_array_access(); + virtual field_access_expression *is_field_access(); + virtual dereference_expression *is_dereference(); protected: designator_expression(const struct position position); @@ -453,6 +491,39 @@ namespace source ~array_access_expression() override; }; + class field_access_expression : public designator_expression + { + designator_expression *m_base; + std::string m_field; + + public: + field_access_expression(const struct position position, designator_expression *base, + const std::string& field); + virtual void accept(parser_visitor *visitor) override; + + designator_expression& base(); + std::string& field(); + + field_access_expression *is_field_access() override; + + ~field_access_expression() override; + }; + + class dereference_expression : public designator_expression + { + designator_expression *m_base; + + public: + dereference_expression(const struct position position, designator_expression *base); + virtual void accept(parser_visitor *visitor) override; + + designator_expression& base(); + + dereference_expression *is_dereference() override; + + ~dereference_expression() override; + }; + class assign_statement : public statement { designator_expression *m_lvalue; diff --git a/include/elna/source/result.h b/include/elna/source/result.h index 77eafe4..ed49fb1 100644 --- a/include/elna/source/result.h +++ b/include/elna/source/result.h @@ -51,23 +51,5 @@ namespace source /// Error column in the source text. std::size_t column() const noexcept; }; - - class name_collision final : public error - { - const struct position previous; - std::string name; - - public: - /** - * \param name Symbol name. - * \param path Source file name. - * \param current Current symbol position. - * \param previous Position of the previously defined symbol. - */ - name_collision(const std::string& name, const char *path, - const struct position current, const struct position previous); - - std::string what() const override; - }; } } diff --git a/source/ast.cc b/source/ast.cc index 32cec0b..e323fc6 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -101,6 +101,19 @@ namespace source expression->base().accept(this); } + void empty_visitor::visit(pointer_type_expression *expression) + { + expression->base().accept(this); + } + + void empty_visitor::visit(record_type_expression *expression) + { + for (auto& field : expression->fields()) + { + field.second->accept(this); + } + } + void empty_visitor::visit(variable_expression *) { } @@ -111,6 +124,16 @@ namespace source expression->index().accept(this); } + void empty_visitor::visit(field_access_expression *expression) + { + expression->base().accept(this); + } + + void empty_visitor::visit(dereference_expression *expression) + { + expression->base().accept(this); + } + void empty_visitor::visit(number_literal *) { } @@ -210,6 +233,16 @@ namespace source return nullptr; } + record_type_expression *type_expression::is_record() + { + return nullptr; + } + + pointer_type_expression *type_expression::is_pointer() + { + return nullptr; + } + basic_type_expression::basic_type_expression( const struct position position, const std::string& name) : type_expression(position), m_name(name) @@ -262,6 +295,57 @@ namespace source delete m_base; } + pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base) + : type_expression(position), m_base(base) + { + } + + void pointer_type_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + type_expression& pointer_type_expression::base() + { + return *m_base; + } + + const std::string& pointer_type_expression::base_name() + { + return base().base_name(); + } + + pointer_type_expression *pointer_type_expression::is_pointer() + { + return this; + } + + pointer_type_expression::~pointer_type_expression() + { + delete m_base; + } + + record_type_expression::record_type_expression(const struct position position, + record_type_expression::fields_t&& fields) + : type_expression(position), m_fields(std::move(fields)) + { + } + + void record_type_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + record_type_expression::fields_t& record_type_expression::fields() + { + return m_fields; + } + + record_type_expression *record_type_expression::is_record() + { + return this; + } + declaration::declaration(const struct position position, const std::string& identifier, type_expression *type) : definition(position, identifier), m_type(type) @@ -504,6 +588,63 @@ namespace source delete m_base; } + field_access_expression::field_access_expression(const struct position position, + designator_expression *base, const std::string& field) + : designator_expression(position), m_base(base), m_field(field) + { + } + + void field_access_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + designator_expression& field_access_expression::base() + { + return *m_base; + } + + std::string& field_access_expression::field() + { + return m_field; + } + + field_access_expression *field_access_expression::is_field_access() + { + return this; + } + + field_access_expression::~field_access_expression() + { + delete m_base; + } + + dereference_expression::dereference_expression(const struct position position, + designator_expression *base) + : designator_expression(position), m_base(base) + { + } + + void dereference_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + designator_expression& dereference_expression::base() + { + return *m_base; + } + + dereference_expression *dereference_expression::is_dereference() + { + return this; + } + + dereference_expression::~dereference_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)) @@ -680,6 +821,16 @@ namespace source return nullptr; } + field_access_expression *designator_expression::is_field_access() + { + return nullptr; + } + + dereference_expression *designator_expression::is_dereference() + { + return nullptr; + } + designator_expression& assign_statement::lvalue() { return *m_lvalue; diff --git a/source/lexer.ll b/source/lexer.ll index de17ce0..5704750 100644 --- a/source/lexer.ll +++ b/source/lexer.ll @@ -70,7 +70,9 @@ of { type { return yy::parser::make_TYPE(this->location); } - +record { + return yy::parser::make_RECORD(this->location); + } true { return yy::parser::make_BOOLEAN(true, this->location); } diff --git a/source/parser.yy b/source/parser.yy index b7c11bb..db04bdb 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -63,7 +63,7 @@ %token STRING "string" %token BOOLEAN %token IF WHILE DO -%token CONST VAR PROCEDURE ARRAY OF TYPE +%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD %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 @@ -315,14 +315,17 @@ type_expression: { $$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2); } + | HAT type_expression + { + $$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $2); + } | IDENTIFIER { $$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1); } variable_declaration: IDENTIFIER COLON type_expression { - $$ = new elna::source::declaration(elna::source::make_position(@1), - $1, $3); + $$ = new elna::source::declaration(elna::source::make_position(@1), $1, $3); }; variable_declarations: variable_declaration COMMA variable_declarations diff --git a/source/result.cc b/source/result.cc index a7b493d..21388ca 100644 --- a/source/result.cc +++ b/source/result.cc @@ -21,16 +21,5 @@ namespace source { return this->position.column; } - - name_collision::name_collision(const std::string& name, const char *path, - const struct position current, const struct position previous) - : error(path, current), previous(previous), name(name) - { - } - - std::string name_collision::what() const - { - return "Name '" + name + "' was already defined"; - } } }