diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 0bb31ed..96c9435 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -282,37 +282,56 @@ namespace gcc this->current_expression = NULL_TREE; } + tree generic_visitor::build_type(source::type_expression& type) + { + if (source::basic_type_expression *basic_type = type.is_basic()) + { + if (basic_type->base_name() == "Int") + { + return integer_type_node; + } + else if (basic_type->base_name() == "Bool") + { + return boolean_type_node; + } + else if (basic_type->base_name() == "Float") + { + return double_type_node; + } + else if (basic_type->base_name() == "Char") + { + return elna_char_type_node; + } + else if (basic_type->base_name() == "String") + { + return elna_string_type_node; + } + } + else if (source::array_type_expression *array_type = type.is_array()) + { + tree lower_bound = build_int_cst_type(integer_type_node, 0); + tree upper_bound = build_int_cst_type(integer_type_node, array_type->size); + tree base_type = build_type(array_type->base()); + + if (base_type == NULL_TREE) + { + return NULL_TREE; + } + tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound); + + return build_array_type(base_type, range_type); + } + return NULL_TREE; + } + void generic_visitor::visit(source::declaration *declaration) { - tree declaration_type = error_mark_node; - source::basic_type_expression *basic_type = declaration->type().is_basic(); + tree declaration_type = build_type(declaration->type()); - gcc_assert(basic_type != nullptr); - - if (basic_type->base() == "Int") - { - declaration_type = integer_type_node; - } - else if (basic_type->base() == "Bool") - { - declaration_type = boolean_type_node; - } - else if (basic_type->base() == "Float") - { - declaration_type = double_type_node; - } - else if (basic_type->base() == "Char") - { - declaration_type = elna_char_type_node; - } - else if (basic_type->base() == "String") - { - declaration_type = elna_string_type_node; - } - else + if (declaration_type == NULL_TREE) { error_at(get_location(&declaration->type().position()), - "type '%s' not declared", basic_type->base().c_str()); + "type '%s' not declared", declaration->type().base_name().c_str()); return; } auto declaration_location = get_location(&declaration->position()); diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 1fb335b..2b29efa 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -25,6 +25,7 @@ namespace gcc tree_chain variable_chain; tree build_label_decl(const char *name, location_t loc); + tree build_type(source::type_expression& type); void enter_scope(); tree_symbol_mapping leave_scope(); diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index 4331ea6..ba2aa2b 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -47,6 +47,7 @@ namespace source class binary_expression; class unary_expression; class basic_type_expression; + class array_type_expression; class variable_expression; template class number_literal; @@ -71,6 +72,7 @@ namespace source virtual void visit(binary_expression *) = 0; virtual void visit(unary_expression *) = 0; virtual void visit(basic_type_expression *) = 0; + virtual void visit(array_type_expression *) = 0; virtual void visit(variable_expression *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; @@ -97,6 +99,7 @@ namespace source virtual void visit(binary_expression *expression) override; virtual void visit(unary_expression *expression) override; virtual void visit(basic_type_expression *) override; + virtual void visit(array_type_expression *) override; virtual void visit(variable_expression *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; @@ -111,7 +114,7 @@ namespace source struct operand { public: - virtual ~operand() noexcept = 0; + virtual ~operand() = 0; }; struct integer_operand final : public operand @@ -121,7 +124,7 @@ namespace source public: explicit integer_operand(const std::int32_t value); - std::int32_t value() const noexcept; + std::int32_t value() const; }; class variable_operand final : public operand @@ -131,7 +134,7 @@ namespace source public: explicit variable_operand(const std::string& name); - const std::string& name() const noexcept; + const std::string& name() const; }; struct temporary_variable final : public operand @@ -141,7 +144,7 @@ namespace source public: explicit temporary_variable(const std::size_t counter); - std::size_t counter() const noexcept; + std::size_t counter() const; }; struct label_operand final : public operand @@ -151,7 +154,7 @@ namespace source public: explicit label_operand(const std::size_t counter); - std::size_t counter() const noexcept; + std::size_t counter() const; }; /** @@ -168,13 +171,13 @@ namespace source explicit node(const position position); public: - virtual ~node() noexcept = default; + virtual ~node() = default; virtual void accept(parser_visitor *) = 0; /** * \return Node position in the source code. */ - const struct position& position() const noexcept; + const struct position& position() const; }; class statement : public node @@ -219,7 +222,7 @@ namespace source /** * \return Definition name. */ - std::string& identifier() noexcept; + std::string& identifier(); }; /** @@ -228,7 +231,9 @@ namespace source class type_expression : public node { public: + virtual const std::string& base_name() = 0; virtual basic_type_expression *is_basic(); + virtual array_type_expression *is_array(); protected: type_expression(const struct position position); @@ -239,7 +244,7 @@ namespace source */ class basic_type_expression : public type_expression { - std::string m_base; + const std::string m_name; public: /** @@ -249,14 +254,40 @@ namespace source basic_type_expression(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; - /** - * \return Name of the base type. - */ - const std::string& base() const noexcept; + const std::string& base_name() override; basic_type_expression *is_basic() override; }; + class array_type_expression : public type_expression + { + 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; + + array_type_expression *is_array() override; + + virtual ~array_type_expression() override; + }; + /** * Variable declaration. */ @@ -276,7 +307,7 @@ namespace source type_expression *type); virtual void accept(parser_visitor *visitor) override; - type_expression& type() noexcept; + type_expression& type(); virtual ~declaration() override; }; @@ -322,7 +353,7 @@ namespace source virtual void accept(parser_visitor *visitor) override; block& body(); - std::vector& parameters() noexcept; + std::vector& parameters(); virtual ~procedure_definition() override; }; @@ -343,8 +374,8 @@ namespace source call_statement(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; - std::string& name() noexcept; - std::vector& arguments() noexcept; + std::string& name(); + std::vector& arguments(); virtual ~call_statement() override; }; @@ -377,7 +408,7 @@ namespace source expression *rvalue); virtual void accept(parser_visitor *visitor) override; - std::string& lvalue() noexcept; + std::string& lvalue(); expression& rvalue(); virtual ~assign_statement() override; @@ -447,8 +478,8 @@ namespace source virtual void accept(parser_visitor *visitor) override; statement& body(); - std::vector& definitions() noexcept; - std::vector& declarations() noexcept; + std::vector& definitions(); + std::vector& declarations(); virtual ~block() override; }; @@ -478,7 +509,7 @@ namespace source visitor->visit(this); } - T number() const noexcept + T number() const { return m_number; } @@ -492,7 +523,7 @@ namespace source char_literal(const struct position position, const unsigned char value); virtual void accept(parser_visitor *visitor) override; - unsigned char character() const noexcept; + unsigned char character() const; }; class string_literal : public expression @@ -503,7 +534,7 @@ namespace source string_literal(const struct position position, const std::string& value); virtual void accept(parser_visitor *visitor) override; - const std::string& string() const noexcept; + const std::string& string() const; }; class variable_expression : public expression @@ -514,7 +545,7 @@ namespace source variable_expression(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; - const std::string& name() const noexcept; + const std::string& name() const; }; class binary_expression : public expression @@ -530,7 +561,7 @@ namespace source virtual void accept(parser_visitor *visitor) override; expression& lhs(); expression& rhs(); - binary_operator operation() const noexcept; + binary_operator operation() const; virtual ~binary_expression() override; }; @@ -546,7 +577,7 @@ namespace source virtual void accept(parser_visitor *visitor) override; expression& operand(); - unary_operator operation() const noexcept; + unary_operator operation() const; virtual ~unary_expression() override; }; diff --git a/source/ast.cc b/source/ast.cc index 0021ea7..2b5b86d 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -91,6 +91,10 @@ namespace source { } + void empty_visitor::visit(array_type_expression *) + { + } + void empty_visitor::visit(variable_expression *) { } @@ -115,7 +119,7 @@ namespace source { } - operand::~operand() noexcept + operand::~operand() { } @@ -124,7 +128,7 @@ namespace source { } - std::int32_t integer_operand::value() const noexcept + std::int32_t integer_operand::value() const { return m_value; } @@ -134,7 +138,7 @@ namespace source { } - const std::string& variable_operand::name() const noexcept + const std::string& variable_operand::name() const { return m_name; } @@ -144,7 +148,7 @@ namespace source { } - std::size_t temporary_variable::counter() const noexcept + std::size_t temporary_variable::counter() const { return m_counter; } @@ -154,7 +158,7 @@ namespace source { } - std::size_t label_operand::counter() const noexcept + std::size_t label_operand::counter() const { return m_counter; } @@ -164,7 +168,7 @@ namespace source { } - const struct position& node::position() const noexcept + const struct position& node::position() const { return this->source_position; } @@ -189,9 +193,14 @@ namespace source return nullptr; } + array_type_expression *type_expression::is_array() + { + return nullptr; + } + basic_type_expression::basic_type_expression( const struct position position, const std::string& name) - : type_expression(position), m_base(name) + : type_expression(position), m_name(name) { } @@ -200,9 +209,9 @@ namespace source visitor->visit(this); } - const std::string& basic_type_expression::base() const noexcept + const std::string& basic_type_expression::base_name() { - return m_base; + return m_name; } basic_type_expression *basic_type_expression::is_basic() @@ -210,6 +219,37 @@ namespace source return this; } + array_type_expression::array_type_expression(const struct position position, type_expression *base, + const std::uint32_t size) + : type_expression(position), m_base(base), size(size) + { + } + + void array_type_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + type_expression& array_type_expression::base() + { + return *m_base; + } + + const std::string& array_type_expression::base_name() + { + return base().base_name(); + } + + array_type_expression *array_type_expression::is_array() + { + return this; + } + + array_type_expression::~array_type_expression() + { + delete m_base; + } + declaration::declaration(const struct position position, const std::string& identifier, type_expression *type) : definition(position, identifier), m_type(type) @@ -226,7 +266,7 @@ namespace source visitor->visit(this); } - type_expression& declaration::type() noexcept + type_expression& declaration::type() { return *m_type; } @@ -236,7 +276,7 @@ namespace source { } - std::string& definition::identifier() noexcept + std::string& definition::identifier() { return m_identifier; } @@ -278,7 +318,7 @@ namespace source return *m_body; } - std::vector& procedure_definition::parameters() noexcept + std::vector& procedure_definition::parameters() { return m_parameters; } @@ -310,12 +350,12 @@ namespace source return *m_body; } - std::vector& block::definitions() noexcept + std::vector& block::definitions() { return m_definitions; } - std::vector& block::declarations() noexcept + std::vector& block::declarations() { return m_declarations; } @@ -355,7 +395,7 @@ namespace source visitor->visit(this); } - unsigned char char_literal::character() const noexcept + unsigned char char_literal::character() const { return m_character; } @@ -370,7 +410,7 @@ namespace source visitor->visit(this); } - const std::string& string_literal::string() const noexcept + const std::string& string_literal::string() const { return m_string; } @@ -385,7 +425,7 @@ namespace source visitor->visit(this); } - const std::string& variable_expression::name() const noexcept + const std::string& variable_expression::name() const { return m_name; } @@ -446,7 +486,7 @@ namespace source return *m_rhs; } - binary_operator binary_expression::operation() const noexcept + binary_operator binary_expression::operation() const { return m_operator; } @@ -484,7 +524,7 @@ namespace source return *m_operand; } - unary_operator unary_expression::operation() const noexcept + unary_operator unary_expression::operation() const { return this->m_operator; } @@ -504,12 +544,12 @@ namespace source visitor->visit(this); } - std::string& call_statement::name() noexcept + std::string& call_statement::name() { return m_name; } - std::vector& call_statement::arguments() noexcept + std::vector& call_statement::arguments() { return m_arguments; } @@ -556,7 +596,7 @@ namespace source { } - std::string& assign_statement::lvalue() noexcept + std::string& assign_statement::lvalue() { return m_lvalue; } diff --git a/source/lexer.ll b/source/lexer.ll index 4e63adc..16d40d2 100644 --- a/source/lexer.ll +++ b/source/lexer.ll @@ -61,6 +61,12 @@ const { var { return yy::parser::make_VAR(this->location); } +array { + return yy::parser::make_ARRAY(this->location); + } +of { + return yy::parser::make_OF(this->location); + } true { return yy::parser::make_BOOLEAN(true, this->location); } diff --git a/source/parser.yy b/source/parser.yy index 7e6180e..9b5abfc 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 +%token CONST VAR PROCEDURE ARRAY OF %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 @@ -83,7 +83,7 @@ %type variable_declaration; %type > variable_declarations variable_declaration_part formal_parameter_list; -%type type_expression; +%type type_expression; %type expression pointer summand factor address comparand; %type > expressions actual_parameter_list; %type variable_expression; @@ -299,7 +299,11 @@ optional_statements: statements { std::swap($$, $1); } | /* no statements */ {} type_expression: - IDENTIFIER + ARRAY INTEGER OF type_expression + { + $$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2); + } + | IDENTIFIER { $$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1); }