Parse pointer types
This commit is contained in:
		
							
								
								
									
										2
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								TODO
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
# Compiler
 | 
			
		||||
 | 
			
		||||
- Catch exceptions thrown by the argument parser and print them normally.
 | 
			
		||||
- Provide position information on parse tree nodes.
 | 
			
		||||
- Structs or records.
 | 
			
		||||
- While loop.
 | 
			
		||||
- Type checking.
 | 
			
		||||
- Calculate additional stack space needed for subexpressions in the allocator
 | 
			
		||||
 
 | 
			
		||||
@@ -289,6 +289,10 @@ namespace elna::riscv
 | 
			
		||||
        statement->body().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void visitor::visit(source::type_expression *type)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void visitor::visit(source::variable_expression *variable)
 | 
			
		||||
    {
 | 
			
		||||
        const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
 | 
			
		||||
 
 | 
			
		||||
@@ -187,6 +187,7 @@ namespace elna::riscv
 | 
			
		||||
        virtual void visit(source::while_statement *statement) override;
 | 
			
		||||
        virtual void visit(source::block *block) override;
 | 
			
		||||
        virtual void visit(source::program *program) override;
 | 
			
		||||
        virtual void visit(source::type_expression *variable) override;
 | 
			
		||||
        virtual void visit(source::variable_expression *variable) override;
 | 
			
		||||
        virtual void visit(source::binary_expression *expression) override;
 | 
			
		||||
        virtual void visit(source::integer_literal *number) override;
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,9 @@ namespace elna::source
 | 
			
		||||
            loop,
 | 
			
		||||
            _do,
 | 
			
		||||
            procedure,
 | 
			
		||||
            comparison_operator
 | 
			
		||||
            comparison_operator,
 | 
			
		||||
            hat,
 | 
			
		||||
            at
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,14 @@ namespace elna::source
 | 
			
		||||
    class block;
 | 
			
		||||
    class program;
 | 
			
		||||
    class binary_expression;
 | 
			
		||||
    class type_expression;
 | 
			
		||||
    class variable_expression;
 | 
			
		||||
    class integer_literal;
 | 
			
		||||
    class boolean_literal;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Interface for AST visitors.
 | 
			
		||||
     */
 | 
			
		||||
    struct parser_visitor
 | 
			
		||||
    {
 | 
			
		||||
        virtual void visit(declaration *) = 0;
 | 
			
		||||
@@ -48,11 +52,15 @@ namespace elna::source
 | 
			
		||||
        virtual void visit(block *) = 0;
 | 
			
		||||
        virtual void visit(program *) = 0;
 | 
			
		||||
        virtual void visit(binary_expression *) = 0;
 | 
			
		||||
        virtual void visit(type_expression *) = 0;
 | 
			
		||||
        virtual void visit(variable_expression *) = 0;
 | 
			
		||||
        virtual void visit(integer_literal *) = 0;
 | 
			
		||||
        virtual void visit(boolean_literal *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * A visitor which visits all nodes but does nothing.
 | 
			
		||||
     */
 | 
			
		||||
    struct empty_visitor : parser_visitor
 | 
			
		||||
    {
 | 
			
		||||
        virtual void visit(declaration *declaration) override;
 | 
			
		||||
@@ -66,6 +74,7 @@ namespace elna::source
 | 
			
		||||
        virtual void visit(block *block) override;
 | 
			
		||||
        virtual void visit(program *program) override;
 | 
			
		||||
        virtual void visit(binary_expression *expression) override;
 | 
			
		||||
        virtual void visit(type_expression *variable) override;
 | 
			
		||||
        virtual void visit(variable_expression *variable) override;
 | 
			
		||||
        virtual void visit(integer_literal *number) override;
 | 
			
		||||
        virtual void visit(boolean_literal *boolean) override;
 | 
			
		||||
@@ -76,16 +85,39 @@ namespace elna::source
 | 
			
		||||
     */
 | 
			
		||||
    class node
 | 
			
		||||
    {
 | 
			
		||||
        const struct position source_position;
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         */
 | 
			
		||||
        explicit node(const position position);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void accept(parser_visitor *) = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * \return Node position in the source code.
 | 
			
		||||
         */
 | 
			
		||||
        const struct position& position() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class statement : public node
 | 
			
		||||
    {
 | 
			
		||||
    protected:
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         */
 | 
			
		||||
        explicit statement(const struct position position);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class expression : public node
 | 
			
		||||
    {
 | 
			
		||||
    protected:
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         */
 | 
			
		||||
        explicit expression(const struct position position);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -99,9 +131,10 @@ namespace elna::source
 | 
			
		||||
        /**
 | 
			
		||||
         * Constructs a definition identified by some name.
 | 
			
		||||
         *
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param identifier Definition name.
 | 
			
		||||
         */
 | 
			
		||||
        definition(const std::string& identifier);
 | 
			
		||||
        definition(const struct position position, const std::string& identifier);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        /**
 | 
			
		||||
@@ -110,18 +143,51 @@ namespace elna::source
 | 
			
		||||
        std::string& identifier() noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class type_expression : public node
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_base;
 | 
			
		||||
        bool m_pointer{ false };
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param name Type name.
 | 
			
		||||
         * \param is_pointer Whether it is a pointer type.
 | 
			
		||||
         */
 | 
			
		||||
        type_expression(const struct position position, const std::string& name, const bool is_pointer = false);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * \return Name of the base type.
 | 
			
		||||
         */
 | 
			
		||||
        const std::string& base() const noexcept;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * \return Whether the type is a pointer.
 | 
			
		||||
         */
 | 
			
		||||
        bool is_pointer() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Variable declaration.
 | 
			
		||||
     */
 | 
			
		||||
    class declaration : public definition
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_type;
 | 
			
		||||
        std::unique_ptr<type_expression> m_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        declaration(const std::string& identifier, const std::string& type);
 | 
			
		||||
        /**
 | 
			
		||||
         * Constructs a declaration with a name and a type.
 | 
			
		||||
         *
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param identifier Definition name.
 | 
			
		||||
         * \param type Declared type.
 | 
			
		||||
         */
 | 
			
		||||
        declaration(const struct position position, const std::string& identifier,
 | 
			
		||||
                std::unique_ptr<type_expression>&& type);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::string& type() noexcept;
 | 
			
		||||
        type_expression& type() noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -132,32 +198,54 @@ namespace elna::source
 | 
			
		||||
        std::unique_ptr<integer_literal> m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        constant_definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param identifier Constant name.
 | 
			
		||||
         * \param body Constant value.
 | 
			
		||||
         */
 | 
			
		||||
        constant_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                std::unique_ptr<integer_literal>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        integer_literal& body();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Procedure definition.
 | 
			
		||||
     */
 | 
			
		||||
    class procedure_definition : public definition
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<block> m_body;
 | 
			
		||||
        std::vector<std::unique_ptr<declaration>> m_parameters;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param identifier Procedure name.
 | 
			
		||||
         * \param body Procedure body.
 | 
			
		||||
         */
 | 
			
		||||
        procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                std::unique_ptr<block>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        block& body();
 | 
			
		||||
        std::vector<std::unique_ptr<declaration>>& parameters() noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Call statement.
 | 
			
		||||
     */
 | 
			
		||||
    class call_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_name;
 | 
			
		||||
        std::vector<std::unique_ptr<expression>> m_arguments;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        call_statement(const std::string& name);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param name Callable's name.
 | 
			
		||||
         */
 | 
			
		||||
        call_statement(const struct position position, const std::string& name);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::string& name() noexcept;
 | 
			
		||||
@@ -169,8 +257,7 @@ namespace elna::source
 | 
			
		||||
        std::vector<std::unique_ptr<statement>> m_statements;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        compound_statement() = default;
 | 
			
		||||
        compound_statement(std::vector<std::unique_ptr<statement>>&& statements);
 | 
			
		||||
        explicit compound_statement(const struct position position);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::vector<std::unique_ptr<statement>>& statements();
 | 
			
		||||
@@ -182,33 +269,57 @@ namespace elna::source
 | 
			
		||||
        std::unique_ptr<expression> m_rvalue;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        assign_statement(const std::string& lvalue, std::unique_ptr<expression>&& rvalue);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param lvalue Left-hand side.
 | 
			
		||||
         * \param rvalue Assigned expression.
 | 
			
		||||
         */
 | 
			
		||||
        assign_statement(const struct position position, const std::string& lvalue,
 | 
			
		||||
                std::unique_ptr<expression>&& rvalue);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::string& lvalue() noexcept;
 | 
			
		||||
        expression& rvalue();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If-statement.
 | 
			
		||||
     */
 | 
			
		||||
    class if_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> m_prerequisite;
 | 
			
		||||
        std::unique_ptr<statement> m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        if_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param prerequisite Condition.
 | 
			
		||||
         * \param body Statement executed if the condition is met.
 | 
			
		||||
         */
 | 
			
		||||
        if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
 | 
			
		||||
                std::unique_ptr<statement>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        expression& prerequisite();
 | 
			
		||||
        statement& body();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * While-statement.
 | 
			
		||||
     */
 | 
			
		||||
    class while_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> m_prerequisite;
 | 
			
		||||
        std::unique_ptr<statement> m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        while_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body);
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
         * \param prerequisite Condition.
 | 
			
		||||
         * \param body Statement executed while the condition is met.
 | 
			
		||||
         */
 | 
			
		||||
        while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
 | 
			
		||||
                std::unique_ptr<statement>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        expression& prerequisite();
 | 
			
		||||
@@ -222,7 +333,7 @@ namespace elna::source
 | 
			
		||||
        std::vector<std::unique_ptr<declaration>> m_declarations;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        block(std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
        block(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
                std::vector<std::unique_ptr<declaration>>&& declarations,
 | 
			
		||||
                std::unique_ptr<statement>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
@@ -235,7 +346,7 @@ namespace elna::source
 | 
			
		||||
    class program : public block
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        program(std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
        program(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
                std::vector<std::unique_ptr<declaration>>&& declarations,
 | 
			
		||||
                std::unique_ptr<statement>&& body);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
@@ -246,7 +357,7 @@ namespace elna::source
 | 
			
		||||
        std::int32_t m_number;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        integer_literal(const std::int32_t value);
 | 
			
		||||
        integer_literal(const struct position position, const std::int32_t value);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::int32_t number() const noexcept;
 | 
			
		||||
@@ -257,7 +368,7 @@ namespace elna::source
 | 
			
		||||
        bool m_boolean;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        boolean_literal(const bool value);
 | 
			
		||||
        boolean_literal(const struct position position, const bool value);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        bool boolean() const noexcept;
 | 
			
		||||
@@ -268,7 +379,7 @@ namespace elna::source
 | 
			
		||||
        std::string m_name;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        variable_expression(const std::string& name);
 | 
			
		||||
        variable_expression(const struct position position, const std::string& name);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        const std::string& name() const noexcept;
 | 
			
		||||
@@ -281,7 +392,7 @@ namespace elna::source
 | 
			
		||||
        binary_operator m_operator;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        binary_expression(std::unique_ptr<expression>&& lhs,
 | 
			
		||||
        binary_expression(const struct position position, std::unique_ptr<expression>&& lhs,
 | 
			
		||||
                std::unique_ptr<expression>&& rhs, const unsigned char operation);
 | 
			
		||||
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
@@ -298,6 +409,7 @@ namespace elna::source
 | 
			
		||||
        std::unique_ptr<expression> parse_condition();
 | 
			
		||||
        std::unique_ptr<constant_definition> parse_constant_definition();
 | 
			
		||||
        std::unique_ptr<procedure_definition> parse_procedure_definition();
 | 
			
		||||
        std::unique_ptr<type_expression> parse_type_expression();
 | 
			
		||||
        std::unique_ptr<declaration> parse_declaration();
 | 
			
		||||
        std::unique_ptr<statement> parse_statement();
 | 
			
		||||
        std::unique_ptr<call_statement> parse_call_statement();
 | 
			
		||||
 
 | 
			
		||||
@@ -149,6 +149,16 @@ namespace elna::source
 | 
			
		||||
        primitive_type(const std::string& type_name, const std::size_t byte_size);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Typed pointer.
 | 
			
		||||
     */
 | 
			
		||||
    struct pointer_type : public type
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<const type> base_type;
 | 
			
		||||
 | 
			
		||||
        pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    inline const primitive_type boolean_type{ "Boolean", 1 };
 | 
			
		||||
    inline const primitive_type int_type{ "Int", 4 };
 | 
			
		||||
 | 
			
		||||
@@ -169,12 +179,12 @@ namespace elna::source
 | 
			
		||||
     */
 | 
			
		||||
    class type_info final : public info
 | 
			
		||||
    {
 | 
			
		||||
        class type m_type;
 | 
			
		||||
        std::shared_ptr<class type> m_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit type_info(const class type& type);
 | 
			
		||||
        ~type_info() override;
 | 
			
		||||
        const class type& type() const noexcept;
 | 
			
		||||
        std::shared_ptr<const class type> type() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -195,14 +205,14 @@ namespace elna::source
 | 
			
		||||
     */
 | 
			
		||||
    class variable_info final : public info
 | 
			
		||||
    {
 | 
			
		||||
        class type m_type;
 | 
			
		||||
        std::shared_ptr<const class type> m_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::ptrdiff_t offset{ 0 };
 | 
			
		||||
 | 
			
		||||
        explicit variable_info(const class type& type);
 | 
			
		||||
        explicit variable_info(std::shared_ptr<const class type> type);
 | 
			
		||||
        ~variable_info() override;
 | 
			
		||||
        const class type& type() const noexcept;
 | 
			
		||||
        std::shared_ptr<const class type> type() noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -210,14 +220,14 @@ namespace elna::source
 | 
			
		||||
     */
 | 
			
		||||
    class parameter_info final : public info
 | 
			
		||||
    {
 | 
			
		||||
        class type m_type;
 | 
			
		||||
        std::shared_ptr<const class type> m_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::ptrdiff_t offset{ 0 };
 | 
			
		||||
 | 
			
		||||
        explicit parameter_info(const class type& type);
 | 
			
		||||
        explicit parameter_info(std::shared_ptr<const class type> type);
 | 
			
		||||
        ~parameter_info() override;
 | 
			
		||||
        const class type& type() const noexcept;
 | 
			
		||||
        std::shared_ptr<const class type> type() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<symbol_table> table = std::make_shared<symbol_table>();
 | 
			
		||||
 | 
			
		||||
        std::shared_ptr<const type> convert_declaration_type(const type_expression& ast_type) const;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        name_analysis_visitor(std::shared_ptr<symbol_table> table);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,10 @@ namespace elna::source
 | 
			
		||||
        expression->rhs().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(type_expression *variable)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(variable_expression *variable)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -90,12 +94,49 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void node::accept(parser_visitor *)
 | 
			
		||||
    node::node(const struct position position)
 | 
			
		||||
        : source_position(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    declaration::declaration(const std::string& identifier, const std::string& type)
 | 
			
		||||
        : definition(identifier), m_type(type)
 | 
			
		||||
    const struct position& node::position() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return this->source_position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    statement::statement(const struct position position)
 | 
			
		||||
        : node(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression::expression(const struct position position)
 | 
			
		||||
        : node(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_expression::type_expression(const struct position position, const std::string& name, const bool is_pointer)
 | 
			
		||||
        : node(position), m_base(name), m_pointer(is_pointer)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_expression::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::string& type_expression::base() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_base;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool type_expression::is_pointer() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_pointer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    declaration::declaration(const struct position position, const std::string& identifier,
 | 
			
		||||
            std::unique_ptr<type_expression>&& type)
 | 
			
		||||
        : definition(position, identifier), m_type(std::move(type))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -104,13 +145,13 @@ namespace elna::source
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string& declaration::type() noexcept
 | 
			
		||||
    type_expression& declaration::type() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_type;
 | 
			
		||||
        return *m_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    definition::definition(const std::string& identifier)
 | 
			
		||||
        : m_identifier(identifier)
 | 
			
		||||
    definition::definition(const struct position position, const std::string& identifier)
 | 
			
		||||
        : node(position), m_identifier(identifier)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -119,8 +160,9 @@ namespace elna::source
 | 
			
		||||
        return m_identifier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constant_definition::constant_definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body)
 | 
			
		||||
        : definition(identifier), m_body(std::move(body))
 | 
			
		||||
    constant_definition::constant_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            std::unique_ptr<integer_literal>&& body)
 | 
			
		||||
        : definition(position, identifier), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -134,8 +176,9 @@ namespace elna::source
 | 
			
		||||
        return *m_body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_definition::procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body)
 | 
			
		||||
        : definition(identifier), m_body(std::move(body))
 | 
			
		||||
    procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            std::unique_ptr<block>&& body)
 | 
			
		||||
        : definition(position, identifier), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -154,10 +197,10 @@ namespace elna::source
 | 
			
		||||
        return m_parameters;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    block::block(std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
    block::block(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
            std::vector<std::unique_ptr<declaration>>&& declarations,
 | 
			
		||||
            std::unique_ptr<statement>&& body)
 | 
			
		||||
        : m_definitions(std::move(definitions)),
 | 
			
		||||
        : node(position), m_definitions(std::move(definitions)),
 | 
			
		||||
        m_declarations(std::move(declarations)), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -182,10 +225,10 @@ namespace elna::source
 | 
			
		||||
        return m_declarations;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    program::program(std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
    program::program(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
 | 
			
		||||
            std::vector<std::unique_ptr<declaration>>&& declarations,
 | 
			
		||||
            std::unique_ptr<statement>&& body)
 | 
			
		||||
        : block(std::move(definitions), std::move(declarations), std::move(body))
 | 
			
		||||
        : block(position, std::move(definitions), std::move(declarations), std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -194,8 +237,8 @@ namespace elna::source
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    integer_literal::integer_literal(const std::int32_t value)
 | 
			
		||||
        : m_number(value)
 | 
			
		||||
    integer_literal::integer_literal(const struct position position, const std::int32_t value)
 | 
			
		||||
        : expression(position), m_number(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -209,8 +252,8 @@ namespace elna::source
 | 
			
		||||
        return m_number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean_literal::boolean_literal(const bool value)
 | 
			
		||||
        : m_boolean(value)
 | 
			
		||||
    boolean_literal::boolean_literal(const struct position position, const bool value)
 | 
			
		||||
        : expression(position), m_boolean(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -224,8 +267,8 @@ namespace elna::source
 | 
			
		||||
        return m_boolean;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_expression::variable_expression(const std::string& name)
 | 
			
		||||
        : m_name(name)
 | 
			
		||||
    variable_expression::variable_expression(const struct position position, const std::string& name)
 | 
			
		||||
        : expression(position), m_name(name)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -239,9 +282,9 @@ namespace elna::source
 | 
			
		||||
        return m_name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    binary_expression::binary_expression(std::unique_ptr<expression>&& lhs,
 | 
			
		||||
    binary_expression::binary_expression(const struct position position, std::unique_ptr<expression>&& lhs,
 | 
			
		||||
            std::unique_ptr<expression>&& rhs, const unsigned char operation)
 | 
			
		||||
        : m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
 | 
			
		||||
        : expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
 | 
			
		||||
    {
 | 
			
		||||
        switch (operation)
 | 
			
		||||
        {
 | 
			
		||||
@@ -300,8 +343,8 @@ namespace elna::source
 | 
			
		||||
        return m_operator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    call_statement::call_statement(const std::string& name)
 | 
			
		||||
        : m_name(name)
 | 
			
		||||
    call_statement::call_statement(const struct position position, const std::string& name)
 | 
			
		||||
        : statement(position), m_name(name)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -320,8 +363,8 @@ namespace elna::source
 | 
			
		||||
        return m_arguments;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements)
 | 
			
		||||
        : m_statements(std::move(statements))
 | 
			
		||||
    compound_statement::compound_statement(const struct position position)
 | 
			
		||||
        : statement(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -340,8 +383,9 @@ namespace elna::source
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assign_statement::assign_statement(const std::string& lvalue, std::unique_ptr<expression>&& rvalue)
 | 
			
		||||
        : m_lvalue(lvalue), m_rvalue(std::move(rvalue))
 | 
			
		||||
    assign_statement::assign_statement(const struct position position, const std::string& lvalue,
 | 
			
		||||
            std::unique_ptr<expression>&& rvalue)
 | 
			
		||||
        : statement(position), m_lvalue(lvalue), m_rvalue(std::move(rvalue))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -355,8 +399,9 @@ namespace elna::source
 | 
			
		||||
        return *m_rvalue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if_statement::if_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body)
 | 
			
		||||
        : m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
 | 
			
		||||
    if_statement::if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
 | 
			
		||||
            std::unique_ptr<statement>&& body)
 | 
			
		||||
        : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -375,8 +420,9 @@ namespace elna::source
 | 
			
		||||
        return *m_body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement::while_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body)
 | 
			
		||||
        : m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
 | 
			
		||||
    while_statement::while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
 | 
			
		||||
            std::unique_ptr<statement>&& body)
 | 
			
		||||
        : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -422,7 +468,7 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            *definition++ = std::move(procedure);
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<program>(std::move(definitions),
 | 
			
		||||
        return std::make_unique<program>(position(), std::move(definitions),
 | 
			
		||||
                std::move(declarations), std::move(parsed_statement));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -435,19 +481,19 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
        if (iterator->of() == source::token::type::identifier)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<variable_expression>(iterator->identifier());
 | 
			
		||||
            auto result = std::make_unique<variable_expression>(iterator->position(), iterator->identifier());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (iterator->of() == source::token::token::type::number)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<integer_literal>(iterator->number());
 | 
			
		||||
            auto result = std::make_unique<integer_literal>(iterator->position(), iterator->number());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (iterator->of() == source::token::token::type::boolean)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<boolean_literal>(iterator->number());
 | 
			
		||||
            auto result = std::make_unique<boolean_literal>(iterator->position(), iterator->number());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
@@ -474,10 +520,11 @@ namespace elna::source
 | 
			
		||||
        while (iterator->of() == source::token::type::factor_operator)
 | 
			
		||||
        {
 | 
			
		||||
            auto _operator = iterator->identifier()[0];
 | 
			
		||||
            const auto operator_position = iterator->position();
 | 
			
		||||
            ++iterator;
 | 
			
		||||
 | 
			
		||||
            auto rhs = parse_factor();
 | 
			
		||||
            lhs = std::make_unique<binary_expression>(std::move(lhs),
 | 
			
		||||
            lhs = std::make_unique<binary_expression>(operator_position, std::move(lhs),
 | 
			
		||||
                    std::move(rhs), _operator);
 | 
			
		||||
        }
 | 
			
		||||
        return lhs;
 | 
			
		||||
@@ -493,10 +540,11 @@ namespace elna::source
 | 
			
		||||
        while (iterator->of() == source::token::type::term_operator)
 | 
			
		||||
        {
 | 
			
		||||
            auto _operator = iterator->identifier()[0];
 | 
			
		||||
            const auto operator_position = iterator->position();
 | 
			
		||||
            ++iterator;
 | 
			
		||||
 | 
			
		||||
            auto rhs = parse_term();
 | 
			
		||||
            term = std::make_unique<binary_expression>(std::move(term),
 | 
			
		||||
            term = std::make_unique<binary_expression>(operator_position, std::move(term),
 | 
			
		||||
                    std::move(rhs), _operator);
 | 
			
		||||
        }
 | 
			
		||||
        return term;
 | 
			
		||||
@@ -524,6 +572,7 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return lhs;
 | 
			
		||||
        }
 | 
			
		||||
        const auto operator_position = iterator->position();
 | 
			
		||||
        ++iterator;
 | 
			
		||||
        auto rhs = parse_expression();
 | 
			
		||||
 | 
			
		||||
@@ -531,12 +580,13 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<binary_expression>(std::move(lhs), std::move(rhs), _operator);
 | 
			
		||||
        return std::make_unique<binary_expression>(operator_position, std::move(lhs), std::move(rhs), _operator);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<constant_definition> parser::parse_constant_definition()
 | 
			
		||||
    {
 | 
			
		||||
        auto definition_identifier = iterator.advance(token::type::identifier);
 | 
			
		||||
        const auto identifier_position = iterator->position();
 | 
			
		||||
 | 
			
		||||
        if (!definition_identifier.has_value())
 | 
			
		||||
        {
 | 
			
		||||
@@ -549,8 +599,9 @@ namespace elna::source
 | 
			
		||||
 | 
			
		||||
        if (iterator->of() == source::token::type::number)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<constant_definition>(definition_identifier.value().get().identifier(),
 | 
			
		||||
                    std::make_unique<integer_literal>(iterator->number()));
 | 
			
		||||
            auto result = std::make_unique<constant_definition>(identifier_position,
 | 
			
		||||
                    definition_identifier.value().get().identifier(),
 | 
			
		||||
                    std::make_unique<integer_literal>(iterator->position(), iterator->number()));
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
@@ -559,6 +610,7 @@ namespace elna::source
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<procedure_definition> parser::parse_procedure_definition()
 | 
			
		||||
    {
 | 
			
		||||
        const auto proc_position = iterator->position();
 | 
			
		||||
        if (!iterator.skip(token::type::procedure))
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
@@ -597,13 +649,32 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        auto procedure = std::make_unique<procedure_definition>(definition_identifier->get().identifier(),
 | 
			
		||||
                std::move(definition_body));
 | 
			
		||||
        auto procedure = std::make_unique<procedure_definition>(proc_position,
 | 
			
		||||
                definition_identifier->get().identifier(), std::move(definition_body));
 | 
			
		||||
        procedure->parameters() = std::move(declarations);
 | 
			
		||||
 | 
			
		||||
        return procedure;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<type_expression> parser::parse_type_expression()
 | 
			
		||||
    {
 | 
			
		||||
        const auto type_position = iterator->position();
 | 
			
		||||
        bool is_pointer{ false };
 | 
			
		||||
        if (iterator.current(token::type::hat))
 | 
			
		||||
        {
 | 
			
		||||
            is_pointer = true;
 | 
			
		||||
            ++iterator;
 | 
			
		||||
        }
 | 
			
		||||
        auto type_identifier = iterator.advance(token::type::identifier);
 | 
			
		||||
 | 
			
		||||
        if (!type_identifier.has_value())
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<type_expression>(type_position, type_identifier.value().get().identifier(),
 | 
			
		||||
                is_pointer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<declaration> parser::parse_declaration()
 | 
			
		||||
    {
 | 
			
		||||
        auto declaration_identifier = iterator.advance(token::type::identifier);
 | 
			
		||||
@@ -612,14 +683,14 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        auto type_identifier = iterator.advance(token::type::identifier);
 | 
			
		||||
        auto type_identifier = parse_type_expression();
 | 
			
		||||
 | 
			
		||||
        if (!type_identifier.has_value())
 | 
			
		||||
        if (type_identifier == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<declaration>(declaration_identifier.value().get().identifier(),
 | 
			
		||||
                type_identifier.value().get().identifier());
 | 
			
		||||
        return std::make_unique<declaration>(declaration_identifier.value().get().position(),
 | 
			
		||||
                declaration_identifier.value().get().identifier(), std::move(type_identifier));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<statement> parser::parse_statement()
 | 
			
		||||
@@ -655,7 +726,8 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        auto call = std::make_unique<call_statement>(function_name->get().identifier());
 | 
			
		||||
        auto call = std::make_unique<call_statement>(function_name->get().position(),
 | 
			
		||||
                function_name->get().identifier());
 | 
			
		||||
        std::unique_ptr<expression> argument_expression;
 | 
			
		||||
 | 
			
		||||
        if (iterator.current(token::type::right_paren))
 | 
			
		||||
@@ -682,11 +754,12 @@ namespace elna::source
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<compound_statement> parser::parse_compound_statement()
 | 
			
		||||
    {
 | 
			
		||||
        const auto begin_position = iterator->position();
 | 
			
		||||
        if (!iterator.advance(token::type::begin))
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        auto result = std::make_unique<compound_statement>();
 | 
			
		||||
        auto result = std::make_unique<compound_statement>(begin_position);
 | 
			
		||||
        std::unique_ptr<statement> next_statement;
 | 
			
		||||
 | 
			
		||||
        while ((next_statement = parse_statement()) != nullptr)
 | 
			
		||||
@@ -725,11 +798,13 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<assign_statement>(name.value().get().identifier(), std::move(rvalue));
 | 
			
		||||
        return std::make_unique<assign_statement>(name.value().get().position(), name.value().get().identifier(),
 | 
			
		||||
                std::move(rvalue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<if_statement> parser::parse_if_statement()
 | 
			
		||||
    {
 | 
			
		||||
        const auto if_position = iterator->position();
 | 
			
		||||
        if (!iterator.skip(token::type::when))
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
@@ -746,11 +821,12 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<if_statement>(std::move(condition), std::move(body));
 | 
			
		||||
        return std::make_unique<if_statement>(if_position, std::move(condition), std::move(body));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<while_statement> parser::parse_while_statement()
 | 
			
		||||
    {
 | 
			
		||||
        const auto while_position = iterator->position();
 | 
			
		||||
        if (!iterator.skip(token::type::loop))
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
@@ -767,7 +843,7 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<while_statement>(std::move(condition), std::move(body));
 | 
			
		||||
        return std::make_unique<while_statement>(while_position, std::move(condition), std::move(body));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<std::unique_ptr<constant_definition>> parser::parse_constant_definitions()
 | 
			
		||||
@@ -870,7 +946,7 @@ namespace elna::source
 | 
			
		||||
        {
 | 
			
		||||
            *definition++ = std::move(constant);
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<block>(std::move(definitions),
 | 
			
		||||
        return std::make_unique<block>(parsed_statement->position(), std::move(definitions),
 | 
			
		||||
                std::move(declarations), std::move(parsed_statement));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,11 @@ namespace elna::source
 | 
			
		||||
    primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size)
 | 
			
		||||
        : type(byte_size), type_name(type_name)
 | 
			
		||||
   {
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
    pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size)
 | 
			
		||||
        : type(byte_size), base_type(base_type)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    symbol_table::symbol_table(std::shared_ptr<symbol_table> scope)
 | 
			
		||||
@@ -48,16 +53,18 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
        if (scope == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            auto boolean_info = std::make_shared<type_info>(boolean_type);
 | 
			
		||||
            auto int_info = std::make_shared<type_info>(int_type);
 | 
			
		||||
            enter("Boolean", boolean_info);
 | 
			
		||||
            enter("Int", int_info);
 | 
			
		||||
 | 
			
		||||
            auto writei = std::make_shared<intrinsic_info>();
 | 
			
		||||
            writei->parameter_infos.emplace_back(int_type);
 | 
			
		||||
            writei->parameter_infos.emplace_back(int_info->type());
 | 
			
		||||
            enter("writei", writei);
 | 
			
		||||
 | 
			
		||||
            auto writeb = std::make_shared<intrinsic_info>();
 | 
			
		||||
            writeb->parameter_infos.emplace_back(boolean_type);
 | 
			
		||||
            writeb->parameter_infos.emplace_back(boolean_info->type());
 | 
			
		||||
            enter("writeb", writeb);
 | 
			
		||||
 | 
			
		||||
            enter("Boolean", std::make_shared<type_info>(boolean_type));
 | 
			
		||||
            enter("Int", std::make_shared<type_info>(int_type));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +102,7 @@ namespace elna::source
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_info::type_info(const class type& type)
 | 
			
		||||
        : info(), m_type(type)
 | 
			
		||||
        : info(), m_type(std::make_shared<class type>(type))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -103,7 +110,7 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const class type& type_info::type() const noexcept
 | 
			
		||||
    std::shared_ptr<const class type> type_info::type() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_type;
 | 
			
		||||
    }
 | 
			
		||||
@@ -122,7 +129,7 @@ namespace elna::source
 | 
			
		||||
        return m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_info::variable_info(const class type& type)
 | 
			
		||||
    variable_info::variable_info(std::shared_ptr<const class type> type)
 | 
			
		||||
        : m_type(type)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -131,12 +138,12 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const class type& variable_info::type() const noexcept
 | 
			
		||||
    std::shared_ptr<const class type> variable_info::type() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    parameter_info::parameter_info(const class type& type)
 | 
			
		||||
    parameter_info::parameter_info(std::shared_ptr<const class type> type)
 | 
			
		||||
        : m_type(type)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -145,7 +152,7 @@ namespace elna::source
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const class type& parameter_info::type() const noexcept
 | 
			
		||||
    std::shared_ptr<const class type> parameter_info::type() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_type;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -159,6 +159,16 @@ False                   {
 | 
			
		||||
 | 
			
		||||
                            return static_cast<int>(elna::source::token::type::colon);
 | 
			
		||||
                        }
 | 
			
		||||
\^                      {
 | 
			
		||||
                            yylval.nil = nullptr;
 | 
			
		||||
 | 
			
		||||
                            return static_cast<int>(elna::source::token::type::hat);
 | 
			
		||||
                        }
 | 
			
		||||
@                       {
 | 
			
		||||
                            yylval.nil = nullptr;
 | 
			
		||||
 | 
			
		||||
                            return static_cast<int>(elna::source::token::type::at);
 | 
			
		||||
                        }
 | 
			
		||||
.                       {
 | 
			
		||||
                            return -1;
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "elna/source/semantic.hpp"
 | 
			
		||||
#include "elna/source/result.hpp"
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
 | 
			
		||||
namespace elna::source
 | 
			
		||||
@@ -14,11 +15,28 @@ namespace elna::source
 | 
			
		||||
                std::make_shared<constant_info>(constant_info(definition->body().number())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const
 | 
			
		||||
    {
 | 
			
		||||
        auto variable_type = std::dynamic_pointer_cast<type_info>(table->lookup(ast_type.base()))
 | 
			
		||||
            ->type();
 | 
			
		||||
        std::shared_ptr<type> declaration_type;
 | 
			
		||||
 | 
			
		||||
        if (ast_type.is_pointer())
 | 
			
		||||
        {
 | 
			
		||||
            return std::make_shared<pointer_type>(variable_type, 4);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return variable_type;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(declaration *declaration)
 | 
			
		||||
    {
 | 
			
		||||
        auto declaration_type = std::dynamic_pointer_cast<type_info>(table->lookup(declaration->type()));
 | 
			
		||||
        std::shared_ptr<const type> declaration_type = convert_declaration_type(declaration->type());
 | 
			
		||||
 | 
			
		||||
        this->table->enter(declaration->identifier(),
 | 
			
		||||
                std::make_shared<variable_info>(declaration_type->type()));
 | 
			
		||||
                std::make_shared<variable_info>(declaration_type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(program *program)
 | 
			
		||||
@@ -35,9 +53,10 @@ namespace elna::source
 | 
			
		||||
 | 
			
		||||
        for (auto& parameter : procedure->parameters())
 | 
			
		||||
        {
 | 
			
		||||
            auto declaration_type = std::dynamic_pointer_cast<type_info>(table->lookup(parameter->type()));
 | 
			
		||||
            auto declaration_type = convert_declaration_type(parameter->type());
 | 
			
		||||
 | 
			
		||||
            this->table->enter(parameter->identifier(),
 | 
			
		||||
                    std::make_shared<parameter_info>(declaration_type->type()));
 | 
			
		||||
                    std::make_shared<parameter_info>(declaration_type));
 | 
			
		||||
        }
 | 
			
		||||
        procedure->body().accept(this);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user