Parse pointer types

This commit is contained in:
2024-04-07 23:39:56 +02:00
parent 0876e25f90
commit 986bcdd0c7
11 changed files with 344 additions and 101 deletions

View File

@ -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;

View File

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

View File

@ -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();

View File

@ -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;
};
/**

View File

@ -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);