Parse reference and dereference operators
This commit is contained in:
parent
60acf3b9a3
commit
159a3a4f38
@ -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)
|
void visitor::visit(source::integer_literal *number)
|
||||||
{
|
{
|
||||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
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::type_expression *variable) override;
|
||||||
virtual void visit(source::variable_expression *variable) override;
|
virtual void visit(source::variable_expression *variable) override;
|
||||||
virtual void visit(source::binary_expression *expression) 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::integer_literal *number) override;
|
||||||
virtual void visit(source::boolean_literal *number) override;
|
virtual void visit(source::boolean_literal *number) override;
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,12 @@ namespace elna::source
|
|||||||
greater_equal
|
greater_equal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class unary_operator
|
||||||
|
{
|
||||||
|
reference,
|
||||||
|
dereference
|
||||||
|
};
|
||||||
|
|
||||||
class declaration;
|
class declaration;
|
||||||
class constant_definition;
|
class constant_definition;
|
||||||
class procedure_definition;
|
class procedure_definition;
|
||||||
@ -31,6 +37,7 @@ namespace elna::source
|
|||||||
class block;
|
class block;
|
||||||
class program;
|
class program;
|
||||||
class binary_expression;
|
class binary_expression;
|
||||||
|
class unary_expression;
|
||||||
class type_expression;
|
class type_expression;
|
||||||
class variable_expression;
|
class variable_expression;
|
||||||
class integer_literal;
|
class integer_literal;
|
||||||
@ -52,6 +59,7 @@ namespace elna::source
|
|||||||
virtual void visit(block *) = 0;
|
virtual void visit(block *) = 0;
|
||||||
virtual void visit(program *) = 0;
|
virtual void visit(program *) = 0;
|
||||||
virtual void visit(binary_expression *) = 0;
|
virtual void visit(binary_expression *) = 0;
|
||||||
|
virtual void visit(unary_expression *) = 0;
|
||||||
virtual void visit(type_expression *) = 0;
|
virtual void visit(type_expression *) = 0;
|
||||||
virtual void visit(variable_expression *) = 0;
|
virtual void visit(variable_expression *) = 0;
|
||||||
virtual void visit(integer_literal *) = 0;
|
virtual void visit(integer_literal *) = 0;
|
||||||
@ -74,6 +82,7 @@ namespace elna::source
|
|||||||
virtual void visit(block *block) override;
|
virtual void visit(block *block) override;
|
||||||
virtual void visit(program *program) override;
|
virtual void visit(program *program) override;
|
||||||
virtual void visit(binary_expression *expression) 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(type_expression *variable) override;
|
||||||
virtual void visit(variable_expression *variable) override;
|
virtual void visit(variable_expression *variable) override;
|
||||||
virtual void visit(integer_literal *number) override;
|
virtual void visit(integer_literal *number) override;
|
||||||
@ -401,8 +410,23 @@ namespace elna::source
|
|||||||
binary_operator operation() const noexcept;
|
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
|
class parser : boost::noncopyable
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<expression> parse_unary_expression();
|
||||||
std::unique_ptr<expression> parse_factor();
|
std::unique_ptr<expression> parse_factor();
|
||||||
std::unique_ptr<expression> parse_term();
|
std::unique_ptr<expression> parse_term();
|
||||||
std::unique_ptr<expression> parse_expression();
|
std::unique_ptr<expression> parse_expression();
|
||||||
|
@ -78,6 +78,11 @@ namespace elna::source
|
|||||||
expression->rhs().accept(this);
|
expression->rhs().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(unary_expression *expression)
|
||||||
|
{
|
||||||
|
expression->operand().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(type_expression *variable)
|
void empty_visitor::visit(type_expression *variable)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -343,6 +348,33 @@ namespace elna::source
|
|||||||
return m_operator;
|
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)
|
call_statement::call_statement(const struct position position, const std::string& name)
|
||||||
: statement(position), m_name(name)
|
: statement(position), m_name(name)
|
||||||
{
|
{
|
||||||
@ -477,33 +509,63 @@ namespace elna::source
|
|||||||
return iterator.errors();
|
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()
|
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());
|
auto result = std::make_unique<variable_expression>(iterator->position(), iterator->identifier());
|
||||||
++iterator;
|
++iterator;
|
||||||
return result;
|
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());
|
auto result = std::make_unique<integer_literal>(iterator->position(), iterator->number());
|
||||||
++iterator;
|
++iterator;
|
||||||
return result;
|
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());
|
auto result = std::make_unique<boolean_literal>(iterator->position(), iterator->number());
|
||||||
++iterator;
|
++iterator;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if (iterator->of() == source::token::type::left_paren)
|
else if (iterator->of() == token::type::left_paren)
|
||||||
{
|
{
|
||||||
++iterator;
|
++iterator;
|
||||||
|
|
||||||
auto expression = parse_condition();
|
auto expression = parse_condition();
|
||||||
|
|
||||||
++iterator;
|
iterator.advance(token::type::right_paren);
|
||||||
|
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
@ -512,7 +574,7 @@ namespace elna::source
|
|||||||
|
|
||||||
std::unique_ptr<expression> parser::parse_term()
|
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)
|
if (lhs == nullptr || iterator.current().of() != source::token::type::factor_operator)
|
||||||
{
|
{
|
||||||
return lhs;
|
return lhs;
|
||||||
@ -523,7 +585,7 @@ namespace elna::source
|
|||||||
const auto operator_position = iterator->position();
|
const auto operator_position = iterator->position();
|
||||||
++iterator;
|
++iterator;
|
||||||
|
|
||||||
auto rhs = parse_factor();
|
auto rhs = parse_unary_expression();
|
||||||
lhs = std::make_unique<binary_expression>(operator_position, std::move(lhs),
|
lhs = std::make_unique<binary_expression>(operator_position, std::move(lhs),
|
||||||
std::move(rhs), _operator);
|
std::move(rhs), _operator);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user