Rename elna::source to elna:boot
This commit is contained in:
982
source/ast.cc
982
source/ast.cc
@ -1,982 +0,0 @@
|
||||
// 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/.
|
||||
#include "elna/source/ast.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
void empty_visitor::visit(variable_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);
|
||||
}
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
definition->body()->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(type_definition *definition)
|
||||
{
|
||||
definition->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(call_expression *expression)
|
||||
{
|
||||
for (auto& argument : expression->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(cast_expression *expression)
|
||||
{
|
||||
expression->target().accept(this);
|
||||
expression->value().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(size_of_expression *expression)
|
||||
{
|
||||
expression->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(expression_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(assign_statement *statement)
|
||||
{
|
||||
statement->rvalue().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(if_statement *statement)
|
||||
{
|
||||
statement->body().prerequisite().accept(this);
|
||||
for (const auto body_statement : statement->body().statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(while_statement *statement)
|
||||
{
|
||||
statement->body().prerequisite().accept(this);
|
||||
for (const auto body_statement : statement->body().statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(return_statement *statement)
|
||||
{
|
||||
expression *return_expression = statement->return_expression();
|
||||
|
||||
if (return_expression != nullptr)
|
||||
{
|
||||
return_expression->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(block *block)
|
||||
{
|
||||
for (const auto definition : block->value_definitions)
|
||||
{
|
||||
definition->accept(this);
|
||||
}
|
||||
for (const auto body_statement : block->body)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(program *program)
|
||||
{
|
||||
for (auto definition : program->type_definitions)
|
||||
{
|
||||
definition->accept(this);
|
||||
}
|
||||
visit(reinterpret_cast<block *>(program));
|
||||
}
|
||||
|
||||
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(basic_type_expression *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(array_type_expression *expression)
|
||||
{
|
||||
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(union_type_expression *expression)
|
||||
{
|
||||
for (auto& field : expression->fields)
|
||||
{
|
||||
field.second->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(variable_expression *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(array_access_expression *expression)
|
||||
{
|
||||
expression->base().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::uint32_t> *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(number_literal<double> *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(number_literal<bool> *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(number_literal<unsigned char> *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(number_literal<std::nullptr_t> *)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(string_literal *)
|
||||
{
|
||||
}
|
||||
|
||||
node::node(const struct position position)
|
||||
: source_position(position)
|
||||
{
|
||||
}
|
||||
|
||||
const struct position& node::position() const
|
||||
{
|
||||
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)
|
||||
: node(position)
|
||||
{
|
||||
}
|
||||
|
||||
basic_type_expression *type_expression::is_basic()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
array_type_expression *type_expression::is_array()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
record_type_expression *type_expression::is_record()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
union_type_expression *type_expression::is_union()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pointer_type_expression *type_expression::is_pointer()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
basic_type_expression::basic_type_expression(
|
||||
const struct position position, const std::string& name)
|
||||
: type_expression(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void basic_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& basic_type_expression::base_name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
basic_type_expression *basic_type_expression::is_basic()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
array_type_expression::array_type_expression(const struct position position, type_expression *base,
|
||||
const std::uint32_t size)
|
||||
: type_expression(position), m_base(base), size(size)
|
||||
{
|
||||
}
|
||||
|
||||
void array_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& array_type_expression::base()
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
array_type_expression *array_type_expression::is_array()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
array_type_expression::~array_type_expression()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
pointer_type_expression *pointer_type_expression::is_pointer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
pointer_type_expression::~pointer_type_expression()
|
||||
{
|
||||
delete m_base;
|
||||
}
|
||||
|
||||
composite_type_expression::composite_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: type_expression(position), fields(std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
composite_type_expression::~composite_type_expression()
|
||||
{
|
||||
for (auto& field_declaration : fields)
|
||||
{
|
||||
delete field_declaration.second;
|
||||
}
|
||||
}
|
||||
|
||||
record_type_expression::record_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: composite_type_expression(position, std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
void record_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
record_type_expression *record_type_expression::is_record()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
union_type_expression::union_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: composite_type_expression(position, std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
union_type_expression *union_type_expression::is_union()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void union_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
||||
type_expression *type)
|
||||
: definition(position, identifier), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
variable_declaration::~variable_declaration()
|
||||
{
|
||||
delete m_type;
|
||||
}
|
||||
|
||||
void variable_declaration::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& variable_declaration::type()
|
||||
{
|
||||
return *m_type;
|
||||
}
|
||||
|
||||
definition::definition(const struct position position, const std::string& identifier)
|
||||
: node(position), m_identifier(identifier)
|
||||
{
|
||||
}
|
||||
|
||||
std::string& definition::identifier()
|
||||
{
|
||||
return m_identifier;
|
||||
}
|
||||
|
||||
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
||||
literal *body)
|
||||
: definition(position, identifier), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
void constant_definition::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
literal& constant_definition::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
constant_definition::~constant_definition()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
|
||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||
std::vector<variable_declaration *>&& parameters, type_expression *return_type, block *body)
|
||||
: definition(position, identifier), m_return_type(return_type), m_body(body), parameters(std::move(parameters))
|
||||
{
|
||||
}
|
||||
|
||||
void procedure_definition::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
block *procedure_definition::body()
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
type_expression *procedure_definition::return_type()
|
||||
{
|
||||
return m_return_type;
|
||||
}
|
||||
|
||||
procedure_definition::~procedure_definition()
|
||||
{
|
||||
if (m_body != nullptr)
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
for (auto parameter : parameters)
|
||||
{
|
||||
delete parameter;
|
||||
}
|
||||
}
|
||||
|
||||
type_definition::type_definition(const struct position position, const std::string& identifier,
|
||||
type_expression *body)
|
||||
: definition(position, identifier), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
void type_definition::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& type_definition::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
type_definition::~type_definition()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
|
||||
block::block(const struct position position, std::vector<definition *>&& value_definitions,
|
||||
std::vector<statement *>&& body)
|
||||
: node(position), value_definitions(std::move(value_definitions)), body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void block::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
block::~block()
|
||||
{
|
||||
for (auto definition : this->value_definitions)
|
||||
{
|
||||
delete definition;
|
||||
}
|
||||
for (auto body_statement : this->body)
|
||||
{
|
||||
delete body_statement;
|
||||
}
|
||||
}
|
||||
|
||||
program::program(const struct position position,
|
||||
std::vector<definition *>&& type_definitions,
|
||||
std::vector<definition *>&& value_definitions, std::vector<statement *>&& body)
|
||||
: block(position, std::move(value_definitions), std::move(body)),
|
||||
type_definitions(std::move(type_definitions))
|
||||
{
|
||||
}
|
||||
|
||||
void program::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
program::~program()
|
||||
{
|
||||
for (auto definition : type_definitions)
|
||||
{
|
||||
delete definition;
|
||||
}
|
||||
}
|
||||
|
||||
literal::literal(const struct position position)
|
||||
: expression(position)
|
||||
{
|
||||
}
|
||||
|
||||
string_literal::string_literal(const struct position position, const std::string& value)
|
||||
: literal(position), m_string(value)
|
||||
{
|
||||
}
|
||||
|
||||
void string_literal::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& string_literal::string() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
designator_expression::designator_expression(const struct position position)
|
||||
: expression(position)
|
||||
{
|
||||
}
|
||||
|
||||
variable_expression::variable_expression(const struct position position, const std::string& name)
|
||||
: designator_expression(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void variable_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& variable_expression::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
variable_expression *variable_expression::is_variable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
array_access_expression::array_access_expression(const struct position position,
|
||||
designator_expression *base, expression *index)
|
||||
: designator_expression(position), m_base(base), m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
void array_access_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& array_access_expression::index()
|
||||
{
|
||||
return *m_index;
|
||||
}
|
||||
|
||||
designator_expression& array_access_expression::base()
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
array_access_expression *array_access_expression::is_array_access()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
array_access_expression::~array_access_expression()
|
||||
{
|
||||
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,
|
||||
expression *rhs, const binary_operator operation)
|
||||
: expression(position), m_lhs(lhs), m_rhs(rhs), m_operator(operation)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return m_operator;
|
||||
}
|
||||
|
||||
binary_expression::~binary_expression()
|
||||
{
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
unary_expression::unary_expression(const struct position position, expression *operand,
|
||||
const unary_operator operation)
|
||||
: expression(position), m_operand(std::move(operand)), m_operator(operation)
|
||||
{
|
||||
}
|
||||
|
||||
void unary_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& unary_expression::operand()
|
||||
{
|
||||
return *m_operand;
|
||||
}
|
||||
|
||||
unary_operator unary_expression::operation() const
|
||||
{
|
||||
return this->m_operator;
|
||||
}
|
||||
|
||||
unary_expression::~unary_expression()
|
||||
{
|
||||
delete m_operand;
|
||||
}
|
||||
|
||||
call_expression::call_expression(const struct position position, const std::string& name)
|
||||
: expression(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void call_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
std::string& call_expression::name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::vector<expression *>& call_expression::arguments()
|
||||
{
|
||||
return m_arguments;
|
||||
}
|
||||
|
||||
call_expression::~call_expression()
|
||||
{
|
||||
for (auto argument : m_arguments)
|
||||
{
|
||||
delete argument;
|
||||
}
|
||||
}
|
||||
|
||||
cast_expression::cast_expression(const struct position position, type_expression *target, expression *value)
|
||||
: expression(position), m_target(target), m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
void cast_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& cast_expression::target()
|
||||
{
|
||||
return *m_target;
|
||||
}
|
||||
|
||||
expression& cast_expression::value()
|
||||
{
|
||||
return *m_value;
|
||||
}
|
||||
|
||||
cast_expression::~cast_expression()
|
||||
{
|
||||
delete m_target;
|
||||
delete m_value;
|
||||
}
|
||||
|
||||
size_of_expression::size_of_expression(const struct position position, type_expression *body)
|
||||
: expression(position), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
void size_of_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& size_of_expression::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
size_of_expression::~size_of_expression()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
|
||||
expression_statement::expression_statement(const struct position position, expression *body)
|
||||
: statement(position), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
void expression_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& expression_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
expression_statement::~expression_statement()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
|
||||
conditional_statements::conditional_statements(expression *prerequisite)
|
||||
: m_prerequisite(prerequisite)
|
||||
{
|
||||
}
|
||||
|
||||
expression& conditional_statements::prerequisite()
|
||||
{
|
||||
return *m_prerequisite;
|
||||
}
|
||||
|
||||
conditional_statements::~conditional_statements()
|
||||
{
|
||||
delete m_prerequisite;
|
||||
for (auto statement : statements)
|
||||
{
|
||||
delete statement;
|
||||
}
|
||||
}
|
||||
|
||||
return_statement::return_statement(const struct position position, expression *return_expression)
|
||||
: statement(position), m_return_expression(return_expression)
|
||||
{
|
||||
}
|
||||
|
||||
void return_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression *return_statement::return_expression()
|
||||
{
|
||||
return m_return_expression;
|
||||
}
|
||||
|
||||
return_statement::~return_statement()
|
||||
{
|
||||
if (m_return_expression != nullptr)
|
||||
{
|
||||
delete m_return_expression;
|
||||
}
|
||||
}
|
||||
|
||||
void assign_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
|
||||
expression *rvalue)
|
||||
: statement(position), m_lvalue(lvalue), m_rvalue(rvalue)
|
||||
{
|
||||
}
|
||||
|
||||
variable_expression *designator_expression::is_variable()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
array_access_expression *designator_expression::is_array_access()
|
||||
{
|
||||
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()
|
||||
{
|
||||
return *m_lvalue;
|
||||
}
|
||||
|
||||
expression& assign_statement::rvalue()
|
||||
{
|
||||
return *m_rvalue;
|
||||
}
|
||||
|
||||
assign_statement::~assign_statement()
|
||||
{
|
||||
delete m_rvalue;
|
||||
}
|
||||
|
||||
if_statement::if_statement(const struct position position, conditional_statements *body,
|
||||
std::vector<statement *> *alternative)
|
||||
: statement(position), m_body(body), m_alternative(alternative)
|
||||
{
|
||||
}
|
||||
|
||||
void if_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
conditional_statements& if_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
std::vector<statement *> *if_statement::alternative()
|
||||
{
|
||||
return m_alternative;
|
||||
}
|
||||
|
||||
if_statement::~if_statement()
|
||||
{
|
||||
delete m_body;
|
||||
for (const auto branch : branches)
|
||||
{
|
||||
delete branch;
|
||||
}
|
||||
if (m_alternative != nullptr)
|
||||
{
|
||||
delete m_alternative;
|
||||
}
|
||||
}
|
||||
|
||||
while_statement::while_statement(const struct position position, conditional_statements *body)
|
||||
: statement(position), m_body(body)
|
||||
{
|
||||
}
|
||||
|
||||
void while_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
conditional_statements& while_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
while_statement::~while_statement()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
|
||||
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::remainder:
|
||||
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 ">=";
|
||||
case binary_operator::conjunction:
|
||||
return "and";
|
||||
case binary_operator::disjunction:
|
||||
return "or";
|
||||
}
|
||||
__builtin_unreachable();
|
||||
};
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// 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/.
|
||||
#include "elna/source/driver.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
position make_position(const yy::location& location)
|
||||
{
|
||||
return position{
|
||||
static_cast<std::size_t>(location.begin.line),
|
||||
static_cast<std::size_t>(location.begin.column)
|
||||
};
|
||||
}
|
||||
|
||||
syntax_error::syntax_error(const std::string& message,
|
||||
const char *input_file, const yy::location& location)
|
||||
: error(input_file, make_position(location)), message(message)
|
||||
{
|
||||
}
|
||||
|
||||
std::string syntax_error::what() const
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
driver::driver(const char *input_file)
|
||||
: input_file(input_file)
|
||||
{
|
||||
}
|
||||
|
||||
void driver::error(const yy::location& loc, const std::string& message)
|
||||
{
|
||||
m_errors.emplace_back(std::make_unique<elna::source::syntax_error>(message, input_file, loc));
|
||||
}
|
||||
|
||||
const std::list<std::unique_ptr<struct error>>& driver::errors() const noexcept
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
std::optional<char> escape_char(char escape)
|
||||
{
|
||||
switch (escape)
|
||||
{
|
||||
case 'n':
|
||||
return std::make_optional<char>('\n');
|
||||
case 'a':
|
||||
return std::make_optional<char>('\a');
|
||||
case 'b':
|
||||
return std::make_optional<char>('\b');
|
||||
case 't':
|
||||
return std::make_optional<char>('\t');
|
||||
case 'f':
|
||||
return std::make_optional<char>('\f');
|
||||
case 'r':
|
||||
return std::make_optional<char>('\r');
|
||||
case 'v':
|
||||
return std::make_optional<char>('\v');
|
||||
case '\\':
|
||||
return std::make_optional<char>('\\');
|
||||
case '\'':
|
||||
return std::make_optional<char>('\'');
|
||||
case '"':
|
||||
return std::make_optional<char>('"');
|
||||
case '?':
|
||||
return std::make_optional<char>('\?');
|
||||
case '0':
|
||||
return std::make_optional<char>('\0');
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
285
source/lexer.ll
285
source/lexer.ll
@ -1,285 +0,0 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
%{
|
||||
#define YY_NO_UNISTD_H
|
||||
#define YY_USER_ACTION this->location.columns(yyleng);
|
||||
|
||||
#include <sstream>
|
||||
#include "parser.hh"
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL yy::parser::symbol_type elna::source::lexer::lex(elna::source::driver& driver)
|
||||
#define yyterminate() return yy::parser::make_YYEOF(this->location)
|
||||
%}
|
||||
|
||||
%option c++ noyywrap never-interactive
|
||||
%option yyclass="elna::source::lexer"
|
||||
|
||||
%x IN_COMMENT
|
||||
|
||||
%%
|
||||
%{
|
||||
this->location.step();
|
||||
%}
|
||||
|
||||
<IN_COMMENT>{
|
||||
\*\) BEGIN(INITIAL);
|
||||
[^*\n]+ ; /* Eat comment in chunks. */
|
||||
\* ; /* Eat the lone star. */
|
||||
\n+ {
|
||||
this->location.lines(yyleng);
|
||||
this->location.step();
|
||||
}
|
||||
}
|
||||
\(\* BEGIN(IN_COMMENT);
|
||||
[\ \t\r] ; /* Skip the whitespaces. */
|
||||
\n+ {
|
||||
this->location.lines(yyleng);
|
||||
this->location.step();
|
||||
}
|
||||
if {
|
||||
return yy::parser::make_IF(this->location);
|
||||
}
|
||||
then {
|
||||
return yy::parser::make_THEN(this->location);
|
||||
}
|
||||
else {
|
||||
return yy::parser::make_ELSE(this->location);
|
||||
}
|
||||
elsif {
|
||||
return yy::parser::make_ELSIF(this->location);
|
||||
}
|
||||
while {
|
||||
return yy::parser::make_WHILE(this->location);
|
||||
}
|
||||
do {
|
||||
return yy::parser::make_DO(this->location);
|
||||
}
|
||||
proc {
|
||||
return yy::parser::make_PROCEDURE(this->location);
|
||||
}
|
||||
begin {
|
||||
return yy::parser::make_BEGIN_BLOCK(this->location);
|
||||
}
|
||||
end {
|
||||
return yy::parser::make_END_BLOCK(this->location);
|
||||
}
|
||||
extern {
|
||||
return yy::parser::make_EXTERN(this->location);
|
||||
}
|
||||
const {
|
||||
return yy::parser::make_CONST(this->location);
|
||||
}
|
||||
var {
|
||||
return yy::parser::make_VAR(this->location);
|
||||
}
|
||||
array {
|
||||
return yy::parser::make_ARRAY(this->location);
|
||||
}
|
||||
of {
|
||||
return yy::parser::make_OF(this->location);
|
||||
}
|
||||
type {
|
||||
return yy::parser::make_TYPE(this->location);
|
||||
}
|
||||
record {
|
||||
return yy::parser::make_RECORD(this->location);
|
||||
}
|
||||
union {
|
||||
return yy::parser::make_UNION(this->location);
|
||||
}
|
||||
pointer {
|
||||
return yy::parser::make_POINTER(this->location);
|
||||
}
|
||||
to {
|
||||
return yy::parser::make_TO(this->location);
|
||||
}
|
||||
true {
|
||||
return yy::parser::make_BOOLEAN(true, this->location);
|
||||
}
|
||||
false {
|
||||
return yy::parser::make_BOOLEAN(false, this->location);
|
||||
}
|
||||
nil {
|
||||
return yy::parser::make_NIL(this->location);
|
||||
}
|
||||
and {
|
||||
return yy::parser::make_AND(this->location);
|
||||
}
|
||||
or {
|
||||
return yy::parser::make_OR(this->location);
|
||||
}
|
||||
not {
|
||||
return yy::parser::make_NOT(this->location);
|
||||
}
|
||||
return {
|
||||
return yy::parser::make_RETURN(this->location);
|
||||
}
|
||||
cast {
|
||||
return yy::parser::make_CAST(this->location);
|
||||
}
|
||||
as {
|
||||
return yy::parser::make_AS(this->location);
|
||||
}
|
||||
sizeof {
|
||||
return yy::parser::make_SIZEOF(this->location);
|
||||
}
|
||||
[A-Za-z_][A-Za-z0-9_]* {
|
||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||
}
|
||||
[0-9]+u {
|
||||
return yy::parser::make_WORD(strtoul(yytext, NULL, 10), this->location);
|
||||
}
|
||||
[0-9]+ {
|
||||
return yy::parser::make_INTEGER(strtol(yytext, NULL, 10), this->location);
|
||||
}
|
||||
[0-9]+\.[0-9] {
|
||||
return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location);
|
||||
}
|
||||
'[[:print:]]' {
|
||||
if (yytext[1] == '\\' || yytext[1] == '\'')
|
||||
{
|
||||
REJECT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return yy::parser::make_CHARACTER(std::string(yytext, 1, 1), this->location);
|
||||
}
|
||||
}
|
||||
'\\x[0-9a-fA-F]{1,2}' {
|
||||
char character = static_cast<char>(std::stoi(yytext + 3, nullptr, 16));
|
||||
|
||||
return yy::parser::make_CHARACTER(std::string(&character, 1), this->location);
|
||||
}
|
||||
'\\[0nabtfrv\\'"?]' {
|
||||
std::optional<char> escape = source::escape_char(yytext[2]);
|
||||
if (escape.has_value())
|
||||
{
|
||||
return yy::parser::make_CHARACTER(std::string(&escape.value(), 1), this->location);
|
||||
}
|
||||
else
|
||||
{
|
||||
REJECT;
|
||||
}
|
||||
}
|
||||
\"[[:print:]]*\" {
|
||||
std::string result;
|
||||
const char *current_position = yytext + 1;
|
||||
|
||||
while (*current_position != '\0')
|
||||
{
|
||||
if (*current_position == '\\' && *(current_position + 1) == 'x')
|
||||
{
|
||||
current_position += 2;
|
||||
|
||||
std::size_t processed;
|
||||
char character = static_cast<char>(std::stoi(current_position, &processed, 16));
|
||||
if (processed == 0)
|
||||
{
|
||||
REJECT;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_position += processed - 1;
|
||||
result.push_back(character);
|
||||
}
|
||||
}
|
||||
else if (*current_position == '\\')
|
||||
{
|
||||
++current_position;
|
||||
|
||||
std::optional<char> escape = source::escape_char(*current_position);
|
||||
if (escape.has_value())
|
||||
{
|
||||
result.push_back(escape.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
REJECT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(*current_position);
|
||||
}
|
||||
++current_position;
|
||||
}
|
||||
result.pop_back();
|
||||
return yy::parser::make_STRING(result, this->location);
|
||||
}
|
||||
\( {
|
||||
return yy::parser::make_LEFT_PAREN(this->location);
|
||||
}
|
||||
\) {
|
||||
return yy::parser::make_RIGHT_PAREN(this->location);
|
||||
}
|
||||
\[ {
|
||||
return yy::parser::make_LEFT_SQUARE(this->location);
|
||||
}
|
||||
\] {
|
||||
return yy::parser::make_RIGHT_SQUARE(this->location);
|
||||
}
|
||||
\>= {
|
||||
return yy::parser::make_GREATER_EQUAL(this->location);
|
||||
}
|
||||
\<= {
|
||||
return yy::parser::make_LESS_EQUAL(this->location);
|
||||
}
|
||||
\> {
|
||||
return yy::parser::make_GREATER_THAN(this->location);
|
||||
}
|
||||
\< {
|
||||
return yy::parser::make_LESS_THAN(this->location);
|
||||
}
|
||||
\<\> {
|
||||
return yy::parser::make_NOT_EQUAL(this->location);
|
||||
}
|
||||
= {
|
||||
return yy::parser::make_EQUALS(this->location);
|
||||
}
|
||||
; {
|
||||
return yy::parser::make_SEMICOLON(this->location);
|
||||
}
|
||||
\. {
|
||||
return yy::parser::make_DOT(this->location);
|
||||
}
|
||||
, {
|
||||
return yy::parser::make_COMMA(this->location);
|
||||
}
|
||||
\+ {
|
||||
return yy::parser::make_PLUS(this->location);
|
||||
}
|
||||
\- {
|
||||
return yy::parser::make_MINUS(this->location);
|
||||
}
|
||||
\* {
|
||||
return yy::parser::make_MULTIPLICATION(this->location);
|
||||
}
|
||||
\/ {
|
||||
return yy::parser::make_DIVISION(this->location);
|
||||
}
|
||||
% {
|
||||
return yy::parser::make_REMAINDER(this->location);
|
||||
}
|
||||
:= {
|
||||
return yy::parser::make_ASSIGNMENT(this->location);
|
||||
}
|
||||
: {
|
||||
return yy::parser::make_COLON(this->location);
|
||||
}
|
||||
\^ {
|
||||
return yy::parser::make_HAT(this->location);
|
||||
}
|
||||
@ {
|
||||
return yy::parser::make_AT(this->location);
|
||||
}
|
||||
. {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
|
||||
driver.error(this->location, ss.str());
|
||||
}
|
||||
%%
|
474
source/parser.yy
474
source/parser.yy
@ -1,474 +0,0 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
%require "3.2"
|
||||
%language "c++"
|
||||
|
||||
%code requires {
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "elna/source/driver.h"
|
||||
|
||||
#if !defined(yyFlexLexerOnce)
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
class lexer;
|
||||
}
|
||||
}
|
||||
|
||||
%code provides {
|
||||
namespace elna::source
|
||||
{
|
||||
|
||||
class lexer: public yyFlexLexer
|
||||
{
|
||||
public:
|
||||
yy::location location;
|
||||
|
||||
lexer(std::istream& arg_yyin)
|
||||
: yyFlexLexer(&arg_yyin)
|
||||
{
|
||||
}
|
||||
|
||||
yy::parser::symbol_type lex(elna::source::driver& driver);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
%define api.token.raw
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
|
||||
%parse-param {elna::source::lexer& lexer}
|
||||
%param {elna::source::driver& driver}
|
||||
%locations
|
||||
|
||||
%header
|
||||
|
||||
%code {
|
||||
#define yylex lexer.lex
|
||||
}
|
||||
%start program;
|
||||
|
||||
%token <std::string> IDENTIFIER "identifier"
|
||||
%token <std::int32_t> INTEGER "integer"
|
||||
%token <std::uint32_t> WORD "word"
|
||||
%token <float> FLOAT "float"
|
||||
%token <std::string> CHARACTER "character"
|
||||
%token <std::string> STRING "string"
|
||||
%token <bool> BOOLEAN
|
||||
%token IF WHILE DO THEN ELSE ELSIF RETURN
|
||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
||||
%token BEGIN_BLOCK END_BLOCK EXTERN
|
||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||
%token AND OR NOT CAST AS SIZEOF
|
||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
||||
%token ASSIGNMENT COLON HAT AT NIL
|
||||
|
||||
%type <elna::source::literal *> literal;
|
||||
%type <elna::source::constant_definition *> constant_definition;
|
||||
%type <std::vector<elna::source::constant_definition *>> constant_part constant_definitions;
|
||||
%type <elna::source::variable_declaration *> variable_declaration;
|
||||
%type <std::vector<elna::source::variable_declaration *>> variable_declarations variable_part
|
||||
formal_parameter_list;
|
||||
%type <elna::source::type_expression *> type_expression;
|
||||
%type <elna::source::expression *> expression pointer summand factor comparand logical_operand;
|
||||
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
|
||||
%type <elna::source::designator_expression *> designator_expression;
|
||||
%type <elna::source::assign_statement *> assign_statement;
|
||||
%type <elna::source::call_expression *> call_expression;
|
||||
%type <elna::source::while_statement *> while_statement;
|
||||
%type <elna::source::if_statement *> if_statement;
|
||||
%type <elna::source::return_statement *> return_statement;
|
||||
%type <elna::source::statement *> statement;
|
||||
%type <std::vector<elna::source::statement *>> statements optional_statements;
|
||||
%type <elna::source::procedure_definition *> procedure_definition;
|
||||
%type <std::vector<elna::source::procedure_definition *>> procedure_definitions procedure_part;
|
||||
%type <elna::source::type_definition *> type_definition;
|
||||
%type <std::vector<elna::source::type_definition *>> type_definitions type_part;
|
||||
%type <elna::source::block *> block;
|
||||
%type <std::pair<std::string, elna::source::type_expression *>> field_declaration;
|
||||
%type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
|
||||
%type <std::vector<elna::source::conditional_statements *>> elsif_statement_list;
|
||||
%type <elna::source::cast_expression *> cast_expression;
|
||||
%%
|
||||
program:
|
||||
type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||
{
|
||||
std::vector<elna::source::definition *> definitions($1.size() + $3.size());
|
||||
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
||||
std::vector<elna::source::definition *> value_definitions($2.size() + $4.size());
|
||||
std::vector<elna::source::definition *>::iterator value_definition = value_definitions.begin();
|
||||
|
||||
for (auto type : $1)
|
||||
{
|
||||
*definition++ = type;
|
||||
}
|
||||
for (auto constant : $2)
|
||||
{
|
||||
*value_definition++ = constant;
|
||||
}
|
||||
for (auto procedure : $3)
|
||||
{
|
||||
*definition++ = procedure;
|
||||
}
|
||||
for (auto variable : $4)
|
||||
{
|
||||
*value_definition++ = variable;
|
||||
}
|
||||
auto tree = new elna::source::program(elna::source::make_position(@5),
|
||||
std::move(definitions), std::move(value_definitions), std::move($6));
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
|
||||
{
|
||||
std::vector<elna::source::definition *> definitions($1.size() + $2.size());
|
||||
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
||||
|
||||
for (auto constant : $1)
|
||||
{
|
||||
*definition++ = constant;
|
||||
}
|
||||
for (auto variable : $2)
|
||||
{
|
||||
*definition++ = variable;
|
||||
}
|
||||
$$ = new elna::source::block(elna::source::make_position(@3),
|
||||
std::move(definitions), std::move($4));
|
||||
}
|
||||
procedure_definition:
|
||||
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::make_position(@1),
|
||||
$2, std::move($3), nullptr, $5);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::make_position(@1),
|
||||
$2, std::move($3), nullptr, nullptr);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON block SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::make_position(@1),
|
||||
$2, std::move($3), $5, $7);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON EXTERN SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::make_position(@1),
|
||||
$2, std::move($3), $5, nullptr);
|
||||
}
|
||||
procedure_definitions:
|
||||
procedure_definition procedure_definitions
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| procedure_definition { $$.emplace_back(std::move($1)); }
|
||||
procedure_part:
|
||||
/* no procedure definitions */ {}
|
||||
| procedure_definitions { std::swap($$, $1); }
|
||||
assign_statement: designator_expression ASSIGNMENT expression
|
||||
{
|
||||
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
|
||||
}
|
||||
call_expression: IDENTIFIER actual_parameter_list
|
||||
{
|
||||
$$ = new elna::source::call_expression(elna::source::make_position(@1), $1);
|
||||
std::swap($$->arguments(), $2);
|
||||
}
|
||||
cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN
|
||||
{
|
||||
$$ = new elna::source::cast_expression(elna::source::make_position(@1), $5, $3);
|
||||
}
|
||||
while_statement: WHILE expression DO optional_statements END_BLOCK
|
||||
{
|
||||
auto body = new elna::source::conditional_statements($2);
|
||||
std::swap($4, body->statements);
|
||||
$$ = new elna::source::while_statement(elna::source::make_position(@1), body);
|
||||
}
|
||||
elsif_statement_list:
|
||||
ELSIF expression THEN optional_statements elsif_statement_list
|
||||
{
|
||||
elna::source::conditional_statements *branch = new elna::source::conditional_statements($2);
|
||||
std::swap(branch->statements, $4);
|
||||
std::swap($5, $$);
|
||||
$$.emplace($$.begin(), branch);
|
||||
}
|
||||
| {}
|
||||
if_statement:
|
||||
IF expression THEN optional_statements elsif_statement_list END_BLOCK
|
||||
{
|
||||
auto then = new elna::source::conditional_statements($2);
|
||||
std::swap($4, then->statements);
|
||||
$$ = new elna::source::if_statement(elna::source::make_position(@1), then);
|
||||
std::swap($5, $$->branches);
|
||||
}
|
||||
| IF expression THEN optional_statements elsif_statement_list ELSE optional_statements END_BLOCK
|
||||
{
|
||||
auto then = new elna::source::conditional_statements($2);
|
||||
std::swap($4, then->statements);
|
||||
auto _else = new std::vector<elna::source::statement *>(std::move($7));
|
||||
$$ = new elna::source::if_statement(elna::source::make_position(@1), then, _else);
|
||||
std::swap($5, $$->branches);
|
||||
}
|
||||
return_statement:
|
||||
RETURN expression
|
||||
{
|
||||
$$ = new elna::source::return_statement(elna::source::make_position(@1), $2);
|
||||
}
|
||||
literal:
|
||||
INTEGER
|
||||
{
|
||||
$$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1);
|
||||
}
|
||||
| WORD
|
||||
{
|
||||
$$ = new elna::source::number_literal<std::uint32_t>(elna::source::make_position(@1), $1);
|
||||
}
|
||||
| FLOAT
|
||||
{
|
||||
$$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1);
|
||||
}
|
||||
| BOOLEAN
|
||||
{
|
||||
$$ = new elna::source::number_literal<bool>(elna::source::make_position(@1), $1);
|
||||
}
|
||||
| CHARACTER
|
||||
{
|
||||
$$ = new elna::source::number_literal<unsigned char>(elna::source::make_position(@1), $1.at(0));
|
||||
}
|
||||
| NIL
|
||||
{
|
||||
$$ = new elna::source::number_literal<std::nullptr_t>(elna::source::make_position(@1), nullptr);
|
||||
}
|
||||
| STRING
|
||||
{
|
||||
$$ = new elna::source::string_literal(elna::source::make_position(@1), $1);
|
||||
}
|
||||
pointer:
|
||||
literal { $$ = $1; }
|
||||
| designator_expression { $$ = $1; }
|
||||
| SIZEOF LEFT_PAREN type_expression RIGHT_PAREN
|
||||
{
|
||||
$$ = new elna::source::size_of_expression(elna::source::make_position(@1), $3);
|
||||
}
|
||||
| cast_expression { $$ = $1; }
|
||||
| call_expression { $$ = $1; }
|
||||
| LEFT_PAREN expression RIGHT_PAREN { $$ = $2; }
|
||||
summand:
|
||||
factor { $$ = std::move($1); }
|
||||
| factor MULTIPLICATION factor
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::multiplication);
|
||||
}
|
||||
| factor DIVISION factor
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::division);
|
||||
}
|
||||
| factor REMAINDER factor
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::remainder);
|
||||
}
|
||||
factor:
|
||||
AT pointer
|
||||
{
|
||||
$$ = new elna::source::unary_expression(elna::source::make_position(@1), $2,
|
||||
elna::source::unary_operator::reference);
|
||||
}
|
||||
| NOT pointer
|
||||
{
|
||||
$$ = new elna::source::unary_expression(elna::source::make_position(@1), $2,
|
||||
elna::source::unary_operator::negation);
|
||||
}
|
||||
| pointer { $$ = $1; }
|
||||
comparand:
|
||||
summand PLUS summand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::sum);
|
||||
}
|
||||
| summand MINUS summand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::subtraction);
|
||||
}
|
||||
| summand { $$ = std::move($1); }
|
||||
logical_operand:
|
||||
comparand EQUALS comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::equals);
|
||||
}
|
||||
| comparand NOT_EQUAL comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::not_equals);
|
||||
}
|
||||
| comparand LESS_THAN comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::less);
|
||||
}
|
||||
| comparand GREATER_THAN comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::greater);
|
||||
}
|
||||
| comparand LESS_EQUAL comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::less_equal);
|
||||
}
|
||||
| comparand GREATER_EQUAL comparand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::greater_equal);
|
||||
}
|
||||
| comparand { $$ = $1; }
|
||||
expression:
|
||||
logical_operand AND logical_operand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::conjunction);
|
||||
}
|
||||
| logical_operand OR logical_operand
|
||||
{
|
||||
$$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3,
|
||||
elna::source::binary_operator::disjunction);
|
||||
}
|
||||
| logical_operand { $$ = $1; }
|
||||
expressions:
|
||||
expression COMMA expressions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| expression { $$.emplace_back(std::move($1)); }
|
||||
designator_expression:
|
||||
designator_expression LEFT_SQUARE expression RIGHT_SQUARE
|
||||
{
|
||||
$$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3);
|
||||
}
|
||||
| designator_expression DOT IDENTIFIER
|
||||
{
|
||||
$$ = new elna::source::field_access_expression(elna::source::make_position(@2), $1, $3);
|
||||
}
|
||||
| designator_expression HAT
|
||||
{
|
||||
$$ = new elna::source::dereference_expression(elna::source::make_position(@1), $1);
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new elna::source::variable_expression(elna::source::make_position(@1), $1);
|
||||
}
|
||||
statement:
|
||||
assign_statement { $$ = $1; }
|
||||
| while_statement { $$ = $1; }
|
||||
| if_statement { $$ = $1; }
|
||||
| return_statement { $$ = $1; }
|
||||
| expression { $$ = new elna::source::expression_statement(elna::source::make_position(@1), $1); }
|
||||
statements:
|
||||
statement SEMICOLON statements
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| statement { $$.push_back($1); }
|
||||
optional_statements:
|
||||
statements { std::swap($$, $1); }
|
||||
| /* no statements */ {}
|
||||
field_declaration:
|
||||
IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); }
|
||||
field_list:
|
||||
field_declaration SEMICOLON field_list
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| field_declaration { $$.emplace_back($1); }
|
||||
type_expression:
|
||||
ARRAY INTEGER OF type_expression
|
||||
{
|
||||
$$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2);
|
||||
}
|
||||
| POINTER TO type_expression
|
||||
{
|
||||
$$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $3);
|
||||
}
|
||||
| RECORD field_list END_BLOCK
|
||||
{
|
||||
$$ = new elna::source::record_type_expression(elna::source::make_position(@1), std::move($2));
|
||||
}
|
||||
| UNION field_list END_BLOCK
|
||||
{
|
||||
$$ = new elna::source::union_type_expression(elna::source::make_position(@1), std::move($2));
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1);
|
||||
}
|
||||
variable_declaration: IDENTIFIER COLON type_expression
|
||||
{
|
||||
$$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3);
|
||||
}
|
||||
variable_declarations:
|
||||
variable_declaration COMMA variable_declarations
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| variable_declaration { $$.emplace_back(std::move($1)); }
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
||||
constant_definition: IDENTIFIER EQUALS literal
|
||||
{
|
||||
$$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3);
|
||||
}
|
||||
constant_definitions:
|
||||
constant_definition COMMA constant_definitions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| constant_definition { $$.emplace_back(std::move($1)); }
|
||||
constant_part:
|
||||
/* no constant definitions */ {}
|
||||
| CONST constant_definitions SEMICOLON { std::swap($$, $2); }
|
||||
type_definition: IDENTIFIER EQUALS type_expression
|
||||
{
|
||||
$$ = new elna::source::type_definition(elna::source::make_position(@1), $1, $3);
|
||||
}
|
||||
type_definitions:
|
||||
type_definition COMMA type_definitions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| type_definition { $$.emplace_back(std::move($1)); }
|
||||
type_part:
|
||||
/* no type definitions */ {}
|
||||
| TYPE type_definitions SEMICOLON { std::swap($$, $2); }
|
||||
formal_parameter_list:
|
||||
LEFT_PAREN RIGHT_PAREN {}
|
||||
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
||||
actual_parameter_list:
|
||||
LEFT_PAREN RIGHT_PAREN {}
|
||||
| LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); }
|
||||
%%
|
||||
|
||||
void yy::parser::error(const location_type& loc, const std::string& message)
|
||||
{
|
||||
driver.error(loc, message);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// 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/.
|
||||
#include "elna/source/result.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
error::error(const char *path, const struct position position)
|
||||
: position(position), path(path)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t error::line() const noexcept
|
||||
{
|
||||
return this->position.line;
|
||||
}
|
||||
|
||||
std::size_t error::column() const noexcept
|
||||
{
|
||||
return this->position.column;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user