Initial commit
This commit is contained in:
524
source/ast.cpp
Normal file
524
source/ast.cpp
Normal file
@ -0,0 +1,524 @@
|
||||
#include "elna/source/ast.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
void empty_visitor::visit(declaration *declaration)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(constant_definition *definition)
|
||||
{
|
||||
definition->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(procedure_definition *definition)
|
||||
{
|
||||
for (auto& parameter : definition->parameters())
|
||||
{
|
||||
parameter->accept(this);
|
||||
}
|
||||
definition->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(call_statement *statement)
|
||||
{
|
||||
for (auto& argument : statement->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(compound_statement *statement)
|
||||
{
|
||||
for (auto& nested_statement : statement->statements())
|
||||
{
|
||||
nested_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(assign_statement *statement)
|
||||
{
|
||||
statement->rvalue().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(if_statement *statement)
|
||||
{
|
||||
statement->prerequisite().accept(this);
|
||||
statement->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(while_statement *statement)
|
||||
{
|
||||
statement->prerequisite().accept(this);
|
||||
statement->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(block *block)
|
||||
{
|
||||
for (const auto& constant : block->definitions())
|
||||
{
|
||||
constant->accept(this);
|
||||
}
|
||||
for (const auto& block_declaration : block->declarations())
|
||||
{
|
||||
block_declaration->accept(this);
|
||||
}
|
||||
block->body().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(program *program)
|
||||
{
|
||||
visit(dynamic_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(type_expression *variable)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(variable_expression *variable)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(integer_literal *number)
|
||||
{
|
||||
}
|
||||
|
||||
void empty_visitor::visit(boolean_literal *boolean)
|
||||
{
|
||||
}
|
||||
|
||||
operand::~operand() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
integer_operand::integer_operand(const std::int32_t value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
std::int32_t integer_operand::value() const noexcept
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
variable_operand::variable_operand(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& variable_operand::name() const noexcept
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
temporary_variable::temporary_variable(const std::size_t counter)
|
||||
: m_counter(counter)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t temporary_variable::counter() const noexcept
|
||||
{
|
||||
return m_counter;
|
||||
}
|
||||
|
||||
label_operand::label_operand(const std::size_t counter)
|
||||
: m_counter(counter)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t label_operand::counter() const noexcept
|
||||
{
|
||||
return m_counter;
|
||||
}
|
||||
|
||||
node::node(const struct position position)
|
||||
: source_position(position)
|
||||
{
|
||||
}
|
||||
|
||||
const struct position& node::position() const noexcept
|
||||
{
|
||||
return this->source_position;
|
||||
}
|
||||
|
||||
statement::statement(const struct position position)
|
||||
: node(position)
|
||||
{
|
||||
}
|
||||
|
||||
expression::expression(const struct position position)
|
||||
: node(position)
|
||||
{
|
||||
}
|
||||
|
||||
type_expression::type_expression(const struct position position, const std::string& name, const bool is_pointer)
|
||||
: node(position), m_base(name), m_pointer(is_pointer)
|
||||
{
|
||||
}
|
||||
|
||||
void type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& type_expression::base() const noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
bool type_expression::is_pointer() const noexcept
|
||||
{
|
||||
return m_pointer;
|
||||
}
|
||||
|
||||
declaration::declaration(const struct position position, const std::string& identifier,
|
||||
std::unique_ptr<type_expression>&& type)
|
||||
: definition(position, identifier), m_type(std::move(type))
|
||||
{
|
||||
}
|
||||
|
||||
void declaration::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& declaration::type() noexcept
|
||||
{
|
||||
return *m_type;
|
||||
}
|
||||
|
||||
definition::definition(const struct position position, const std::string& identifier)
|
||||
: node(position), m_identifier(identifier)
|
||||
{
|
||||
}
|
||||
|
||||
std::string& definition::identifier() noexcept
|
||||
{
|
||||
return m_identifier;
|
||||
}
|
||||
|
||||
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
||||
std::unique_ptr<integer_literal>&& body)
|
||||
: definition(position, identifier), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void constant_definition::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
integer_literal& constant_definition::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||
std::unique_ptr<block>&& body)
|
||||
: definition(position, identifier), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void procedure_definition::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
block& procedure_definition::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<declaration>>& procedure_definition::parameters() noexcept
|
||||
{
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
block::block(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
|
||||
std::vector<std::unique_ptr<declaration>>&& declarations,
|
||||
std::unique_ptr<statement>&& body)
|
||||
: node(position), m_definitions(std::move(definitions)),
|
||||
m_declarations(std::move(declarations)), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void block::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
statement& block::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<definition>>& block::definitions() noexcept
|
||||
{
|
||||
return m_definitions;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<declaration>>& block::declarations() noexcept
|
||||
{
|
||||
return m_declarations;
|
||||
}
|
||||
|
||||
program::program(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
|
||||
std::vector<std::unique_ptr<declaration>>&& declarations,
|
||||
std::unique_ptr<statement>&& body)
|
||||
: block(position, std::move(definitions), std::move(declarations), std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void program::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
integer_literal::integer_literal(const struct position position, const std::int32_t value)
|
||||
: expression(position), m_number(value)
|
||||
{
|
||||
}
|
||||
|
||||
void integer_literal::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
std::int32_t integer_literal::number() const noexcept
|
||||
{
|
||||
return m_number;
|
||||
}
|
||||
|
||||
boolean_literal::boolean_literal(const struct position position, const bool value)
|
||||
: expression(position), m_boolean(value)
|
||||
{
|
||||
}
|
||||
|
||||
void boolean_literal::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
bool boolean_literal::boolean() const noexcept
|
||||
{
|
||||
return m_boolean;
|
||||
}
|
||||
|
||||
variable_expression::variable_expression(const struct position position, const std::string& name)
|
||||
: expression(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void variable_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& variable_expression::name() const noexcept
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
binary_expression::binary_expression(const struct position position, std::unique_ptr<expression>&& lhs,
|
||||
std::unique_ptr<expression>&& rhs, const unsigned char operation)
|
||||
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case '+':
|
||||
this->m_operator = binary_operator::sum;
|
||||
break;
|
||||
case '-':
|
||||
this->m_operator = binary_operator::subtraction;
|
||||
break;
|
||||
case '*':
|
||||
this->m_operator = binary_operator::multiplication;
|
||||
break;
|
||||
case '/':
|
||||
this->m_operator = binary_operator::division;
|
||||
break;
|
||||
case '=':
|
||||
this->m_operator = binary_operator::equals;
|
||||
break;
|
||||
case 'n':
|
||||
this->m_operator = binary_operator::not_equals;
|
||||
break;
|
||||
case '<':
|
||||
this->m_operator = binary_operator::less;
|
||||
break;
|
||||
case 'l':
|
||||
this->m_operator = binary_operator::less_equal;
|
||||
break;
|
||||
case '>':
|
||||
this->m_operator = binary_operator::greater;
|
||||
break;
|
||||
case 'g':
|
||||
this->m_operator = binary_operator::greater_equal;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid binary operator");
|
||||
}
|
||||
}
|
||||
|
||||
void binary_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& binary_expression::lhs()
|
||||
{
|
||||
return *m_lhs;
|
||||
}
|
||||
|
||||
expression& binary_expression::rhs()
|
||||
{
|
||||
return *m_rhs;
|
||||
}
|
||||
|
||||
binary_operator binary_expression::operation() const noexcept
|
||||
{
|
||||
return m_operator;
|
||||
}
|
||||
|
||||
unary_expression::unary_expression(const struct position position, std::unique_ptr<expression>&& operand,
|
||||
const unsigned char operation)
|
||||
: expression(position), m_operand(std::move(operand))
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case '@':
|
||||
this->m_operator = unary_operator::reference;
|
||||
break;
|
||||
case '^':
|
||||
this->m_operator = unary_operator::dereference;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid unary operator");
|
||||
}
|
||||
}
|
||||
|
||||
void unary_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& unary_expression::operand()
|
||||
{
|
||||
return *m_operand;
|
||||
}
|
||||
|
||||
unary_operator unary_expression::operation() const noexcept
|
||||
{
|
||||
return this->m_operator;
|
||||
}
|
||||
|
||||
call_statement::call_statement(const struct position position, const std::string& name)
|
||||
: statement(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void call_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
std::string& call_statement::name() noexcept
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<expression>>& call_statement::arguments() noexcept
|
||||
{
|
||||
return m_arguments;
|
||||
}
|
||||
|
||||
compound_statement::compound_statement(const struct position position)
|
||||
: statement(position)
|
||||
{
|
||||
}
|
||||
|
||||
void compound_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<statement>>& compound_statement::statements()
|
||||
{
|
||||
return m_statements;
|
||||
}
|
||||
|
||||
void assign_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
assign_statement::assign_statement(const struct position position, const std::string& lvalue,
|
||||
std::unique_ptr<expression>&& rvalue)
|
||||
: statement(position), m_lvalue(lvalue), m_rvalue(std::move(rvalue))
|
||||
{
|
||||
}
|
||||
|
||||
std::string& assign_statement::lvalue() noexcept
|
||||
{
|
||||
return m_lvalue;
|
||||
}
|
||||
|
||||
expression& assign_statement::rvalue()
|
||||
{
|
||||
return *m_rvalue;
|
||||
}
|
||||
|
||||
if_statement::if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
||||
std::unique_ptr<statement>&& body)
|
||||
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void if_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& if_statement::prerequisite()
|
||||
{
|
||||
return *m_prerequisite;
|
||||
}
|
||||
|
||||
statement& if_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
while_statement::while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
||||
std::unique_ptr<statement>&& body)
|
||||
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
void while_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& while_statement::prerequisite()
|
||||
{
|
||||
return *m_prerequisite;
|
||||
}
|
||||
|
||||
statement& while_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
}
|
131
source/lexer.ll
Normal file
131
source/lexer.ll
Normal file
@ -0,0 +1,131 @@
|
||||
%{
|
||||
#define YY_NO_UNISTD_H
|
||||
#define YY_USER_ACTION this->location.columns(yyleng);
|
||||
|
||||
#include <sstream>
|
||||
#include "parser.hpp"
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL yy::parser::symbol_type elna::syntax::FooLexer::lex()
|
||||
#define yyterminate() return yy::parser::make_YYEOF(this->location)
|
||||
%}
|
||||
|
||||
%option c++ noyywrap never-interactive
|
||||
%option yyclass="elna::syntax::FooLexer"
|
||||
|
||||
%%
|
||||
%{
|
||||
this->location.step();
|
||||
%}
|
||||
|
||||
\-\-.* {
|
||||
/* Skip the 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
const {
|
||||
return yy::parser::make_CONST(this->location);
|
||||
}
|
||||
var {
|
||||
return yy::parser::make_VAR(this->location);
|
||||
}
|
||||
True {
|
||||
return yy::parser::make_BOOLEAN(true, this->location);
|
||||
}
|
||||
False {
|
||||
return yy::parser::make_BOOLEAN(false, this->location);
|
||||
}
|
||||
[A-Za-z_][A-Za-z0-9_]* {
|
||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||
}
|
||||
[0-9]+ {
|
||||
return yy::parser::make_NUMBER(strtol(yytext, NULL, 10), this->location);
|
||||
}
|
||||
\( {
|
||||
return yy::parser::make_LEFT_PAREN(this->location);
|
||||
}
|
||||
\) {
|
||||
return yy::parser::make_RIGHT_PAREN(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_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 char>(yytext[0]);
|
||||
throw yy::parser::syntax_error(this->location, ss.str());
|
||||
}
|
||||
%%
|
141
source/parser.yy
Normal file
141
source/parser.yy
Normal file
@ -0,0 +1,141 @@
|
||||
%require "3.2"
|
||||
%language "c++"
|
||||
|
||||
%code requires {
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "elna/source/ast.hpp"
|
||||
|
||||
|
||||
#if ! defined(yyFlexLexerOnce)
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
namespace elna::syntax
|
||||
{
|
||||
class FooLexer;
|
||||
}
|
||||
}
|
||||
|
||||
%code provides {
|
||||
namespace elna::syntax
|
||||
{
|
||||
|
||||
class FooLexer : public yyFlexLexer
|
||||
{
|
||||
public:
|
||||
yy::location location;
|
||||
|
||||
FooLexer(std::istream& arg_yyin)
|
||||
: yyFlexLexer(&arg_yyin)
|
||||
{
|
||||
}
|
||||
|
||||
yy::parser::symbol_type lex();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
%define api.token.raw
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
%define parse.assert
|
||||
|
||||
%parse-param {elna::syntax::FooLexer& lexer}
|
||||
%parse-param {std::unique_ptr<elna::source::program>& program}
|
||||
%locations
|
||||
|
||||
%header
|
||||
|
||||
%code {
|
||||
#define yylex lexer.lex
|
||||
}
|
||||
%start program;
|
||||
|
||||
%token <std::string> IDENTIFIER "identifier"
|
||||
%token <std::int32_t> NUMBER "number"
|
||||
%token <bool> BOOLEAN
|
||||
%token IF THEN WHILE DO
|
||||
%token CONST VAR PROCEDURE
|
||||
%token BEGIN_BLOCK END_BLOCK
|
||||
%token TRUE FALSE
|
||||
%token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA
|
||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||
%token PLUS MINUS MULTIPLICATION DIVISION
|
||||
%token ASSIGNMENT COLON HAT AT
|
||||
|
||||
%type <std::unique_ptr<elna::source::integer_literal>> integer_literal;
|
||||
%type <std::unique_ptr<elna::source::constant_definition>> constant_definition;
|
||||
%type <std::vector<std::unique_ptr<elna::source::constant_definition>>> constant_definition_part constant_definitions;
|
||||
%type <std::unique_ptr<elna::source::type_expression>> type_expression;
|
||||
%%
|
||||
program: constant_definition_part
|
||||
{
|
||||
elna::source::position position;
|
||||
std::vector<std::unique_ptr<elna::source::declaration>> declarations;
|
||||
std::vector<std::unique_ptr<elna::source::definition>> definitions($1.size());
|
||||
std::vector<std::unique_ptr<elna::source::definition>>::iterator definition = definitions.begin();
|
||||
|
||||
for (auto& constant : $1)
|
||||
{
|
||||
*definition++ = std::move(constant);
|
||||
}
|
||||
program = std::make_unique<elna::source::program>(position,
|
||||
std::move(definitions), std::move(declarations),
|
||||
std::make_unique<elna::source::compound_statement>(position));
|
||||
}
|
||||
integer_literal: NUMBER
|
||||
{
|
||||
elna::source::position position{
|
||||
static_cast<std::size_t>(@1.begin.line),
|
||||
static_cast<std::size_t>(@1.begin.column)
|
||||
};
|
||||
$$ = std::make_unique<elna::source::integer_literal>(position, $1);
|
||||
};
|
||||
type_expression:
|
||||
HAT IDENTIFIER
|
||||
{
|
||||
elna::source::position position{
|
||||
static_cast<std::size_t>(@1.begin.line),
|
||||
static_cast<std::size_t>(@1.begin.column)
|
||||
};
|
||||
$$ = std::make_unique<elna::source::type_expression>(position, $2, true);
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
elna::source::position position{
|
||||
static_cast<std::size_t>(@1.begin.line),
|
||||
static_cast<std::size_t>(@1.begin.column)
|
||||
};
|
||||
$$ = std::make_unique<elna::source::type_expression>(position, $1, false);
|
||||
}
|
||||
variable_declaration: IDENTIFIER COLON type_expression
|
||||
variable_declarations:
|
||||
variable_declaration COMMA variable_declarations
|
||||
| variable_declaration
|
||||
constant_definition: IDENTIFIER EQUALS integer_literal
|
||||
{
|
||||
elna::source::position position{
|
||||
static_cast<std::size_t>(@1.begin.line),
|
||||
static_cast<std::size_t>(@1.begin.column)
|
||||
};
|
||||
$$ = std::make_unique<elna::source::constant_definition>(position,
|
||||
$1, std::move($3));
|
||||
};
|
||||
constant_definitions:
|
||||
constant_definition COMMA constant_definitions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| constant_definition { $$.emplace_back(std::move($1)); }
|
||||
constant_definition_part:
|
||||
/* no constant definitions */ {}
|
||||
| CONST constant_definitions SEMICOLON { std::swap($$, $2); };
|
||||
%%
|
||||
|
||||
void yy::parser::error(const location_type& loc, const std::string &message)
|
||||
{
|
||||
std::cerr << "Error: " << message << std::endl;
|
||||
}
|
24
source/result.cpp
Normal file
24
source/result.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "elna/source/result.hpp"
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
error::error(const std::filesystem::path& path, const position position)
|
||||
: m_position(position), m_path(path)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t error::line() const noexcept
|
||||
{
|
||||
return this->m_position.line;
|
||||
}
|
||||
|
||||
std::size_t error::column() const noexcept
|
||||
{
|
||||
return this->m_position.column;
|
||||
}
|
||||
|
||||
const std::filesystem::path& error::path() const noexcept
|
||||
{
|
||||
return this->m_path;
|
||||
}
|
||||
}
|
96
source/types.cpp
Normal file
96
source/types.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include <elna/source/types.hpp>
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
type::type(const std::size_t byte_size)
|
||||
: byte_size(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t type::size() const noexcept
|
||||
{
|
||||
return this->byte_size;
|
||||
}
|
||||
|
||||
primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size)
|
||||
: type(byte_size), type_name(type_name)
|
||||
{
|
||||
}
|
||||
|
||||
bool primitive_type::operator==(const primitive_type& that) const noexcept
|
||||
{
|
||||
return this->type_name == that.type_name;
|
||||
}
|
||||
|
||||
bool primitive_type::operator!=(const primitive_type& that) const noexcept
|
||||
{
|
||||
return this->type_name != that.type_name;
|
||||
}
|
||||
|
||||
pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size)
|
||||
: type(byte_size), base_type(base_type)
|
||||
{
|
||||
}
|
||||
|
||||
bool pointer_type::operator==(const pointer_type& that) const noexcept
|
||||
{
|
||||
return this->base_type == that.base_type;
|
||||
}
|
||||
|
||||
bool pointer_type::operator!=(const pointer_type& that) const noexcept
|
||||
{
|
||||
return this->base_type != that.base_type;
|
||||
}
|
||||
|
||||
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
|
||||
: arguments(std::move(arguments)), type(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
bool procedure_type::operator==(const procedure_type &that) const noexcept
|
||||
{
|
||||
return this->arguments == that.arguments;
|
||||
}
|
||||
|
||||
bool procedure_type::operator!=(const procedure_type &that) const noexcept
|
||||
{
|
||||
return this->arguments != that.arguments;
|
||||
}
|
||||
|
||||
bool operator==(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const primitive_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const primitive_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const pointer_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const pointer_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const procedure_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const procedure_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user