diff --git a/source/ast.cc b/boot/ast.cc similarity index 98% rename from source/ast.cc rename to boot/ast.cc index 2187a6b..ccca46e 100644 --- a/source/ast.cc +++ b/boot/ast.cc @@ -1,11 +1,11 @@ // 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" +#include "elna/boot/ast.h" namespace elna { -namespace source +namespace boot { void empty_visitor::visit(variable_declaration *) { @@ -52,7 +52,7 @@ namespace source expression->body().accept(this); } - void empty_visitor::visit(expression_statement *statement) + void empty_visitor::visit(call_statement *statement) { statement->body().accept(this); } @@ -783,22 +783,22 @@ namespace source delete m_body; } - expression_statement::expression_statement(const struct position position, expression *body) + call_statement::call_statement(const struct position position, call_expression *body) : statement(position), m_body(body) { } - void expression_statement::accept(parser_visitor *visitor) + void call_statement::accept(parser_visitor *visitor) { visitor->visit(this); } - expression& expression_statement::body() + call_expression& call_statement::body() { return *m_body; } - expression_statement::~expression_statement() + call_statement::~call_statement() { delete m_body; } diff --git a/source/driver.cc b/boot/driver.cc similarity index 93% rename from source/driver.cc rename to boot/driver.cc index c58324f..dab1436 100644 --- a/source/driver.cc +++ b/boot/driver.cc @@ -1,11 +1,11 @@ // 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" +#include "elna/boot/driver.h" namespace elna { -namespace source +namespace boot { position make_position(const yy::location& location) { @@ -33,7 +33,7 @@ namespace source void driver::error(const yy::location& loc, const std::string& message) { - m_errors.emplace_back(std::make_unique(message, input_file, loc)); + m_errors.emplace_back(std::make_unique(message, input_file, loc)); } const std::list>& driver::errors() const noexcept diff --git a/source/lexer.ll b/boot/lexer.ll similarity index 97% rename from source/lexer.ll rename to boot/lexer.ll index 66faaa5..96d2b66 100644 --- a/source/lexer.ll +++ b/boot/lexer.ll @@ -11,12 +11,12 @@ #include "parser.hh" #undef YY_DECL -#define YY_DECL yy::parser::symbol_type elna::source::lexer::lex(elna::source::driver& driver) +#define YY_DECL yy::parser::symbol_type elna::boot::lexer::lex(elna::boot::driver& driver) #define yyterminate() return yy::parser::make_YYEOF(this->location) %} %option c++ noyywrap never-interactive -%option yyclass="elna::source::lexer" +%option yyclass="elna::boot::lexer" %x IN_COMMENT @@ -155,7 +155,7 @@ sizeof { return yy::parser::make_CHARACTER(std::string(&character, 1), this->location); } '\\[0nabtfrv\\'"?]' { - std::optional escape = source::escape_char(yytext[2]); + std::optional escape = elna::boot::escape_char(yytext[2]); if (escape.has_value()) { return yy::parser::make_CHARACTER(std::string(&escape.value(), 1), this->location); @@ -191,7 +191,7 @@ sizeof { { ++current_position; - std::optional escape = source::escape_char(*current_position); + std::optional escape = elna::boot::escape_char(*current_position); if (escape.has_value()) { result.push_back(escape.value()); diff --git a/boot/parser.yy b/boot/parser.yy new file mode 100644 index 0000000..af986ce --- /dev/null +++ b/boot/parser.yy @@ -0,0 +1,482 @@ +/* + * 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 + #include + #include "elna/boot/driver.h" + + #if !defined(yyFlexLexerOnce) + #include + #endif + + namespace elna + { + namespace boot + { + class lexer; + } + } +} + +%code provides { + namespace elna + { + namespace boot + { + + class lexer: public yyFlexLexer + { + public: + yy::location location; + + lexer(std::istream& arg_yyin) + : yyFlexLexer(&arg_yyin) + { + } + + yy::parser::symbol_type lex(elna::boot::driver& driver); + }; + + } + } +} + +%define api.token.raw +%define api.token.constructor +%define api.value.type variant + +%parse-param {elna::boot::lexer& lexer} +%param {elna::boot::driver& driver} +%locations + +%header + +%code { + #define yylex lexer.lex +} +%start program; + +%token IDENTIFIER "identifier" +%token INTEGER "integer" +%token WORD "word" +%token FLOAT "float" +%token CHARACTER "character" +%token STRING "string" +%token 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 + +%left OR AND +%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL +%left PLUS MINUS +%left MULTIPLICATION DIVISION REMAINDER + +%type literal; +%type constant_definition; +%type > constant_part constant_definitions; +%type variable_declaration; +%type > variable_declarations variable_part + formal_parameter_list; +%type type_expression; +%type expression operand unary; +%type > expressions actual_parameter_list; +%type designator_expression; +%type assign_statement; +%type call_expression; +%type while_statement; +%type if_statement; +%type return_statement; +%type statement; +%type > statements optional_statements; +%type procedure_definition; +%type > procedure_definitions procedure_part; +%type type_definition; +%type > type_definitions type_part; +%type block; +%type > field_declaration; +%type >> field_list; +%type > elsif_statement_list; +%type cast_expression; +%% +program: + type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT + { + std::vector definitions($1.size() + $3.size()); + std::vector::iterator definition = definitions.begin(); + std::vector value_definitions($2.size() + $4.size()); + std::vector::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::boot::program(elna::boot::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 definitions($1.size() + $2.size()); + std::vector::iterator definition = definitions.begin(); + + for (auto constant : $1) + { + *definition++ = constant; + } + for (auto variable : $2) + { + *definition++ = variable; + } + $$ = new elna::boot::block(elna::boot::make_position(@3), + std::move(definitions), std::move($4)); + } +procedure_definition: + PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON + { + $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), + $2, std::move($3), nullptr, $5); + } + | PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON + { + $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), + $2, std::move($3), nullptr, nullptr); + } + | PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON block SEMICOLON + { + $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), + $2, std::move($3), $5, $7); + } + | PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON EXTERN SEMICOLON + { + $$ = new elna::boot::procedure_definition(elna::boot::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::boot::assign_statement(elna::boot::make_position(@1), $1, $3); + } +call_expression: IDENTIFIER actual_parameter_list + { + $$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1); + std::swap($$->arguments(), $2); + } +cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN + { + $$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3); + } +while_statement: WHILE expression DO optional_statements END_BLOCK + { + auto body = new elna::boot::conditional_statements($2); + std::swap($4, body->statements); + $$ = new elna::boot::while_statement(elna::boot::make_position(@1), body); + } +elsif_statement_list: + ELSIF expression THEN optional_statements elsif_statement_list + { + elna::boot::conditional_statements *branch = new elna::boot::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::boot::conditional_statements($2); + std::swap($4, then->statements); + $$ = new elna::boot::if_statement(elna::boot::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::boot::conditional_statements($2); + std::swap($4, then->statements); + auto _else = new std::vector(std::move($7)); + $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else); + std::swap($5, $$->branches); + } +return_statement: + RETURN expression + { + $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2); + } +literal: + INTEGER + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), $1); + } + | WORD + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), $1); + } + | FLOAT + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), $1); + } + | BOOLEAN + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), $1); + } + | CHARACTER + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), $1.at(0)); + } + | NIL + { + $$ = new elna::boot::number_literal(elna::boot::make_position(@1), nullptr); + } + | STRING + { + $$ = new elna::boot::string_literal(elna::boot::make_position(@1), $1); + } +operand: + literal { $$ = $1; } + | designator_expression { $$ = $1; } + | SIZEOF LEFT_PAREN type_expression RIGHT_PAREN + { + $$ = new elna::boot::size_of_expression(elna::boot::make_position(@1), $3); + } + | cast_expression { $$ = $1; } + | call_expression { $$ = $1; } + | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; } +expression: + unary { $$ = $1; } + | expression MULTIPLICATION expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::multiplication); + } + | expression DIVISION expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::division); + } + | expression REMAINDER expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::remainder); + } + | expression PLUS expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::sum); + } + | expression MINUS expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::subtraction); + } + | expression EQUALS expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::equals); + } + | expression NOT_EQUAL expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::not_equals); + } + | expression LESS_THAN expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::less); + } + | expression GREATER_THAN expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::greater); + } + | expression LESS_EQUAL expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::less_equal); + } + | expression GREATER_EQUAL expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::greater_equal); + } + | expression AND expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::conjunction); + } + | expression OR expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::disjunction); + } +unary: + AT operand + { + $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2, + elna::boot::unary_operator::reference); + } + | NOT operand + { + $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2, + elna::boot::unary_operator::negation); + } + | 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::boot::array_access_expression(elna::boot::make_position(@1), $1, $3); + } + | designator_expression DOT IDENTIFIER + { + $$ = new elna::boot::field_access_expression(elna::boot::make_position(@2), $1, $3); + } + | designator_expression HAT + { + $$ = new elna::boot::dereference_expression(elna::boot::make_position(@1), $1); + } + | IDENTIFIER + { + $$ = new elna::boot::variable_expression(elna::boot::make_position(@1), $1); + } +statement: + assign_statement { $$ = $1; } + | while_statement { $$ = $1; } + | if_statement { $$ = $1; } + | return_statement { $$ = $1; } + | call_expression + { + $$ = new elna::boot::call_statement(elna::boot::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::boot::array_type_expression(elna::boot::make_position(@1), $4, $2); + } + | POINTER TO type_expression + { + $$ = new elna::boot::pointer_type_expression(elna::boot::make_position(@1), $3); + } + | RECORD field_list END_BLOCK + { + $$ = new elna::boot::record_type_expression(elna::boot::make_position(@1), std::move($2)); + } + | UNION field_list END_BLOCK + { + $$ = new elna::boot::union_type_expression(elna::boot::make_position(@1), std::move($2)); + } + | IDENTIFIER + { + $$ = new elna::boot::basic_type_expression(elna::boot::make_position(@1), $1); + } +variable_declaration: IDENTIFIER COLON type_expression + { + $$ = new elna::boot::variable_declaration(elna::boot::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::boot::constant_definition(elna::boot::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::boot::type_definition(elna::boot::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); +} diff --git a/source/result.cc b/boot/result.cc similarity index 91% rename from source/result.cc rename to boot/result.cc index 21388ca..8c3585c 100644 --- a/source/result.cc +++ b/boot/result.cc @@ -1,11 +1,11 @@ // 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" +#include "elna/boot/result.h" namespace elna { -namespace source +namespace boot { error::error(const char *path, const struct position position) : position(position), path(path) diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in index e87da96..a0fbc0d 100644 --- a/gcc/Make-lang.in +++ b/gcc/Make-lang.in @@ -88,7 +88,7 @@ elna.stagefeedback: stagefeedback-start ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated -elna/%.o: elna/source/%.cc elna/generated/parser.hh elna/generated/location.hh +elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh $(COMPILE) $(ELNA_INCLUDES) $< $(POSTCOMPILE) @@ -100,13 +100,13 @@ elna/%.o: elna/gcc/%.cc elna/generated/parser.hh elna/generated/location.hh $(COMPILE) $(ELNA_INCLUDES) $< $(POSTCOMPILE) -elna/generated/parser.cc: elna/source/parser.yy +elna/generated/parser.cc: elna/boot/parser.yy mkdir -p $(dir $@) $(BISON) -d -o $@ $< elna/generated/parser.hh elna/generated/location.hh: elna/generated/parser.cc @touch $@ -elna/generated/lexer.cc: elna/source/lexer.ll +elna/generated/lexer.cc: elna/boot/lexer.ll mkdir -p $(dir $@) $(FLEX) -o $@ $< diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc index 5693064..c3035f4 100644 --- a/gcc/elna-diagnostic.cc +++ b/gcc/elna-diagnostic.cc @@ -5,7 +5,7 @@ namespace elna { namespace gcc { - location_t get_location(const elna::source::position *position) + location_t get_location(const boot::position *position) { linemap_line_start(line_table, position->line, 0); diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 1e68825..0d72c03 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -16,12 +16,12 @@ namespace elna { namespace gcc { - generic_visitor::generic_visitor(std::shared_ptr> symbol_table) + generic_visitor::generic_visitor(std::shared_ptr> symbol_table) { this->symbol_map = symbol_table; } - void generic_visitor::visit(source::call_expression *expression) + void generic_visitor::visit(boot::call_expression *expression) { if (auto symbol = this->symbol_map->lookup(expression->name())) { @@ -57,7 +57,7 @@ namespace gcc } } - void generic_visitor::visit(source::cast_expression *expression) + void generic_visitor::visit(boot::cast_expression *expression) { tree cast_target = build_type(expression->target()); gcc_assert(cast_target != NULL_TREE); @@ -68,14 +68,14 @@ namespace gcc cast_target, this->current_expression); } - void generic_visitor::visit(source::size_of_expression *expression) + void generic_visitor::visit(boot::size_of_expression *expression) { auto body_type = build_type(expression->body()); this->current_expression = build1(CONVERT_EXPR, integer_type_node, TYPE_SIZE_UNIT(body_type)); } - void generic_visitor::visit(source::program *program) + void generic_visitor::visit(boot::program *program) { for (const auto definition : program->value_definitions) { @@ -119,7 +119,7 @@ namespace gcc cgraph_node::finalize_function(this->main_fndecl, true); } - void generic_visitor::visit(source::procedure_definition *definition) + void generic_visitor::visit(boot::procedure_definition *definition) { std::vector parameter_types(definition->parameters.size()); @@ -133,7 +133,7 @@ namespace gcc tree declaration_type = build_function_type_array(return_type, definition->parameters.size(), parameter_types.data()); this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type); - this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); + this->symbol_map->enter(definition->identifier(), boot::make_info(this->main_fndecl)); if (definition->body() != nullptr) { @@ -155,7 +155,7 @@ namespace gcc if (definition->body() != nullptr) { - this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree)); + this->symbol_map->enter(parameter->identifier(), boot::make_info(declaration_tree)); } argument_chain.append(declaration_tree); } @@ -187,7 +187,7 @@ namespace gcc { this->current_statements = alloc_stmt_list(); this->variable_chain = tree_chain(); - this->symbol_map = std::make_shared>(this->symbol_map); + this->symbol_map = std::make_shared>(this->symbol_map); } tree_symbol_mapping generic_visitor::leave_scope() @@ -201,17 +201,17 @@ namespace gcc return tree_symbol_mapping{ bind_expr, new_block }; } - void generic_visitor::visit(source::number_literal *literal) + void generic_visitor::visit(boot::number_literal *literal) { this->current_expression = build_int_cst(integer_type_node, literal->number()); } - void generic_visitor::visit(source::number_literal *literal) + void generic_visitor::visit(boot::number_literal *literal) { this->current_expression = build_int_cstu(unsigned_type_node, literal->number()); } - void generic_visitor::visit(source::number_literal *literal) + void generic_visitor::visit(boot::number_literal *literal) { REAL_VALUE_TYPE real_value1; @@ -226,27 +226,27 @@ namespace gcc mpfr_clear(number); } - void generic_visitor::visit(source::number_literal *boolean) + void generic_visitor::visit(boot::number_literal *boolean) { this->current_expression = build_int_cst_type(boolean_type_node, boolean->number()); } - void generic_visitor::visit(source::number_literal *character) + void generic_visitor::visit(boot::number_literal *character) { this->current_expression = build_int_cstu(elna_char_type_node, character->number()); } - void generic_visitor::visit(source::number_literal *) + void generic_visitor::visit(boot::number_literal *) { this->current_expression = null_pointer_node; } - void generic_visitor::visit(source::string_literal *string) + void generic_visitor::visit(boot::string_literal *string) { this->current_expression = build_string_literal(string->string().size() + 1, string->string().c_str()); } - void generic_visitor::build_binary_operation(bool condition, source::binary_expression *expression, + void generic_visitor::build_binary_operation(bool condition, boot::binary_expression *expression, tree_code operator_code, tree left, tree right, tree target_type) { auto expression_location = get_location(&expression->position()); @@ -263,12 +263,12 @@ namespace gcc error_at(expression_location, "invalid operands of type %s and %s for operator %s", print_type(left_type), print_type(right_type), - elna::source::print_binary_operator(expression->operation())); + elna::boot::print_binary_operator(expression->operation())); this->current_expression = error_mark_node; } } - void generic_visitor::visit(source::binary_expression *expression) + void generic_visitor::visit(boot::binary_expression *expression) { expression->lhs().accept(this); auto left = this->current_expression; @@ -284,7 +284,7 @@ namespace gcc if (is_pointer_type(left_type) && (right_type == integer_type_node || right_type == unsigned_type_node) - && expression->operation() == source::binary_operator::sum) + && expression->operation() == boot::binary_operator::sum) { tree convert_expression = build1_loc(expression_location, CONVERT_EXPR, sizetype, right); @@ -297,45 +297,45 @@ namespace gcc error_at(expression_location, "invalid operands of type %s and %s for operator %s", print_type(left_type), print_type(right_type), - elna::source::print_binary_operator(expression->operation())); + boot::print_binary_operator(expression->operation())); this->current_expression = error_mark_node; return; } switch (expression->operation()) { - case source::binary_operator::sum: + case boot::binary_operator::sum: operator_code = PLUS_EXPR; target_type = left_type; break; - case source::binary_operator::subtraction: + case boot::binary_operator::subtraction: operator_code = MINUS_EXPR; target_type = left_type; break; - case source::binary_operator::division: + case boot::binary_operator::division: operator_code = TRUNC_DIV_EXPR; target_type = left_type; break; - case source::binary_operator::remainder: + case boot::binary_operator::remainder: operator_code = TRUNC_MOD_EXPR; target_type = left_type; break; - case source::binary_operator::multiplication: + case boot::binary_operator::multiplication: operator_code = MULT_EXPR; target_type = left_type; break; - case source::binary_operator::less: + case boot::binary_operator::less: operator_code = LT_EXPR; target_type = boolean_type_node; break; - case source::binary_operator::greater: + case boot::binary_operator::greater: operator_code = GT_EXPR; target_type = boolean_type_node; break; - case source::binary_operator::less_equal: + case boot::binary_operator::less_equal: operator_code = LE_EXPR; target_type = boolean_type_node; break; - case source::binary_operator::greater_equal: + case boot::binary_operator::greater_equal: operator_code = GE_EXPR; target_type = boolean_type_node; break; @@ -350,11 +350,11 @@ namespace gcc } switch (expression->operation()) { - case source::binary_operator::conjunction: + case boot::binary_operator::conjunction: operator_code = TRUTH_ANDIF_EXPR; target_type = boolean_type_node; break; - case source::binary_operator::disjunction: + case boot::binary_operator::disjunction: operator_code = TRUTH_ORIF_EXPR; target_type = boolean_type_node; break; @@ -369,11 +369,11 @@ namespace gcc } switch (expression->operation()) { - case source::binary_operator::equals: + case boot::binary_operator::equals: operator_code = EQ_EXPR; target_type = boolean_type_node; break; - case source::binary_operator::not_equals: + case boot::binary_operator::not_equals: operator_code = NE_EXPR; target_type = boolean_type_node; break; @@ -387,34 +387,34 @@ namespace gcc operator_code, target_type, left, right); } - void generic_visitor::visit(source::unary_expression *expression) + void generic_visitor::visit(boot::unary_expression *expression) { expression->operand().accept(this); switch (expression->operation()) { - case source::unary_operator::reference: + case boot::unary_operator::reference: TREE_ADDRESSABLE(this->current_expression) = 1; this->current_expression = build_fold_addr_expr_with_type_loc(get_location(&expression->position()), this->current_expression, build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true)); TREE_NO_TRAMPOLINE(this->current_expression) = 1; break; - case source::unary_operator::negation: + case boot::unary_operator::negation: this->current_expression = build1_loc(get_location(&expression->position()), TRUTH_NOT_EXPR, boolean_type_node, this->current_expression); break; } } - void generic_visitor::visit(source::constant_definition *definition) + void generic_visitor::visit(boot::constant_definition *definition) { location_t definition_location = get_location(&definition->position()); definition->body().accept(this); tree definition_tree = build_decl(definition_location, CONST_DECL, get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression)); - auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree)); + auto result = this->symbol_map->enter(definition->identifier(), boot::make_info(definition_tree)); if (result) { @@ -435,7 +435,7 @@ namespace gcc this->current_expression = NULL_TREE; } - void generic_visitor::visit(source::type_definition *definition) + void generic_visitor::visit(boot::type_definition *definition) { tree tree_type = build_type(definition->body()); @@ -446,7 +446,7 @@ namespace gcc location_t definition_location = get_location(&definition->position()); tree definition_tree = build_decl(definition_location, TYPE_DECL, get_identifier(definition->identifier().c_str()), tree_type); - auto result = this->symbol_map->enter(definition->identifier(), source::make_info(tree_type)); + auto result = this->symbol_map->enter(definition->identifier(), boot::make_info(tree_type)); if (result) { @@ -465,9 +465,9 @@ namespace gcc } } - tree generic_visitor::build_type(source::type_expression& type) + tree generic_visitor::build_type(boot::type_expression& type) { - if (source::basic_type_expression *basic_type = type.is_basic()) + if (boot::basic_type_expression *basic_type = type.is_basic()) { auto symbol = this->symbol_map->lookup(basic_type->base_name()); @@ -480,7 +480,7 @@ namespace gcc return error_mark_node; } - else if (source::array_type_expression *array_type = type.is_array()) + else if (boot::array_type_expression *array_type = type.is_array()) { tree lower_bound = build_int_cst_type(integer_type_node, 0); tree upper_bound = build_int_cst_type(integer_type_node, array_type->size); @@ -494,7 +494,7 @@ namespace gcc return build_array_type(base_type, range_type); } - else if (source::pointer_type_expression *pointer_type = type.is_pointer()) + else if (boot::pointer_type_expression *pointer_type = type.is_pointer()) { tree base_type = build_type(pointer_type->base()); @@ -504,7 +504,7 @@ namespace gcc } return build_pointer_type_for_mode(base_type, VOIDmode, true); } - else if (source::record_type_expression *record_type = type.is_record()) + else if (boot::record_type_expression *record_type = type.is_record()) { std::set field_names; tree record_type_node = make_node(RECORD_TYPE); @@ -536,7 +536,7 @@ namespace gcc return record_type_node; } - else if (source::union_type_expression *union_type = type.is_union()) + else if (boot::union_type_expression *union_type = type.is_union()) { std::set field_names; tree union_type_node = make_node(UNION_TYPE); @@ -571,7 +571,7 @@ namespace gcc return NULL_TREE; } - void generic_visitor::visit(source::variable_declaration *declaration) + void generic_visitor::visit(boot::variable_declaration *declaration) { tree declaration_type = build_type(declaration->type()); gcc_assert(declaration_type != NULL_TREE); @@ -579,7 +579,7 @@ namespace gcc auto declaration_location = get_location(&declaration->position()); tree declaration_tree = build_decl(declaration_location, VAR_DECL, get_identifier(declaration->identifier().c_str()), declaration_type); - auto result = this->symbol_map->enter(declaration->identifier(), source::make_info(declaration_tree)); + auto result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree)); if (result) { @@ -598,7 +598,7 @@ namespace gcc } } - void generic_visitor::visit(source::variable_expression *expression) + void generic_visitor::visit(boot::variable_expression *expression) { auto symbol = this->symbol_map->lookup(expression->name()); @@ -613,7 +613,7 @@ namespace gcc this->current_expression = symbol->payload; } - void generic_visitor::visit(source::array_access_expression *expression) + void generic_visitor::visit(boot::array_access_expression *expression) { expression->base().accept(this); tree designator = this->current_expression; @@ -627,7 +627,7 @@ namespace gcc ARRAY_REF, element_type, designator, index, NULL_TREE, NULL_TREE); } - void generic_visitor::visit(source::field_access_expression *expression) + void generic_visitor::visit(boot::field_access_expression *expression) { expression->base().accept(this); tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression)); @@ -659,7 +659,7 @@ namespace gcc } } - void generic_visitor::visit(source::dereference_expression *expression) + void generic_visitor::visit(boot::dereference_expression *expression) { expression->base().accept(this); @@ -667,7 +667,7 @@ namespace gcc TREE_TYPE(TREE_TYPE(this->current_expression)), this->current_expression); } - void generic_visitor::visit(source::assign_statement *statement) + void generic_visitor::visit(boot::assign_statement *statement) { statement->lvalue().accept(this); @@ -699,7 +699,7 @@ namespace gcc this->current_expression = NULL_TREE; } - void generic_visitor::visit(source::if_statement *statement) + void generic_visitor::visit(boot::if_statement *statement) { tree endif_label_decl = build_label_decl("endif", UNKNOWN_LOCATION); tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl); @@ -723,7 +723,7 @@ namespace gcc this->current_expression = NULL_TREE; } - void generic_visitor::make_if_branch(source::conditional_statements& branch, tree goto_endif) + void generic_visitor::make_if_branch(boot::conditional_statements& branch, tree goto_endif) { branch.prerequisite().accept(this); @@ -767,7 +767,7 @@ namespace gcc return label_decl; } - void generic_visitor::visit(source::while_statement *statement) + void generic_visitor::visit(boot::while_statement *statement) { statement->body().prerequisite().accept(this); @@ -816,15 +816,15 @@ namespace gcc this->current_expression = NULL_TREE; } - void generic_visitor::visit(source::expression_statement *statement) + void generic_visitor::visit(boot::call_statement *statement) { statement->body().accept(this); append_to_statement_list(this->current_expression, &this->current_statements); } - void generic_visitor::visit(source::return_statement *statement) + void generic_visitor::visit(boot::return_statement *statement) { - source::expression *return_expression = statement->return_expression(); + boot::expression *return_expression = statement->return_expression(); if (return_expression == nullptr) { diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index f0fa4a1..fdae9a3 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -74,17 +74,17 @@ namespace gcc return m_block; } - std::shared_ptr> builtin_symbol_table() + std::shared_ptr> builtin_symbol_table() { - std::shared_ptr> initial_table = - std::make_shared>(); + std::shared_ptr> initial_table = + std::make_shared>(); - initial_table->enter("Int", source::make_info(integer_type_node)); - initial_table->enter("Word", source::make_info(unsigned_type_node)); - initial_table->enter("Bool", source::make_info(boolean_type_node)); - initial_table->enter("Float", source::make_info(double_type_node)); - initial_table->enter("Char", source::make_info(elna_char_type_node)); - initial_table->enter("String", source::make_info(elna_string_type_node)); + initial_table->enter("Int", boot::make_info(integer_type_node)); + initial_table->enter("Word", boot::make_info(unsigned_type_node)); + initial_table->enter("Bool", boot::make_info(boolean_type_node)); + initial_table->enter("Float", boot::make_info(double_type_node)); + initial_table->enter("Char", boot::make_info(elna_char_type_node)); + initial_table->enter("String", boot::make_info(elna_string_type_node)); return initial_table; } diff --git a/gcc/elna1.cc b/gcc/elna1.cc index 51d76e7..7b0f004 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -15,7 +15,7 @@ #include "common/common-target.h" #include -#include +#include #include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-generic.h" #include "elna/gcc/elna-diagnostic.h" @@ -84,8 +84,8 @@ static void elna_parse_file(const char *filename) fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); } - elna::source::driver driver{ filename }; - elna::source::lexer lexer(file); + elna::boot::driver driver{ filename }; + elna::boot::lexer lexer(file); yy::parser parser(lexer, driver); linemap_add(line_table, LC_ENTER, 0, filename, 1); diff --git a/include/elna/source/ast.h b/include/elna/boot/ast.h similarity index 97% rename from include/elna/source/ast.h rename to include/elna/boot/ast.h index bfb1ee7..fee9759 100644 --- a/include/elna/source/ast.h +++ b/include/elna/boot/ast.h @@ -7,11 +7,11 @@ #include #include #include -#include "elna/source/result.h" +#include "elna/boot/result.h" namespace elna { -namespace source +namespace boot { enum class binary_operator { @@ -47,7 +47,7 @@ namespace source class if_statement; class while_statement; class return_statement; - class expression_statement; + class call_statement; class block; class program; class binary_expression; @@ -77,7 +77,7 @@ namespace source virtual void visit(call_expression *) = 0; virtual void visit(cast_expression *) = 0; virtual void visit(size_of_expression *) = 0; - virtual void visit(expression_statement *) = 0; + virtual void visit(call_statement *) = 0; virtual void visit(assign_statement *) = 0; virtual void visit(if_statement *) = 0; virtual void visit(while_statement *) = 0; @@ -116,7 +116,7 @@ namespace source virtual void visit(call_expression *expression) override; virtual void visit(cast_expression *expression) override; virtual void visit(size_of_expression *expression) override; - virtual void visit(expression_statement *statement) override; + virtual void visit(call_statement *statement) override; virtual void visit(assign_statement *statement) override; virtual void visit(if_statement *) override; virtual void visit(while_statement *) override; @@ -458,17 +458,17 @@ namespace source virtual ~size_of_expression() override; }; - class expression_statement : public statement + class call_statement : public statement { - expression *m_body; + call_expression *m_body; public: - expression_statement(const struct position position, expression *body); + call_statement(const struct position position, call_expression *body); virtual void accept(parser_visitor *visitor) override; - expression& body(); + call_expression& body(); - virtual ~expression_statement() override; + virtual ~call_statement() override; }; /** diff --git a/include/elna/source/driver.h b/include/elna/boot/driver.h similarity index 95% rename from include/elna/source/driver.h rename to include/elna/boot/driver.h index de4dead..00c6e4f 100644 --- a/include/elna/source/driver.h +++ b/include/elna/boot/driver.h @@ -5,12 +5,12 @@ #include #include -#include "elna/source/ast.h" +#include "elna/boot/ast.h" #include "location.hh" namespace elna { -namespace source +namespace boot { position make_position(const yy::location& location); diff --git a/include/elna/source/result.h b/include/elna/boot/result.h similarity index 98% rename from include/elna/source/result.h rename to include/elna/boot/result.h index 94789f4..335f955 100644 --- a/include/elna/source/result.h +++ b/include/elna/boot/result.h @@ -8,7 +8,7 @@ namespace elna { -namespace source +namespace boot { /** * Position in the source text. diff --git a/include/elna/source/symbol.h b/include/elna/boot/symbol.h similarity index 99% rename from include/elna/source/symbol.h rename to include/elna/boot/symbol.h index bc6da9b..14c8cff 100644 --- a/include/elna/source/symbol.h +++ b/include/elna/boot/symbol.h @@ -10,7 +10,7 @@ namespace elna { -namespace source +namespace boot { /** * Generic language entity information. diff --git a/include/elna/gcc/elna-diagnostic.h b/include/elna/gcc/elna-diagnostic.h index 65fda53..08c56dd 100644 --- a/include/elna/gcc/elna-diagnostic.h +++ b/include/elna/gcc/elna-diagnostic.h @@ -6,13 +6,13 @@ #include "input.h" #include "tree.h" -#include "elna/source/result.h" +#include "elna/boot/result.h" namespace elna { namespace gcc { - location_t get_location(const elna::source::position *position); + location_t get_location(const boot::position *position); const char *print_type(tree type); } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 0ce0308..0a9776b 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -1,7 +1,7 @@ #pragma once -#include "elna/source/ast.h" -#include "elna/source/symbol.h" +#include "elna/boot/ast.h" +#include "elna/boot/symbol.h" #include "elna/gcc/elna-tree.h" #include "config.h" @@ -17,54 +17,54 @@ namespace elna { namespace gcc { - class generic_visitor final : public source::empty_visitor + class generic_visitor final : public boot::empty_visitor { tree current_statements{ NULL_TREE }; tree current_expression{ NULL_TREE }; - std::shared_ptr> symbol_map; + std::shared_ptr> symbol_map; tree main_fndecl{ NULL_TREE }; tree_chain variable_chain; tree build_label_decl(const char *name, location_t loc); - tree build_type(source::type_expression& type); + tree build_type(boot::type_expression& type); void enter_scope(); tree_symbol_mapping leave_scope(); - void build_binary_operation(bool condition, source::binary_expression *expression, + void build_binary_operation(bool condition, boot::binary_expression *expression, tree_code operator_code, tree left, tree right, tree target_type); - void make_if_branch(source::conditional_statements& branch, tree goto_endif); + void make_if_branch(boot::conditional_statements& branch, tree goto_endif); public: - generic_visitor(std::shared_ptr> symbol_table); + generic_visitor(std::shared_ptr> symbol_table); - void visit(source::program *program) override; - void visit(source::procedure_definition *definition) override; - void visit(source::call_expression *expression) override; - void visit(source::cast_expression *expression) override; - void visit(source::size_of_expression *expression) override; - void visit(source::number_literal *literal) override; - void visit(source::number_literal *literal) override; - void visit(source::number_literal *literal) override; - void visit(source::number_literal *boolean) override; - void visit(source::number_literal *character) override; - void visit(source::number_literal *) override; - void visit(source::string_literal *string) override; - void visit(source::binary_expression *expression) override; - void visit(source::unary_expression *expression) override; - void visit(source::constant_definition *definition) override; - void visit(source::type_definition *definition) override; - void visit(source::variable_declaration *declaration) override; - void visit(source::variable_expression *expression) override; - void visit(source::array_access_expression *expression) override; - void visit(source::field_access_expression *expression) override; - void visit(source::dereference_expression *expression) override; - void visit(source::assign_statement *statement) override; - void visit(source::if_statement *statement) override; - void visit(source::while_statement *statement) override; - void visit(source::expression_statement *statement) override; - void visit(source::return_statement *statement) override; + void visit(boot::program *program) override; + void visit(boot::procedure_definition *definition) override; + void visit(boot::call_expression *expression) override; + void visit(boot::cast_expression *expression) override; + void visit(boot::size_of_expression *expression) override; + void visit(boot::number_literal *literal) override; + void visit(boot::number_literal *literal) override; + void visit(boot::number_literal *literal) override; + void visit(boot::number_literal *boolean) override; + void visit(boot::number_literal *character) override; + void visit(boot::number_literal *) override; + void visit(boot::string_literal *string) override; + void visit(boot::binary_expression *expression) override; + void visit(boot::unary_expression *expression) override; + void visit(boot::constant_definition *definition) override; + void visit(boot::type_definition *definition) override; + void visit(boot::variable_declaration *declaration) override; + void visit(boot::variable_expression *expression) override; + void visit(boot::array_access_expression *expression) override; + void visit(boot::field_access_expression *expression) override; + void visit(boot::dereference_expression *expression) override; + void visit(boot::assign_statement *statement) override; + void visit(boot::if_statement *statement) override; + void visit(boot::while_statement *statement) override; + void visit(boot::call_statement *statement) override; + void visit(boot::return_statement *statement) override; }; } } diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index a3b6a8f..ead6f22 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -6,7 +6,7 @@ #include "tree.h" #include "tree.h" -#include "elna/source/symbol.h" +#include "elna/boot/symbol.h" enum elna_tree_index { @@ -60,6 +60,6 @@ namespace gcc tree block(); }; - std::shared_ptr> builtin_symbol_table(); + std::shared_ptr> builtin_symbol_table(); } } diff --git a/source/parser.yy b/source/parser.yy deleted file mode 100644 index 322fecd..0000000 --- a/source/parser.yy +++ /dev/null @@ -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 - #include - #include "elna/source/driver.h" - - #if !defined(yyFlexLexerOnce) - #include - #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 IDENTIFIER "identifier" -%token INTEGER "integer" -%token WORD "word" -%token FLOAT "float" -%token CHARACTER "character" -%token STRING "string" -%token 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 literal; -%type constant_definition; -%type > constant_part constant_definitions; -%type variable_declaration; -%type > variable_declarations variable_part - formal_parameter_list; -%type type_expression; -%type expression pointer summand factor comparand logical_operand; -%type > expressions actual_parameter_list; -%type designator_expression; -%type assign_statement; -%type call_expression; -%type while_statement; -%type if_statement; -%type return_statement; -%type statement; -%type > statements optional_statements; -%type procedure_definition; -%type > procedure_definitions procedure_part; -%type type_definition; -%type > type_definitions type_part; -%type block; -%type > field_declaration; -%type >> field_list; -%type > elsif_statement_list; -%type cast_expression; -%% -program: - type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT - { - std::vector definitions($1.size() + $3.size()); - std::vector::iterator definition = definitions.begin(); - std::vector value_definitions($2.size() + $4.size()); - std::vector::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 definitions($1.size() + $2.size()); - std::vector::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(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(elna::source::make_position(@1), $1); - } - | WORD - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - } - | FLOAT - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - } - | BOOLEAN - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - } - | CHARACTER - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1.at(0)); - } - | NIL - { - $$ = new elna::source::number_literal(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); -}