Rename elna::source to elna:boot

This commit is contained in:
2025-01-31 09:46:17 +01:00
parent 45898bb95f
commit 4011adbe2b
19 changed files with 754 additions and 654 deletions

View File

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

View File

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

View File

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

View File

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

View File

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