Parse reference and dereference operators
This commit is contained in:
		@@ -398,6 +398,17 @@ namespace elna::riscv
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void visitor::visit(source::unary_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
 | 
			
		||||
        auto operand_identifier = dynamic_cast<source::variable_expression&>(expression->operand()).name();
 | 
			
		||||
        auto variable_symbol =
 | 
			
		||||
            std::dynamic_pointer_cast<source::variable_info>(this->table->lookup(operand_identifier));
 | 
			
		||||
 | 
			
		||||
        this->instructions.push_back(instruction(base_opcode::opImm)
 | 
			
		||||
            .i(free_register, funct3_t::addi, x_register::s0, variable_symbol->offset));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void visitor::visit(source::integer_literal *number)
 | 
			
		||||
    {
 | 
			
		||||
        const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
 | 
			
		||||
 
 | 
			
		||||
@@ -190,6 +190,7 @@ namespace elna::riscv
 | 
			
		||||
        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::unary_expression *expression) override;
 | 
			
		||||
        virtual void visit(source::integer_literal *number) override;
 | 
			
		||||
        virtual void visit(source::boolean_literal *number) override;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,12 @@ namespace elna::source
 | 
			
		||||
        greater_equal
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum class unary_operator
 | 
			
		||||
    {
 | 
			
		||||
        reference,
 | 
			
		||||
        dereference
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class declaration;
 | 
			
		||||
    class constant_definition;
 | 
			
		||||
    class procedure_definition;
 | 
			
		||||
@@ -31,6 +37,7 @@ namespace elna::source
 | 
			
		||||
    class block;
 | 
			
		||||
    class program;
 | 
			
		||||
    class binary_expression;
 | 
			
		||||
    class unary_expression;
 | 
			
		||||
    class type_expression;
 | 
			
		||||
    class variable_expression;
 | 
			
		||||
    class integer_literal;
 | 
			
		||||
@@ -52,6 +59,7 @@ namespace elna::source
 | 
			
		||||
        virtual void visit(block *) = 0;
 | 
			
		||||
        virtual void visit(program *) = 0;
 | 
			
		||||
        virtual void visit(binary_expression *) = 0;
 | 
			
		||||
        virtual void visit(unary_expression *) = 0;
 | 
			
		||||
        virtual void visit(type_expression *) = 0;
 | 
			
		||||
        virtual void visit(variable_expression *) = 0;
 | 
			
		||||
        virtual void visit(integer_literal *) = 0;
 | 
			
		||||
@@ -74,6 +82,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(unary_expression *expression) override;
 | 
			
		||||
        virtual void visit(type_expression *variable) override;
 | 
			
		||||
        virtual void visit(variable_expression *variable) override;
 | 
			
		||||
        virtual void visit(integer_literal *number) override;
 | 
			
		||||
@@ -401,8 +410,23 @@ namespace elna::source
 | 
			
		||||
        binary_operator operation() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class unary_expression : public expression
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> m_operand;
 | 
			
		||||
        unary_operator m_operator;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        unary_expression(const struct position position, std::unique_ptr<expression>&& operand,
 | 
			
		||||
                const unsigned char operation);
 | 
			
		||||
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
        expression& operand();
 | 
			
		||||
        unary_operator operation() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class parser : boost::noncopyable
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> parse_unary_expression();
 | 
			
		||||
        std::unique_ptr<expression> parse_factor();
 | 
			
		||||
        std::unique_ptr<expression> parse_term();
 | 
			
		||||
        std::unique_ptr<expression> parse_expression();
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,11 @@ namespace elna::source
 | 
			
		||||
        expression->rhs().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(unary_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->operand().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(type_expression *variable)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -343,6 +348,33 @@ namespace elna::source
 | 
			
		||||
        return m_operator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unary_expression::unary_expression(const struct position position, std::unique_ptr<expression>&& operand,
 | 
			
		||||
            const unsigned char operation)
 | 
			
		||||
        : expression(position), m_operand(std::move(operand))
 | 
			
		||||
    {
 | 
			
		||||
        switch (operation)
 | 
			
		||||
        {
 | 
			
		||||
            case '@':
 | 
			
		||||
                this->m_operator = unary_operator::reference;
 | 
			
		||||
                break;
 | 
			
		||||
            case '^': 
 | 
			
		||||
                this->m_operator = unary_operator::dereference;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw std::logic_error("Invalid unary operator");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void unary_expression::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression& unary_expression::operand()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_operand;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    call_statement::call_statement(const struct position position, const std::string& name)
 | 
			
		||||
        : statement(position), m_name(name)
 | 
			
		||||
    {
 | 
			
		||||
@@ -477,33 +509,63 @@ namespace elna::source
 | 
			
		||||
        return iterator.errors();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_unary_expression()
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> result;
 | 
			
		||||
 | 
			
		||||
        if (iterator.current(token::type::at))
 | 
			
		||||
        {
 | 
			
		||||
            std::unique_ptr<expression> body_expression;
 | 
			
		||||
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            if ((body_expression = parse_factor()) == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                return nullptr;
 | 
			
		||||
            }
 | 
			
		||||
            result = std::make_unique<unary_expression>(iterator->position(), std::move(body_expression), '@');
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if ((result = parse_factor()) == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                return nullptr;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (iterator.current(token::type::hat))
 | 
			
		||||
        {
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            result = std::make_unique<unary_expression>(iterator->position(), std::move(result), '^');
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_factor()
 | 
			
		||||
    {
 | 
			
		||||
        if (iterator->of() == source::token::type::identifier)
 | 
			
		||||
        if (iterator->of() == token::type::identifier)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<variable_expression>(iterator->position(), iterator->identifier());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (iterator->of() == source::token::token::type::number)
 | 
			
		||||
        else if (iterator->of() == token::token::type::number)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<integer_literal>(iterator->position(), iterator->number());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (iterator->of() == source::token::token::type::boolean)
 | 
			
		||||
        else if (iterator->of() == token::token::type::boolean)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<boolean_literal>(iterator->position(), iterator->number());
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (iterator->of() == source::token::type::left_paren)
 | 
			
		||||
        else if (iterator->of() == token::type::left_paren)
 | 
			
		||||
        {
 | 
			
		||||
            ++iterator;
 | 
			
		||||
 | 
			
		||||
            auto expression = parse_condition();
 | 
			
		||||
 | 
			
		||||
            ++iterator;
 | 
			
		||||
            iterator.advance(token::type::right_paren);
 | 
			
		||||
 | 
			
		||||
            return expression;
 | 
			
		||||
        }
 | 
			
		||||
@@ -512,7 +574,7 @@ namespace elna::source
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_term()
 | 
			
		||||
    {
 | 
			
		||||
        auto lhs = parse_factor();
 | 
			
		||||
        auto lhs = parse_unary_expression();
 | 
			
		||||
        if (lhs == nullptr || iterator.current().of() != source::token::type::factor_operator)
 | 
			
		||||
        {
 | 
			
		||||
            return lhs;
 | 
			
		||||
@@ -523,7 +585,7 @@ namespace elna::source
 | 
			
		||||
            const auto operator_position = iterator->position();
 | 
			
		||||
            ++iterator;
 | 
			
		||||
 | 
			
		||||
            auto rhs = parse_factor();
 | 
			
		||||
            auto rhs = parse_unary_expression();
 | 
			
		||||
            lhs = std::make_unique<binary_expression>(operator_position, std::move(lhs),
 | 
			
		||||
                    std::move(rhs), _operator);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user