2024-12-27 10:51:46 +01:00
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
|
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
2024-12-23 13:54:11 +01:00
|
|
|
#include "elna/source/ast.h"
|
2024-12-21 00:08:48 +01:00
|
|
|
|
2024-12-23 13:54:11 +01:00
|
|
|
namespace elna
|
|
|
|
{
|
|
|
|
namespace source
|
2024-12-21 00:08:48 +01:00
|
|
|
{
|
|
|
|
void empty_visitor::visit(declaration *declaration)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(constant_definition *definition)
|
|
|
|
{
|
|
|
|
definition->body().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(procedure_definition *definition)
|
|
|
|
{
|
|
|
|
for (auto& parameter : definition->parameters())
|
|
|
|
{
|
|
|
|
parameter->accept(this);
|
|
|
|
}
|
|
|
|
definition->body().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(call_statement *statement)
|
|
|
|
{
|
|
|
|
for (auto& argument : statement->arguments())
|
|
|
|
{
|
|
|
|
argument->accept(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(compound_statement *statement)
|
|
|
|
{
|
|
|
|
for (auto& nested_statement : statement->statements())
|
|
|
|
{
|
|
|
|
nested_statement->accept(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(assign_statement *statement)
|
|
|
|
{
|
|
|
|
statement->rvalue().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(if_statement *statement)
|
|
|
|
{
|
|
|
|
statement->prerequisite().accept(this);
|
|
|
|
statement->body().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(while_statement *statement)
|
|
|
|
{
|
|
|
|
statement->prerequisite().accept(this);
|
|
|
|
statement->body().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(block *block)
|
|
|
|
{
|
|
|
|
for (const auto& constant : block->definitions())
|
|
|
|
{
|
|
|
|
constant->accept(this);
|
|
|
|
}
|
|
|
|
for (const auto& block_declaration : block->declarations())
|
|
|
|
{
|
|
|
|
block_declaration->accept(this);
|
|
|
|
}
|
|
|
|
block->body().accept(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(program *program)
|
|
|
|
{
|
2024-12-23 13:54:11 +01:00
|
|
|
visit(reinterpret_cast<block *>(program));
|
2024-12-21 00:08:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(binary_expression *expression)
|
|
|
|
{
|
|
|
|
expression->lhs().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(variable_expression *variable)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(integer_literal *number)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void empty_visitor::visit(boolean_literal *boolean)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
operand::~operand() noexcept
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
integer_operand::integer_operand(const std::int32_t value)
|
|
|
|
: m_value(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::int32_t integer_operand::value() const noexcept
|
|
|
|
{
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
variable_operand::variable_operand(const std::string& name)
|
|
|
|
: m_name(name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& variable_operand::name() const noexcept
|
|
|
|
{
|
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
temporary_variable::temporary_variable(const std::size_t counter)
|
|
|
|
: m_counter(counter)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t temporary_variable::counter() const noexcept
|
|
|
|
{
|
|
|
|
return m_counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
label_operand::label_operand(const std::size_t counter)
|
|
|
|
: m_counter(counter)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t label_operand::counter() const noexcept
|
|
|
|
{
|
|
|
|
return m_counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
node::node(const struct position position)
|
|
|
|
: source_position(position)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void declaration::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_expression& declaration::type() noexcept
|
|
|
|
{
|
|
|
|
return *m_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
definition::definition(const struct position position, const std::string& identifier)
|
|
|
|
: node(position), m_identifier(identifier)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string& definition::identifier() noexcept
|
|
|
|
{
|
|
|
|
return m_identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void constant_definition::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
integer_literal& constant_definition::body()
|
|
|
|
{
|
|
|
|
return *m_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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void procedure_definition::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
block& procedure_definition::body()
|
|
|
|
{
|
|
|
|
return *m_body;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<declaration>>& procedure_definition::parameters() noexcept
|
|
|
|
{
|
|
|
|
return m_parameters;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
: node(position), m_definitions(std::move(definitions)),
|
|
|
|
m_declarations(std::move(declarations)), m_body(std::move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void block::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
statement& block::body()
|
|
|
|
{
|
|
|
|
return *m_body;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<definition>>& block::definitions() noexcept
|
|
|
|
{
|
|
|
|
return m_definitions;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<declaration>>& block::declarations() noexcept
|
|
|
|
{
|
|
|
|
return m_declarations;
|
|
|
|
}
|
|
|
|
|
|
|
|
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(position, std::move(definitions), std::move(declarations), std::move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void program::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
integer_literal::integer_literal(const struct position position, const std::int32_t value)
|
|
|
|
: expression(position), m_number(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void integer_literal::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::int32_t integer_literal::number() const noexcept
|
|
|
|
{
|
|
|
|
return m_number;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean_literal::boolean_literal(const struct position position, const bool value)
|
|
|
|
: expression(position), m_boolean(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void boolean_literal::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool boolean_literal::boolean() const noexcept
|
|
|
|
{
|
|
|
|
return m_boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
variable_expression::variable_expression(const struct position position, const std::string& name)
|
|
|
|
: expression(position), m_name(name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void variable_expression::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& variable_expression::name() const noexcept
|
|
|
|
{
|
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
binary_expression::binary_expression(const struct position position, std::unique_ptr<expression>&& lhs,
|
|
|
|
std::unique_ptr<expression>&& rhs, const unsigned char operation)
|
|
|
|
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
|
|
|
|
{
|
|
|
|
switch (operation)
|
|
|
|
{
|
|
|
|
case '+':
|
|
|
|
this->m_operator = binary_operator::sum;
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
this->m_operator = binary_operator::subtraction;
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
this->m_operator = binary_operator::multiplication;
|
|
|
|
break;
|
|
|
|
case '/':
|
|
|
|
this->m_operator = binary_operator::division;
|
|
|
|
break;
|
|
|
|
case '=':
|
|
|
|
this->m_operator = binary_operator::equals;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
this->m_operator = binary_operator::not_equals;
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
this->m_operator = binary_operator::less;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
this->m_operator = binary_operator::less_equal;
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
this->m_operator = binary_operator::greater;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
this->m_operator = binary_operator::greater_equal;
|
|
|
|
break;
|
|
|
|
default:
|
2024-12-23 13:54:11 +01:00
|
|
|
__builtin_unreachable();
|
2024-12-21 00:08:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void binary_expression::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& binary_expression::lhs()
|
|
|
|
{
|
|
|
|
return *m_lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& binary_expression::rhs()
|
|
|
|
{
|
|
|
|
return *m_rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
binary_operator binary_expression::operation() const noexcept
|
|
|
|
{
|
|
|
|
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:
|
2024-12-23 13:54:11 +01:00
|
|
|
__builtin_unreachable();
|
2024-12-21 00:08:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void unary_expression::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& unary_expression::operand()
|
|
|
|
{
|
|
|
|
return *m_operand;
|
|
|
|
}
|
|
|
|
|
|
|
|
unary_operator unary_expression::operation() const noexcept
|
|
|
|
{
|
|
|
|
return this->m_operator;
|
|
|
|
}
|
|
|
|
|
|
|
|
call_statement::call_statement(const struct position position, const std::string& name)
|
|
|
|
: statement(position), m_name(name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void call_statement::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string& call_statement::name() noexcept
|
|
|
|
{
|
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<expression>>& call_statement::arguments() noexcept
|
|
|
|
{
|
|
|
|
return m_arguments;
|
|
|
|
}
|
|
|
|
|
|
|
|
compound_statement::compound_statement(const struct position position)
|
|
|
|
: statement(position)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void compound_statement::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<statement>>& compound_statement::statements()
|
|
|
|
{
|
|
|
|
return m_statements;
|
|
|
|
}
|
|
|
|
|
|
|
|
void assign_statement::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string& assign_statement::lvalue() noexcept
|
|
|
|
{
|
|
|
|
return m_lvalue;
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& assign_statement::rvalue()
|
|
|
|
{
|
|
|
|
return *m_rvalue;
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void if_statement::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& if_statement::prerequisite()
|
|
|
|
{
|
|
|
|
return *m_prerequisite;
|
|
|
|
}
|
|
|
|
|
|
|
|
statement& if_statement::body()
|
|
|
|
{
|
|
|
|
return *m_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))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void while_statement::accept(parser_visitor *visitor)
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
expression& while_statement::prerequisite()
|
|
|
|
{
|
|
|
|
return *m_prerequisite;
|
|
|
|
}
|
|
|
|
|
|
|
|
statement& while_statement::body()
|
|
|
|
{
|
|
|
|
return *m_body;
|
|
|
|
}
|
2024-12-28 14:33:35 +01:00
|
|
|
|
|
|
|
const char *print_binary_operator(const binary_operator operation)
|
|
|
|
{
|
|
|
|
switch (operation)
|
|
|
|
{
|
|
|
|
case binary_operator::sum:
|
|
|
|
return "+";
|
|
|
|
case binary_operator::subtraction:
|
|
|
|
return "-";
|
|
|
|
case binary_operator::multiplication:
|
|
|
|
return "*";
|
|
|
|
case binary_operator::division:
|
|
|
|
return "/";
|
|
|
|
case binary_operator::equals:
|
|
|
|
return "=";
|
|
|
|
case binary_operator::not_equals:
|
|
|
|
return "/=";
|
|
|
|
case binary_operator::less:
|
|
|
|
return "<";
|
|
|
|
case binary_operator::less_equal:
|
|
|
|
return "<=";
|
|
|
|
case binary_operator::greater:
|
|
|
|
return ">";
|
|
|
|
case binary_operator::greater_equal:
|
|
|
|
return ">=";
|
|
|
|
}
|
|
|
|
};
|
2024-12-21 00:08:48 +01:00
|
|
|
}
|
2024-12-23 13:54:11 +01:00
|
|
|
}
|