Parse pointer types

This commit is contained in:
Eugen Wissner 2024-04-07 23:39:56 +02:00
parent aa3df7f4d3
commit 60acf3b9a3
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
11 changed files with 344 additions and 101 deletions

2
TODO
View File

@ -1,7 +1,7 @@
# Compiler # Compiler
- Catch exceptions thrown by the argument parser and print them normally. - Catch exceptions thrown by the argument parser and print them normally.
- Provide position information on parse tree nodes. - Structs or records.
- While loop. - While loop.
- Type checking. - Type checking.
- Calculate additional stack space needed for subexpressions in the allocator - Calculate additional stack space needed for subexpressions in the allocator

View File

@ -289,6 +289,10 @@ namespace elna::riscv
statement->body().accept(this); statement->body().accept(this);
} }
void visitor::visit(source::type_expression *type)
{
}
void visitor::visit(source::variable_expression *variable) void visitor::visit(source::variable_expression *variable)
{ {
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;

View File

@ -187,6 +187,7 @@ namespace elna::riscv
virtual void visit(source::while_statement *statement) override; virtual void visit(source::while_statement *statement) override;
virtual void visit(source::block *block) override; virtual void visit(source::block *block) override;
virtual void visit(source::program *program) 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::variable_expression *variable) override;
virtual void visit(source::binary_expression *expression) override; virtual void visit(source::binary_expression *expression) override;
virtual void visit(source::integer_literal *number) override; virtual void visit(source::integer_literal *number) override;

View File

@ -42,7 +42,9 @@ namespace elna::source
loop, loop,
_do, _do,
procedure, procedure,
comparison_operator comparison_operator,
hat,
at
}; };
/** /**

View File

@ -31,10 +31,14 @@ namespace elna::source
class block; class block;
class program; class program;
class binary_expression; class binary_expression;
class type_expression;
class variable_expression; class variable_expression;
class integer_literal; class integer_literal;
class boolean_literal; class boolean_literal;
/**
* Interface for AST visitors.
*/
struct parser_visitor struct parser_visitor
{ {
virtual void visit(declaration *) = 0; virtual void visit(declaration *) = 0;
@ -48,11 +52,15 @@ 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(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;
virtual void visit(boolean_literal *) = 0; virtual void visit(boolean_literal *) = 0;
}; };
/**
* A visitor which visits all nodes but does nothing.
*/
struct empty_visitor : parser_visitor struct empty_visitor : parser_visitor
{ {
virtual void visit(declaration *declaration) override; virtual void visit(declaration *declaration) override;
@ -66,6 +74,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(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;
virtual void visit(boolean_literal *boolean) override; virtual void visit(boolean_literal *boolean) override;
@ -76,16 +85,39 @@ namespace elna::source
*/ */
class node class node
{ {
const struct position source_position;
protected:
/**
* \param position Source code position.
*/
explicit node(const position position);
public: public:
virtual void accept(parser_visitor *) = 0; virtual void accept(parser_visitor *) = 0;
/**
* \return Node position in the source code.
*/
const struct position& position() const noexcept;
}; };
class statement : public node class statement : public node
{ {
protected:
/**
* \param position Source code position.
*/
explicit statement(const struct position position);
}; };
class expression : public node 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. * Constructs a definition identified by some name.
* *
* \param position Source code position.
* \param identifier Definition name. * \param identifier Definition name.
*/ */
definition(const std::string& identifier); definition(const struct position position, const std::string& identifier);
public: public:
/** /**
@ -110,18 +143,51 @@ namespace elna::source
std::string& identifier() noexcept; 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. * Variable declaration.
*/ */
class declaration : public definition class declaration : public definition
{ {
std::string m_type; std::unique_ptr<type_expression> m_type;
public: 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; 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; std::unique_ptr<integer_literal> m_body;
public: 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; virtual void accept(parser_visitor *visitor) override;
integer_literal& body(); integer_literal& body();
}; };
/**
* Procedure definition.
*/
class procedure_definition : public definition class procedure_definition : public definition
{ {
std::unique_ptr<block> m_body; std::unique_ptr<block> m_body;
std::vector<std::unique_ptr<declaration>> m_parameters; std::vector<std::unique_ptr<declaration>> m_parameters;
public: 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; virtual void accept(parser_visitor *visitor) override;
block& body(); block& body();
std::vector<std::unique_ptr<declaration>>& parameters() noexcept; std::vector<std::unique_ptr<declaration>>& parameters() noexcept;
}; };
/**
* Call statement.
*/
class call_statement : public statement class call_statement : public statement
{ {
std::string m_name; std::string m_name;
std::vector<std::unique_ptr<expression>> m_arguments; std::vector<std::unique_ptr<expression>> m_arguments;
public: 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; virtual void accept(parser_visitor *visitor) override;
std::string& name() noexcept; std::string& name() noexcept;
@ -169,8 +257,7 @@ namespace elna::source
std::vector<std::unique_ptr<statement>> m_statements; std::vector<std::unique_ptr<statement>> m_statements;
public: public:
compound_statement() = default; explicit compound_statement(const struct position position);
compound_statement(std::vector<std::unique_ptr<statement>>&& statements);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
std::vector<std::unique_ptr<statement>>& statements(); std::vector<std::unique_ptr<statement>>& statements();
@ -182,33 +269,57 @@ namespace elna::source
std::unique_ptr<expression> m_rvalue; std::unique_ptr<expression> m_rvalue;
public: 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; virtual void accept(parser_visitor *visitor) override;
std::string& lvalue() noexcept; std::string& lvalue() noexcept;
expression& rvalue(); expression& rvalue();
}; };
/**
* If-statement.
*/
class if_statement : public statement class if_statement : public statement
{ {
std::unique_ptr<expression> m_prerequisite; std::unique_ptr<expression> m_prerequisite;
std::unique_ptr<statement> m_body; std::unique_ptr<statement> m_body;
public: 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; virtual void accept(parser_visitor *visitor) override;
expression& prerequisite(); expression& prerequisite();
statement& body(); statement& body();
}; };
/**
* While-statement.
*/
class while_statement : public statement class while_statement : public statement
{ {
std::unique_ptr<expression> m_prerequisite; std::unique_ptr<expression> m_prerequisite;
std::unique_ptr<statement> m_body; std::unique_ptr<statement> m_body;
public: 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; virtual void accept(parser_visitor *visitor) override;
expression& prerequisite(); expression& prerequisite();
@ -222,7 +333,7 @@ namespace elna::source
std::vector<std::unique_ptr<declaration>> m_declarations; std::vector<std::unique_ptr<declaration>> m_declarations;
public: 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::vector<std::unique_ptr<declaration>>&& declarations,
std::unique_ptr<statement>&& body); std::unique_ptr<statement>&& body);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
@ -235,7 +346,7 @@ namespace elna::source
class program : public block class program : public block
{ {
public: 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::vector<std::unique_ptr<declaration>>&& declarations,
std::unique_ptr<statement>&& body); std::unique_ptr<statement>&& body);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
@ -246,7 +357,7 @@ namespace elna::source
std::int32_t m_number; std::int32_t m_number;
public: 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; virtual void accept(parser_visitor *visitor) override;
std::int32_t number() const noexcept; std::int32_t number() const noexcept;
@ -257,7 +368,7 @@ namespace elna::source
bool m_boolean; bool m_boolean;
public: public:
boolean_literal(const bool value); boolean_literal(const struct position position, const bool value);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
bool boolean() const noexcept; bool boolean() const noexcept;
@ -268,7 +379,7 @@ namespace elna::source
std::string m_name; std::string m_name;
public: public:
variable_expression(const std::string& name); variable_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
const std::string& name() const noexcept; const std::string& name() const noexcept;
@ -281,7 +392,7 @@ namespace elna::source
binary_operator m_operator; binary_operator m_operator;
public: 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); std::unique_ptr<expression>&& rhs, const unsigned char operation);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
@ -298,6 +409,7 @@ namespace elna::source
std::unique_ptr<expression> parse_condition(); std::unique_ptr<expression> parse_condition();
std::unique_ptr<constant_definition> parse_constant_definition(); std::unique_ptr<constant_definition> parse_constant_definition();
std::unique_ptr<procedure_definition> parse_procedure_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<declaration> parse_declaration();
std::unique_ptr<statement> parse_statement(); std::unique_ptr<statement> parse_statement();
std::unique_ptr<call_statement> parse_call_statement(); std::unique_ptr<call_statement> parse_call_statement();

View File

@ -149,6 +149,16 @@ namespace elna::source
primitive_type(const std::string& type_name, const std::size_t byte_size); 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 boolean_type{ "Boolean", 1 };
inline const primitive_type int_type{ "Int", 4 }; inline const primitive_type int_type{ "Int", 4 };
@ -169,12 +179,12 @@ namespace elna::source
*/ */
class type_info final : public info class type_info final : public info
{ {
class type m_type; std::shared_ptr<class type> m_type;
public: public:
explicit type_info(const class type& type); explicit type_info(const class type& type);
~type_info() override; ~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 variable_info final : public info
{ {
class type m_type; std::shared_ptr<const class type> m_type;
public: public:
std::ptrdiff_t offset{ 0 }; 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; ~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 parameter_info final : public info
{ {
class type m_type; std::shared_ptr<const class type> m_type;
public: public:
std::ptrdiff_t offset{ 0 }; 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; ~parameter_info() override;
const class type& type() const noexcept; std::shared_ptr<const class type> type() const noexcept;
}; };
/** /**

View File

@ -8,6 +8,8 @@ namespace elna::source
{ {
std::shared_ptr<symbol_table> table = std::make_shared<symbol_table>(); 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: public:
name_analysis_visitor(std::shared_ptr<symbol_table> table); name_analysis_visitor(std::shared_ptr<symbol_table> table);

View File

@ -78,6 +78,10 @@ namespace elna::source
expression->rhs().accept(this); expression->rhs().accept(this);
} }
void empty_visitor::visit(type_expression *variable)
{
}
void empty_visitor::visit(variable_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) const struct position& node::position() const noexcept
: definition(identifier), m_type(type) {
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); 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) definition::definition(const struct position position, const std::string& identifier)
: m_identifier(identifier) : node(position), m_identifier(identifier)
{ {
} }
@ -119,8 +160,9 @@ namespace elna::source
return m_identifier; return m_identifier;
} }
constant_definition::constant_definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body) constant_definition::constant_definition(const struct position position, const std::string& identifier,
: definition(identifier), m_body(std::move(body)) std::unique_ptr<integer_literal>&& body)
: definition(position, identifier), m_body(std::move(body))
{ {
} }
@ -134,8 +176,9 @@ namespace elna::source
return *m_body; return *m_body;
} }
procedure_definition::procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body) procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
: definition(identifier), m_body(std::move(body)) std::unique_ptr<block>&& body)
: definition(position, identifier), m_body(std::move(body))
{ {
} }
@ -154,10 +197,10 @@ namespace elna::source
return m_parameters; 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::vector<std::unique_ptr<declaration>>&& declarations,
std::unique_ptr<statement>&& body) 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)) m_declarations(std::move(declarations)), m_body(std::move(body))
{ {
} }
@ -182,10 +225,10 @@ namespace elna::source
return m_declarations; 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::vector<std::unique_ptr<declaration>>&& declarations,
std::unique_ptr<statement>&& body) 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); visitor->visit(this);
} }
integer_literal::integer_literal(const std::int32_t value) integer_literal::integer_literal(const struct position position, const std::int32_t value)
: m_number(value) : expression(position), m_number(value)
{ {
} }
@ -209,8 +252,8 @@ namespace elna::source
return m_number; return m_number;
} }
boolean_literal::boolean_literal(const bool value) boolean_literal::boolean_literal(const struct position position, const bool value)
: m_boolean(value) : expression(position), m_boolean(value)
{ {
} }
@ -224,8 +267,8 @@ namespace elna::source
return m_boolean; return m_boolean;
} }
variable_expression::variable_expression(const std::string& name) variable_expression::variable_expression(const struct position position, const std::string& name)
: m_name(name) : expression(position), m_name(name)
{ {
} }
@ -239,9 +282,9 @@ namespace elna::source
return m_name; 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) 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) switch (operation)
{ {
@ -300,8 +343,8 @@ namespace elna::source
return m_operator; return m_operator;
} }
call_statement::call_statement(const std::string& name) call_statement::call_statement(const struct position position, const std::string& name)
: m_name(name) : statement(position), m_name(name)
{ {
} }
@ -320,8 +363,8 @@ namespace elna::source
return m_arguments; return m_arguments;
} }
compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements) compound_statement::compound_statement(const struct position position)
: m_statements(std::move(statements)) : statement(position)
{ {
} }
@ -340,8 +383,9 @@ namespace elna::source
visitor->visit(this); visitor->visit(this);
} }
assign_statement::assign_statement(const std::string& lvalue, std::unique_ptr<expression>&& rvalue) assign_statement::assign_statement(const struct position position, const std::string& lvalue,
: m_lvalue(lvalue), m_rvalue(std::move(rvalue)) 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; return *m_rvalue;
} }
if_statement::if_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body) if_statement::if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) 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; return *m_body;
} }
while_statement::while_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body) while_statement::while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) 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); *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)); std::move(declarations), std::move(parsed_statement));
} }
@ -435,19 +481,19 @@ namespace elna::source
{ {
if (iterator->of() == source::token::type::identifier) 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; ++iterator;
return result; return result;
} }
else if (iterator->of() == source::token::token::type::number) 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; ++iterator;
return result; return result;
} }
else if (iterator->of() == source::token::token::type::boolean) 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; ++iterator;
return result; return result;
} }
@ -474,10 +520,11 @@ namespace elna::source
while (iterator->of() == source::token::type::factor_operator) while (iterator->of() == source::token::type::factor_operator)
{ {
auto _operator = iterator->identifier()[0]; auto _operator = iterator->identifier()[0];
const auto operator_position = iterator->position();
++iterator; ++iterator;
auto rhs = parse_factor(); 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); std::move(rhs), _operator);
} }
return lhs; return lhs;
@ -493,10 +540,11 @@ namespace elna::source
while (iterator->of() == source::token::type::term_operator) while (iterator->of() == source::token::type::term_operator)
{ {
auto _operator = iterator->identifier()[0]; auto _operator = iterator->identifier()[0];
const auto operator_position = iterator->position();
++iterator; ++iterator;
auto rhs = parse_term(); 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); std::move(rhs), _operator);
} }
return term; return term;
@ -524,6 +572,7 @@ namespace elna::source
{ {
return lhs; return lhs;
} }
const auto operator_position = iterator->position();
++iterator; ++iterator;
auto rhs = parse_expression(); auto rhs = parse_expression();
@ -531,12 +580,13 @@ namespace elna::source
{ {
return nullptr; 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() std::unique_ptr<constant_definition> parser::parse_constant_definition()
{ {
auto definition_identifier = iterator.advance(token::type::identifier); auto definition_identifier = iterator.advance(token::type::identifier);
const auto identifier_position = iterator->position();
if (!definition_identifier.has_value()) if (!definition_identifier.has_value())
{ {
@ -549,8 +599,9 @@ namespace elna::source
if (iterator->of() == source::token::type::number) if (iterator->of() == source::token::type::number)
{ {
auto result = std::make_unique<constant_definition>(definition_identifier.value().get().identifier(), auto result = std::make_unique<constant_definition>(identifier_position,
std::make_unique<integer_literal>(iterator->number())); definition_identifier.value().get().identifier(),
std::make_unique<integer_literal>(iterator->position(), iterator->number()));
++iterator; ++iterator;
return result; return result;
} }
@ -559,6 +610,7 @@ namespace elna::source
std::unique_ptr<procedure_definition> parser::parse_procedure_definition() std::unique_ptr<procedure_definition> parser::parse_procedure_definition()
{ {
const auto proc_position = iterator->position();
if (!iterator.skip(token::type::procedure)) if (!iterator.skip(token::type::procedure))
{ {
return nullptr; return nullptr;
@ -597,13 +649,32 @@ namespace elna::source
{ {
return nullptr; return nullptr;
} }
auto procedure = std::make_unique<procedure_definition>(definition_identifier->get().identifier(), auto procedure = std::make_unique<procedure_definition>(proc_position,
std::move(definition_body)); definition_identifier->get().identifier(), std::move(definition_body));
procedure->parameters() = std::move(declarations); procedure->parameters() = std::move(declarations);
return procedure; 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() std::unique_ptr<declaration> parser::parse_declaration()
{ {
auto declaration_identifier = iterator.advance(token::type::identifier); auto declaration_identifier = iterator.advance(token::type::identifier);
@ -612,14 +683,14 @@ namespace elna::source
{ {
return nullptr; 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 nullptr;
} }
return std::make_unique<declaration>(declaration_identifier.value().get().identifier(), return std::make_unique<declaration>(declaration_identifier.value().get().position(),
type_identifier.value().get().identifier()); declaration_identifier.value().get().identifier(), std::move(type_identifier));
} }
std::unique_ptr<statement> parser::parse_statement() std::unique_ptr<statement> parser::parse_statement()
@ -655,7 +726,8 @@ namespace elna::source
{ {
return nullptr; 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; std::unique_ptr<expression> argument_expression;
if (iterator.current(token::type::right_paren)) if (iterator.current(token::type::right_paren))
@ -682,11 +754,12 @@ namespace elna::source
std::unique_ptr<compound_statement> parser::parse_compound_statement() std::unique_ptr<compound_statement> parser::parse_compound_statement()
{ {
const auto begin_position = iterator->position();
if (!iterator.advance(token::type::begin)) if (!iterator.advance(token::type::begin))
{ {
return nullptr; return nullptr;
} }
auto result = std::make_unique<compound_statement>(); auto result = std::make_unique<compound_statement>(begin_position);
std::unique_ptr<statement> next_statement; std::unique_ptr<statement> next_statement;
while ((next_statement = parse_statement()) != nullptr) while ((next_statement = parse_statement()) != nullptr)
@ -725,11 +798,13 @@ namespace elna::source
{ {
return nullptr; 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() std::unique_ptr<if_statement> parser::parse_if_statement()
{ {
const auto if_position = iterator->position();
if (!iterator.skip(token::type::when)) if (!iterator.skip(token::type::when))
{ {
return nullptr; return nullptr;
@ -746,11 +821,12 @@ namespace elna::source
{ {
return nullptr; 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() std::unique_ptr<while_statement> parser::parse_while_statement()
{ {
const auto while_position = iterator->position();
if (!iterator.skip(token::type::loop)) if (!iterator.skip(token::type::loop))
{ {
return nullptr; return nullptr;
@ -767,7 +843,7 @@ namespace elna::source
{ {
return nullptr; 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() std::vector<std::unique_ptr<constant_definition>> parser::parse_constant_definitions()
@ -870,7 +946,7 @@ namespace elna::source
{ {
*definition++ = std::move(constant); *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)); std::move(declarations), std::move(parsed_statement));
} }
} }

View File

@ -43,21 +43,28 @@ namespace elna::source
{ {
} }
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) symbol_table::symbol_table(std::shared_ptr<symbol_table> scope)
: outer_scope(scope) : outer_scope(scope)
{ {
if (scope == nullptr) 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>(); 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); enter("writei", writei);
auto writeb = std::make_shared<intrinsic_info>(); 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("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) 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; return m_type;
} }
@ -122,7 +129,7 @@ namespace elna::source
return m_value; 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) : 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; 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) : 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; return m_type;
} }

View File

@ -159,6 +159,16 @@ False {
return static_cast<int>(elna::source::token::type::colon); 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; return -1;
} }
@ -172,10 +182,10 @@ result<lexer> tokenize(const std::filesystem::path& path)
std::vector<token> tokens; std::vector<token> tokens;
yyin = fopen(path.c_str(), "rb"); yyin = fopen(path.c_str(), "rb");
if (yyin == nullptr) if (yyin == nullptr)
{ {
throw std::ios_base::failure("File does not exist"); throw std::ios_base::failure("File does not exist");
} }
do do
{ {
yytoken = yylex(); yytoken = yylex();

View File

@ -1,4 +1,5 @@
#include "elna/source/semantic.hpp" #include "elna/source/semantic.hpp"
#include "elna/source/result.hpp"
#include <cstdlib> #include <cstdlib>
namespace elna::source namespace elna::source
@ -14,11 +15,28 @@ namespace elna::source
std::make_shared<constant_info>(constant_info(definition->body().number()))); 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) 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(), 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) void name_analysis_visitor::visit(program *program)
@ -35,9 +53,10 @@ namespace elna::source
for (auto& parameter : procedure->parameters()) 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(), this->table->enter(parameter->identifier(),
std::make_shared<parameter_info>(declaration_type->type())); std::make_shared<parameter_info>(declaration_type));
} }
procedure->body().accept(this); procedure->body().accept(this);