Add pointer and field access nodes

This commit is contained in:
Eugen Wissner 2025-01-08 23:23:27 +01:00
parent 2d61828903
commit cf4b6b7ccc
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
6 changed files with 242 additions and 44 deletions

View File

@ -49,8 +49,12 @@ namespace source
class unary_expression; class unary_expression;
class basic_type_expression; class basic_type_expression;
class array_type_expression; class array_type_expression;
class pointer_type_expression;
class record_type_expression;
class variable_expression; class variable_expression;
class array_access_expression; class array_access_expression;
class field_access_expression;
class dereference_expression;
template<typename T> template<typename T>
class number_literal; class number_literal;
class char_literal; class char_literal;
@ -76,8 +80,12 @@ namespace source
virtual void visit(unary_expression *) = 0; virtual void visit(unary_expression *) = 0;
virtual void visit(basic_type_expression *) = 0; virtual void visit(basic_type_expression *) = 0;
virtual void visit(array_type_expression *) = 0; virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(variable_expression *) = 0; virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0; virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *is_field_access) = 0;
virtual void visit(dereference_expression *is_dereference) = 0;
virtual void visit(number_literal<std::int32_t> *) = 0; virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0; virtual void visit(number_literal<double> *) = 0;
virtual void visit(number_literal<bool> *) = 0; virtual void visit(number_literal<bool> *) = 0;
@ -105,8 +113,12 @@ namespace source
virtual void visit(unary_expression *expression) override; virtual void visit(unary_expression *expression) override;
virtual void visit(basic_type_expression *) override; virtual void visit(basic_type_expression *) override;
virtual void visit(array_type_expression *expression) override; virtual void visit(array_type_expression *expression) override;
virtual void visit(pointer_type_expression *) override;
virtual void visit(record_type_expression *expression) override;
virtual void visit(variable_expression *) override; virtual void visit(variable_expression *) override;
virtual void visit(array_access_expression *expression) override; virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *is_field_access) override;
virtual void visit(dereference_expression *is_dereference) override;
virtual void visit(number_literal<std::int32_t> *) override; virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<double> *) override; virtual void visit(number_literal<double> *) override;
virtual void visit(number_literal<bool> *) override; virtual void visit(number_literal<bool> *) override;
@ -240,6 +252,8 @@ namespace source
virtual const std::string& base_name() = 0; virtual const std::string& base_name() = 0;
virtual basic_type_expression *is_basic(); virtual basic_type_expression *is_basic();
virtual array_type_expression *is_array(); virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
virtual record_type_expression *is_record();
protected: protected:
type_expression(const struct position position); type_expression(const struct position position);
@ -270,22 +284,11 @@ namespace source
type_expression *m_base; type_expression *m_base;
public: public:
/**
* Array size.
*/
const std::uint32_t size; const std::uint32_t size;
/**
* \param position Source code position.
* \param name Array base type.
* \param name Array size.
*/
array_type_expression(const struct position position, type_expression *base, const std::uint32_t size); array_type_expression(const struct position position, type_expression *base, const std::uint32_t size);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
/**
* \return Array base type.
*/
type_expression& base(); type_expression& base();
const std::string& base_name() override; const std::string& base_name() override;
@ -294,6 +297,39 @@ namespace source
virtual ~array_type_expression() override; virtual ~array_type_expression() override;
}; };
class pointer_type_expression : public type_expression
{
type_expression *m_base;
public:
pointer_type_expression(const struct position position, type_expression *base);
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
const std::string& base_name() override;
pointer_type_expression *is_pointer() override;
virtual ~pointer_type_expression() override;
};
class record_type_expression : public type_expression
{
public:
using field_t = std::pair<std::string, type_expression *>;
using fields_t = std::vector<field_t>;
record_type_expression(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
fields_t& fields();
record_type_expression *is_record() override;
private:
fields_t m_fields;
};
/** /**
* Variable declaration. * Variable declaration.
*/ */
@ -418,6 +454,8 @@ namespace source
public: public:
virtual variable_expression *is_variable(); virtual variable_expression *is_variable();
virtual array_access_expression *is_array_access(); virtual array_access_expression *is_array_access();
virtual field_access_expression *is_field_access();
virtual dereference_expression *is_dereference();
protected: protected:
designator_expression(const struct position position); designator_expression(const struct position position);
@ -453,6 +491,39 @@ namespace source
~array_access_expression() override; ~array_access_expression() override;
}; };
class field_access_expression : public designator_expression
{
designator_expression *m_base;
std::string m_field;
public:
field_access_expression(const struct position position, designator_expression *base,
const std::string& field);
virtual void accept(parser_visitor *visitor) override;
designator_expression& base();
std::string& field();
field_access_expression *is_field_access() override;
~field_access_expression() override;
};
class dereference_expression : public designator_expression
{
designator_expression *m_base;
public:
dereference_expression(const struct position position, designator_expression *base);
virtual void accept(parser_visitor *visitor) override;
designator_expression& base();
dereference_expression *is_dereference() override;
~dereference_expression() override;
};
class assign_statement : public statement class assign_statement : public statement
{ {
designator_expression *m_lvalue; designator_expression *m_lvalue;

View File

@ -51,23 +51,5 @@ namespace source
/// Error column in the source text. /// Error column in the source text.
std::size_t column() const noexcept; std::size_t column() const noexcept;
}; };
class name_collision final : public error
{
const struct position previous;
std::string name;
public:
/**
* \param name Symbol name.
* \param path Source file name.
* \param current Current symbol position.
* \param previous Position of the previously defined symbol.
*/
name_collision(const std::string& name, const char *path,
const struct position current, const struct position previous);
std::string what() const override;
};
} }
} }

View File

@ -101,6 +101,19 @@ namespace source
expression->base().accept(this); expression->base().accept(this);
} }
void empty_visitor::visit(pointer_type_expression *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(record_type_expression *expression)
{
for (auto& field : expression->fields())
{
field.second->accept(this);
}
}
void empty_visitor::visit(variable_expression *) void empty_visitor::visit(variable_expression *)
{ {
} }
@ -111,6 +124,16 @@ namespace source
expression->index().accept(this); expression->index().accept(this);
} }
void empty_visitor::visit(field_access_expression *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(dereference_expression *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(number_literal<std::int32_t> *) void empty_visitor::visit(number_literal<std::int32_t> *)
{ {
} }
@ -210,6 +233,16 @@ namespace source
return nullptr; return nullptr;
} }
record_type_expression *type_expression::is_record()
{
return nullptr;
}
pointer_type_expression *type_expression::is_pointer()
{
return nullptr;
}
basic_type_expression::basic_type_expression( basic_type_expression::basic_type_expression(
const struct position position, const std::string& name) const struct position position, const std::string& name)
: type_expression(position), m_name(name) : type_expression(position), m_name(name)
@ -262,6 +295,57 @@ namespace source
delete m_base; delete m_base;
} }
pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base)
: type_expression(position), m_base(base)
{
}
void pointer_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
type_expression& pointer_type_expression::base()
{
return *m_base;
}
const std::string& pointer_type_expression::base_name()
{
return base().base_name();
}
pointer_type_expression *pointer_type_expression::is_pointer()
{
return this;
}
pointer_type_expression::~pointer_type_expression()
{
delete m_base;
}
record_type_expression::record_type_expression(const struct position position,
record_type_expression::fields_t&& fields)
: type_expression(position), m_fields(std::move(fields))
{
}
void record_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
record_type_expression::fields_t& record_type_expression::fields()
{
return m_fields;
}
record_type_expression *record_type_expression::is_record()
{
return this;
}
declaration::declaration(const struct position position, const std::string& identifier, declaration::declaration(const struct position position, const std::string& identifier,
type_expression *type) type_expression *type)
: definition(position, identifier), m_type(type) : definition(position, identifier), m_type(type)
@ -504,6 +588,63 @@ namespace source
delete m_base; delete m_base;
} }
field_access_expression::field_access_expression(const struct position position,
designator_expression *base, const std::string& field)
: designator_expression(position), m_base(base), m_field(field)
{
}
void field_access_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
designator_expression& field_access_expression::base()
{
return *m_base;
}
std::string& field_access_expression::field()
{
return m_field;
}
field_access_expression *field_access_expression::is_field_access()
{
return this;
}
field_access_expression::~field_access_expression()
{
delete m_base;
}
dereference_expression::dereference_expression(const struct position position,
designator_expression *base)
: designator_expression(position), m_base(base)
{
}
void dereference_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
designator_expression& dereference_expression::base()
{
return *m_base;
}
dereference_expression *dereference_expression::is_dereference()
{
return this;
}
dereference_expression::~dereference_expression()
{
delete m_base;
}
binary_expression::binary_expression(const struct position position, expression *lhs, binary_expression::binary_expression(const struct position position, expression *lhs,
expression *rhs, const unsigned char operation) expression *rhs, const unsigned char operation)
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) : expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
@ -680,6 +821,16 @@ namespace source
return nullptr; return nullptr;
} }
field_access_expression *designator_expression::is_field_access()
{
return nullptr;
}
dereference_expression *designator_expression::is_dereference()
{
return nullptr;
}
designator_expression& assign_statement::lvalue() designator_expression& assign_statement::lvalue()
{ {
return *m_lvalue; return *m_lvalue;

View File

@ -70,7 +70,9 @@ of {
type { type {
return yy::parser::make_TYPE(this->location); return yy::parser::make_TYPE(this->location);
} }
record {
return yy::parser::make_RECORD(this->location);
}
true { true {
return yy::parser::make_BOOLEAN(true, this->location); return yy::parser::make_BOOLEAN(true, this->location);
} }

View File

@ -63,7 +63,7 @@
%token <std::string> STRING "string" %token <std::string> STRING "string"
%token <bool> BOOLEAN %token <bool> BOOLEAN
%token IF WHILE DO %token IF WHILE DO
%token CONST VAR PROCEDURE ARRAY OF TYPE %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD
%token BEGIN_BLOCK END_BLOCK %token BEGIN_BLOCK END_BLOCK
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
@ -315,14 +315,17 @@ type_expression:
{ {
$$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2); $$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2);
} }
| HAT type_expression
{
$$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $2);
}
| IDENTIFIER | IDENTIFIER
{ {
$$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1); $$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1);
} }
variable_declaration: IDENTIFIER COLON type_expression variable_declaration: IDENTIFIER COLON type_expression
{ {
$$ = new elna::source::declaration(elna::source::make_position(@1), $$ = new elna::source::declaration(elna::source::make_position(@1), $1, $3);
$1, $3);
}; };
variable_declarations: variable_declarations:
variable_declaration COMMA variable_declarations variable_declaration COMMA variable_declarations

View File

@ -21,16 +21,5 @@ namespace source
{ {
return this->position.column; return this->position.column;
} }
name_collision::name_collision(const std::string& name, const char *path,
const struct position current, const struct position previous)
: error(path, current), previous(previous), name(name)
{
}
std::string name_collision::what() const
{
return "Name '" + name + "' was already defined";
}
} }
} }