Parse pointer types
This commit is contained in:
@ -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));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user