Rename elna::source to elna:boot
This commit is contained in:
		| @@ -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; | ||||
|     } | ||||
| @@ -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<elna::source::syntax_error>(message, input_file, loc)); | ||||
|         m_errors.emplace_back(std::make_unique<boot::syntax_error>(message, input_file, loc)); | ||||
|     } | ||||
| 
 | ||||
|     const std::list<std::unique_ptr<struct error>>& driver::errors() const noexcept | ||||
| @@ -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<char> escape = source::escape_char(yytext[2]); | ||||
|                             std::optional<char> 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<char> escape = source::escape_char(*current_position); | ||||
|                                     std::optional<char> escape = elna::boot::escape_char(*current_position); | ||||
|                                     if (escape.has_value()) | ||||
|                                     { | ||||
|                                         result.push_back(escape.value()); | ||||
							
								
								
									
										482
									
								
								boot/parser.yy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								boot/parser.yy
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <cstdint> | ||||
|     #include <iostream> | ||||
|     #include "elna/boot/driver.h" | ||||
|  | ||||
|     #if !defined(yyFlexLexerOnce) | ||||
|         #include <FlexLexer.h> | ||||
|     #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 <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 | ||||
|  | ||||
| %left OR AND | ||||
| %left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL | ||||
| %left PLUS MINUS | ||||
| %left MULTIPLICATION DIVISION REMAINDER | ||||
|  | ||||
| %type <elna::boot::literal *> literal; | ||||
| %type <elna::boot::constant_definition *> constant_definition; | ||||
| %type <std::vector<elna::boot::constant_definition *>> constant_part constant_definitions; | ||||
| %type <elna::boot::variable_declaration *> variable_declaration; | ||||
| %type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part | ||||
|     formal_parameter_list; | ||||
| %type <elna::boot::type_expression *> type_expression; | ||||
| %type <elna::boot::expression *> expression operand unary; | ||||
| %type <std::vector<elna::boot::expression *>> expressions actual_parameter_list; | ||||
| %type <elna::boot::designator_expression *> designator_expression; | ||||
| %type <elna::boot::assign_statement *> assign_statement; | ||||
| %type <elna::boot::call_expression *> call_expression; | ||||
| %type <elna::boot::while_statement *> while_statement; | ||||
| %type <elna::boot::if_statement *> if_statement; | ||||
| %type <elna::boot::return_statement *> return_statement; | ||||
| %type <elna::boot::statement *> statement; | ||||
| %type <std::vector<elna::boot::statement *>> statements optional_statements; | ||||
| %type <elna::boot::procedure_definition *> procedure_definition; | ||||
| %type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part; | ||||
| %type <elna::boot::type_definition *> type_definition; | ||||
| %type <std::vector<elna::boot::type_definition *>> type_definitions type_part; | ||||
| %type <elna::boot::block *> block; | ||||
| %type <std::pair<std::string, elna::boot::type_expression *>> field_declaration; | ||||
| %type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> field_list; | ||||
| %type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list; | ||||
| %type <elna::boot::cast_expression *> cast_expression; | ||||
| %% | ||||
| program: | ||||
|     type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT | ||||
|         { | ||||
|             std::vector<elna::boot::definition *> definitions($1.size() + $3.size()); | ||||
|             std::vector<elna::boot::definition *>::iterator definition = definitions.begin(); | ||||
|             std::vector<elna::boot::definition *> value_definitions($2.size() + $4.size()); | ||||
|             std::vector<elna::boot::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::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<elna::boot::definition *> definitions($1.size() + $2.size()); | ||||
|             std::vector<elna::boot::definition *>::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<elna::boot::statement *>(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<std::int32_t>(elna::boot::make_position(@1), $1); | ||||
|         } | ||||
|     | WORD | ||||
|         { | ||||
|             $$ = new elna::boot::number_literal<std::uint32_t>(elna::boot::make_position(@1), $1); | ||||
|         } | ||||
|     | FLOAT | ||||
|         { | ||||
|             $$ = new elna::boot::number_literal<double>(elna::boot::make_position(@1), $1); | ||||
|         } | ||||
|     | BOOLEAN | ||||
|         { | ||||
|             $$ = new elna::boot::number_literal<bool>(elna::boot::make_position(@1), $1); | ||||
|         } | ||||
|     | CHARACTER | ||||
|         { | ||||
|             $$ = new elna::boot::number_literal<unsigned char>(elna::boot::make_position(@1), $1.at(0)); | ||||
|         } | ||||
|     | NIL | ||||
|         { | ||||
|             $$ = new elna::boot::number_literal<std::nullptr_t>(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); | ||||
| } | ||||
| @@ -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) | ||||
| @@ -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 $@ $< | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -16,12 +16,12 @@ namespace elna | ||||
| { | ||||
| namespace gcc | ||||
| { | ||||
|     generic_visitor::generic_visitor(std::shared_ptr<source::symbol_table<tree>> symbol_table) | ||||
|     generic_visitor::generic_visitor(std::shared_ptr<boot::symbol_table<tree>> 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<tree> 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<source::symbol_table<tree>>(this->symbol_map); | ||||
|         this->symbol_map = std::make_shared<boot::symbol_table<tree>>(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<std::int32_t> *literal) | ||||
|     void generic_visitor::visit(boot::number_literal<std::int32_t> *literal) | ||||
|     { | ||||
|         this->current_expression = build_int_cst(integer_type_node, literal->number()); | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(source::number_literal<std::uint32_t> *literal) | ||||
|     void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal) | ||||
|     { | ||||
|         this->current_expression = build_int_cstu(unsigned_type_node, literal->number()); | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(source::number_literal<double> *literal) | ||||
|     void generic_visitor::visit(boot::number_literal<double> *literal) | ||||
|     { | ||||
|         REAL_VALUE_TYPE real_value1; | ||||
|  | ||||
| @@ -226,27 +226,27 @@ namespace gcc | ||||
|         mpfr_clear(number); | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(source::number_literal<bool> *boolean) | ||||
|     void generic_visitor::visit(boot::number_literal<bool> *boolean) | ||||
|     { | ||||
|         this->current_expression = build_int_cst_type(boolean_type_node, boolean->number()); | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(source::number_literal<unsigned char> *character) | ||||
|     void generic_visitor::visit(boot::number_literal<unsigned char> *character) | ||||
|     { | ||||
|         this->current_expression = build_int_cstu(elna_char_type_node, character->number()); | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(source::number_literal<nullptr_t> *) | ||||
|     void generic_visitor::visit(boot::number_literal<nullptr_t> *) | ||||
|     { | ||||
|         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<std::string> 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<std::string> 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) | ||||
|         { | ||||
|   | ||||
| @@ -74,17 +74,17 @@ namespace gcc | ||||
|         return m_block; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<elna::source::symbol_table<tree>> builtin_symbol_table() | ||||
|     std::shared_ptr<boot::symbol_table<tree>> builtin_symbol_table() | ||||
|     { | ||||
|         std::shared_ptr<elna::source::symbol_table<tree>> initial_table = | ||||
|             std::make_shared<elna::source::symbol_table<tree>>(); | ||||
|         std::shared_ptr<boot::symbol_table<tree>> initial_table = | ||||
|             std::make_shared<boot::symbol_table<tree>>(); | ||||
|  | ||||
|         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; | ||||
|     } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
| #include "common/common-target.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <elna/source/driver.h> | ||||
| #include <elna/boot/driver.h> | ||||
| #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); | ||||
|   | ||||
| @@ -7,11 +7,11 @@ | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #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; | ||||
|     }; | ||||
| 
 | ||||
|     /**
 | ||||
| @@ -5,12 +5,12 @@ | ||||
| 
 | ||||
| #include <list> | ||||
| #include <optional> | ||||
| #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); | ||||
| 
 | ||||
| @@ -8,7 +8,7 @@ | ||||
| 
 | ||||
| namespace elna | ||||
| { | ||||
| namespace source | ||||
| namespace boot | ||||
| { | ||||
|     /**
 | ||||
|      * Position in the source text. | ||||
| @@ -10,7 +10,7 @@ | ||||
| 
 | ||||
| namespace elna | ||||
| { | ||||
| namespace source | ||||
| namespace boot | ||||
| { | ||||
|     /**
 | ||||
|      * Generic language entity information. | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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<source::symbol_table<tree>> symbol_map; | ||||
|         std::shared_ptr<boot::symbol_table<tree>> 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<source::symbol_table<tree>> symbol_table); | ||||
|         generic_visitor(std::shared_ptr<boot::symbol_table<tree>> 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<std::int32_t> *literal) override; | ||||
|         void visit(source::number_literal<std::uint32_t> *literal) override; | ||||
|         void visit(source::number_literal<double> *literal) override; | ||||
|         void visit(source::number_literal<bool> *boolean) override; | ||||
|         void visit(source::number_literal<unsigned char> *character) override; | ||||
|         void visit(source::number_literal<std::nullptr_t> *) 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<std::int32_t> *literal) override; | ||||
|         void visit(boot::number_literal<std::uint32_t> *literal) override; | ||||
|         void visit(boot::number_literal<double> *literal) override; | ||||
|         void visit(boot::number_literal<bool> *boolean) override; | ||||
|         void visit(boot::number_literal<unsigned char> *character) override; | ||||
|         void visit(boot::number_literal<std::nullptr_t> *) 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; | ||||
|     }; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -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<source::symbol_table<tree>> builtin_symbol_table(); | ||||
|     std::shared_ptr<boot::symbol_table<tree>> builtin_symbol_table(); | ||||
| } | ||||
| } | ||||
|   | ||||
							
								
								
									
										474
									
								
								source/parser.yy
									
									
									
									
									
								
							
							
						
						
									
										474
									
								
								source/parser.yy
									
									
									
									
									
								
							| @@ -1,474 +0,0 @@ | ||||
| /* | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public License | ||||
|  * v. 2.0. If a copy of the MPL was not distributed with this file, You can | ||||
|  * obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| %require "3.2" | ||||
| %language "c++" | ||||
|  | ||||
| %code requires { | ||||
|     #include <cstdint> | ||||
|     #include <iostream> | ||||
|     #include "elna/source/driver.h" | ||||
|  | ||||
|     #if !defined(yyFlexLexerOnce) | ||||
|         #include <FlexLexer.h> | ||||
|     #endif | ||||
|  | ||||
|     namespace elna::source | ||||
|     { | ||||
|     class lexer; | ||||
|     } | ||||
| } | ||||
|  | ||||
| %code provides { | ||||
|     namespace elna::source | ||||
|     { | ||||
|  | ||||
|     class lexer: public yyFlexLexer | ||||
|     { | ||||
|     public: | ||||
|         yy::location location; | ||||
|  | ||||
|         lexer(std::istream& arg_yyin) | ||||
|             : yyFlexLexer(&arg_yyin) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         yy::parser::symbol_type lex(elna::source::driver& driver); | ||||
|     }; | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| %define api.token.raw | ||||
| %define api.token.constructor | ||||
| %define api.value.type variant | ||||
|  | ||||
| %parse-param {elna::source::lexer& lexer} | ||||
| %param {elna::source::driver& driver} | ||||
| %locations | ||||
|  | ||||
| %header | ||||
|  | ||||
| %code { | ||||
|     #define yylex lexer.lex | ||||
| } | ||||
| %start program; | ||||
|  | ||||
| %token <std::string> IDENTIFIER "identifier" | ||||
| %token <std::int32_t> INTEGER "integer" | ||||
| %token <std::uint32_t> WORD "word" | ||||
| %token <float> FLOAT "float" | ||||
| %token <std::string> CHARACTER "character" | ||||
| %token <std::string> STRING "string" | ||||
| %token <bool> BOOLEAN | ||||
| %token IF WHILE DO THEN ELSE ELSIF RETURN | ||||
| %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION | ||||
| %token BEGIN_BLOCK END_BLOCK EXTERN | ||||
| %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA | ||||
| %token AND OR NOT CAST AS SIZEOF | ||||
| %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS | ||||
| %token PLUS MINUS MULTIPLICATION DIVISION REMAINDER | ||||
| %token ASSIGNMENT COLON HAT AT NIL | ||||
|  | ||||
| %type <elna::source::literal *> literal; | ||||
| %type <elna::source::constant_definition *> constant_definition; | ||||
| %type <std::vector<elna::source::constant_definition *>> constant_part constant_definitions; | ||||
| %type <elna::source::variable_declaration *> variable_declaration; | ||||
| %type <std::vector<elna::source::variable_declaration *>> variable_declarations variable_part | ||||
|     formal_parameter_list; | ||||
| %type <elna::source::type_expression *> type_expression; | ||||
| %type <elna::source::expression *> expression pointer summand factor comparand logical_operand; | ||||
| %type <std::vector<elna::source::expression *>> expressions actual_parameter_list; | ||||
| %type <elna::source::designator_expression *> designator_expression; | ||||
| %type <elna::source::assign_statement *> assign_statement; | ||||
| %type <elna::source::call_expression *> call_expression; | ||||
| %type <elna::source::while_statement *> while_statement; | ||||
| %type <elna::source::if_statement *> if_statement; | ||||
| %type <elna::source::return_statement *> return_statement; | ||||
| %type <elna::source::statement *> statement; | ||||
| %type <std::vector<elna::source::statement *>> statements optional_statements; | ||||
| %type <elna::source::procedure_definition *> procedure_definition; | ||||
| %type <std::vector<elna::source::procedure_definition *>> procedure_definitions procedure_part; | ||||
| %type <elna::source::type_definition *> type_definition; | ||||
| %type <std::vector<elna::source::type_definition *>> type_definitions type_part; | ||||
| %type <elna::source::block *> block; | ||||
| %type <std::pair<std::string, elna::source::type_expression *>> field_declaration; | ||||
| %type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list; | ||||
| %type <std::vector<elna::source::conditional_statements *>> elsif_statement_list; | ||||
| %type <elna::source::cast_expression *> cast_expression; | ||||
| %% | ||||
| program: | ||||
|     type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT | ||||
|         { | ||||
|             std::vector<elna::source::definition *> definitions($1.size() + $3.size()); | ||||
|             std::vector<elna::source::definition *>::iterator definition = definitions.begin(); | ||||
|             std::vector<elna::source::definition *> value_definitions($2.size() + $4.size()); | ||||
|             std::vector<elna::source::definition *>::iterator value_definition = value_definitions.begin(); | ||||
|  | ||||
|             for (auto type : $1) | ||||
|             { | ||||
|                 *definition++ = type; | ||||
|             } | ||||
|             for (auto constant : $2) | ||||
|             { | ||||
|                 *value_definition++ = constant; | ||||
|             } | ||||
|             for (auto procedure : $3) | ||||
|             { | ||||
|                 *definition++ = procedure; | ||||
|             } | ||||
|             for (auto variable : $4) | ||||
|             { | ||||
|                 *value_definition++ = variable; | ||||
|             } | ||||
|             auto tree = new elna::source::program(elna::source::make_position(@5), | ||||
|                  std::move(definitions), std::move(value_definitions), std::move($6)); | ||||
|  | ||||
|             driver.tree.reset(tree); | ||||
|         } | ||||
| block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK | ||||
|         { | ||||
|             std::vector<elna::source::definition *> definitions($1.size() + $2.size()); | ||||
|             std::vector<elna::source::definition *>::iterator definition = definitions.begin(); | ||||
|  | ||||
|             for (auto constant : $1) | ||||
|             { | ||||
|                 *definition++ = constant; | ||||
|             } | ||||
|             for (auto variable : $2) | ||||
|             { | ||||
|                 *definition++ = variable; | ||||
|             } | ||||
|             $$ = new elna::source::block(elna::source::make_position(@3), | ||||
|                  std::move(definitions), std::move($4)); | ||||
|         } | ||||
| procedure_definition: | ||||
|     PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON | ||||
|         { | ||||
|             $$ = new elna::source::procedure_definition(elna::source::make_position(@1), | ||||
|                  $2, std::move($3), nullptr, $5); | ||||
|         } | ||||
|     | PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON | ||||
|         { | ||||
|             $$ = new elna::source::procedure_definition(elna::source::make_position(@1), | ||||
|                  $2, std::move($3), nullptr, nullptr); | ||||
|         } | ||||
|     | PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON block SEMICOLON | ||||
|         { | ||||
|             $$ = new elna::source::procedure_definition(elna::source::make_position(@1), | ||||
|                  $2, std::move($3), $5, $7); | ||||
|         } | ||||
|     | PROCEDURE IDENTIFIER formal_parameter_list COLON type_expression SEMICOLON EXTERN SEMICOLON | ||||
|         { | ||||
|             $$ = new elna::source::procedure_definition(elna::source::make_position(@1), | ||||
|                  $2, std::move($3), $5, nullptr); | ||||
|         } | ||||
| procedure_definitions: | ||||
|     procedure_definition procedure_definitions | ||||
|         { | ||||
|             std::swap($$, $2); | ||||
|             $$.emplace($$.cbegin(), std::move($1)); | ||||
|         } | ||||
|     | procedure_definition { $$.emplace_back(std::move($1)); } | ||||
| procedure_part: | ||||
|     /* no procedure definitions */ {} | ||||
|     | procedure_definitions { std::swap($$, $1); } | ||||
| assign_statement: designator_expression ASSIGNMENT expression | ||||
|         { | ||||
|             $$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3); | ||||
|         } | ||||
| call_expression: IDENTIFIER actual_parameter_list | ||||
|         { | ||||
|             $$ = new elna::source::call_expression(elna::source::make_position(@1), $1); | ||||
|             std::swap($$->arguments(), $2); | ||||
|         } | ||||
| cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN | ||||
|         { | ||||
|             $$ = new elna::source::cast_expression(elna::source::make_position(@1), $5, $3); | ||||
|         } | ||||
| while_statement: WHILE expression DO optional_statements END_BLOCK | ||||
|         { | ||||
|             auto body = new elna::source::conditional_statements($2); | ||||
|             std::swap($4, body->statements); | ||||
|             $$ = new elna::source::while_statement(elna::source::make_position(@1), body); | ||||
|         } | ||||
| elsif_statement_list: | ||||
|     ELSIF expression THEN optional_statements elsif_statement_list | ||||
|         { | ||||
|             elna::source::conditional_statements *branch = new elna::source::conditional_statements($2); | ||||
|             std::swap(branch->statements, $4); | ||||
|             std::swap($5, $$); | ||||
|             $$.emplace($$.begin(), branch); | ||||
|         } | ||||
|     | {} | ||||
| if_statement: | ||||
|     IF expression THEN optional_statements elsif_statement_list END_BLOCK | ||||
|         { | ||||
|             auto then = new elna::source::conditional_statements($2); | ||||
|             std::swap($4, then->statements); | ||||
|             $$ = new elna::source::if_statement(elna::source::make_position(@1), then); | ||||
|             std::swap($5, $$->branches); | ||||
|         } | ||||
|     | IF expression THEN optional_statements elsif_statement_list ELSE optional_statements END_BLOCK | ||||
|         { | ||||
|             auto then = new elna::source::conditional_statements($2); | ||||
|             std::swap($4, then->statements); | ||||
|             auto _else = new std::vector<elna::source::statement *>(std::move($7)); | ||||
|             $$ = new elna::source::if_statement(elna::source::make_position(@1), then, _else); | ||||
|             std::swap($5, $$->branches); | ||||
|         } | ||||
| return_statement: | ||||
|     RETURN expression | ||||
|         { | ||||
|             $$ = new elna::source::return_statement(elna::source::make_position(@1), $2); | ||||
|         } | ||||
| literal: | ||||
|     INTEGER | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1); | ||||
|         } | ||||
|     | WORD | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<std::uint32_t>(elna::source::make_position(@1), $1); | ||||
|         } | ||||
|     | FLOAT | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1); | ||||
|         } | ||||
|     | BOOLEAN | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<bool>(elna::source::make_position(@1), $1); | ||||
|         } | ||||
|     | CHARACTER | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<unsigned char>(elna::source::make_position(@1), $1.at(0)); | ||||
|         } | ||||
|     | NIL | ||||
|         { | ||||
|             $$ = new elna::source::number_literal<std::nullptr_t>(elna::source::make_position(@1), nullptr); | ||||
|         } | ||||
|     | STRING | ||||
|         { | ||||
|             $$ = new elna::source::string_literal(elna::source::make_position(@1), $1); | ||||
|         } | ||||
| pointer: | ||||
|     literal { $$ = $1; } | ||||
|     | designator_expression { $$ = $1; } | ||||
|     | SIZEOF LEFT_PAREN type_expression RIGHT_PAREN | ||||
|         { | ||||
|             $$ = new elna::source::size_of_expression(elna::source::make_position(@1), $3); | ||||
|         } | ||||
|     | cast_expression { $$ = $1; } | ||||
|     | call_expression { $$ = $1; } | ||||
|     | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; } | ||||
| summand: | ||||
|     factor { $$ = std::move($1); } | ||||
|     | factor MULTIPLICATION factor | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::multiplication); | ||||
|         } | ||||
|     | factor DIVISION factor | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::division); | ||||
|         } | ||||
|     | factor REMAINDER factor | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::remainder); | ||||
|         } | ||||
| factor: | ||||
|     AT pointer | ||||
|         { | ||||
|             $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, | ||||
|                 elna::source::unary_operator::reference); | ||||
|         } | ||||
|     | NOT pointer | ||||
|         { | ||||
|             $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, | ||||
|                 elna::source::unary_operator::negation); | ||||
|         } | ||||
|     | pointer { $$ = $1; } | ||||
| comparand: | ||||
|     summand PLUS summand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::sum); | ||||
|         } | ||||
|     | summand MINUS summand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::subtraction); | ||||
|         } | ||||
|     | summand { $$ = std::move($1); } | ||||
| logical_operand: | ||||
|     comparand EQUALS comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::equals); | ||||
|         } | ||||
|     | comparand NOT_EQUAL comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::not_equals); | ||||
|         } | ||||
|     | comparand LESS_THAN comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::less); | ||||
|         } | ||||
|     | comparand GREATER_THAN comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::greater); | ||||
|         } | ||||
|     | comparand LESS_EQUAL comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::less_equal); | ||||
|         } | ||||
|     | comparand GREATER_EQUAL comparand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::greater_equal); | ||||
|         } | ||||
|     | comparand { $$ = $1; } | ||||
| expression: | ||||
|     logical_operand AND logical_operand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::conjunction); | ||||
|         } | ||||
|     | logical_operand OR logical_operand | ||||
|         { | ||||
|             $$ = new elna::source::binary_expression(elna::source::make_position(@2), $1, $3, | ||||
|                 elna::source::binary_operator::disjunction); | ||||
|         } | ||||
|     | logical_operand { $$ = $1; } | ||||
| expressions: | ||||
|     expression COMMA expressions | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), $1); | ||||
|         } | ||||
|     | expression { $$.emplace_back(std::move($1)); } | ||||
| designator_expression: | ||||
|     designator_expression LEFT_SQUARE expression RIGHT_SQUARE | ||||
|         { | ||||
|             $$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3); | ||||
|         } | ||||
|     | designator_expression DOT IDENTIFIER | ||||
|         { | ||||
|             $$ = new elna::source::field_access_expression(elna::source::make_position(@2), $1, $3); | ||||
|         } | ||||
|     | designator_expression HAT | ||||
|         { | ||||
|             $$ = new elna::source::dereference_expression(elna::source::make_position(@1), $1); | ||||
|         } | ||||
|     | IDENTIFIER | ||||
|         { | ||||
|             $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); | ||||
|         } | ||||
| statement: | ||||
|     assign_statement { $$ = $1; } | ||||
|     | while_statement { $$ = $1; } | ||||
|     | if_statement { $$ = $1; } | ||||
|     | return_statement { $$ = $1; } | ||||
|     | expression { $$ = new elna::source::expression_statement(elna::source::make_position(@1), $1); } | ||||
| statements: | ||||
|     statement SEMICOLON statements | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), $1); | ||||
|         } | ||||
|     | statement { $$.push_back($1); } | ||||
| optional_statements: | ||||
|     statements { std::swap($$, $1); } | ||||
|     | /* no statements */ {} | ||||
| field_declaration: | ||||
|     IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); } | ||||
| field_list: | ||||
|     field_declaration SEMICOLON field_list | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), $1); | ||||
|         } | ||||
|     | field_declaration { $$.emplace_back($1); } | ||||
| type_expression: | ||||
|     ARRAY INTEGER OF type_expression | ||||
|         { | ||||
|             $$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2); | ||||
|         } | ||||
|     | POINTER TO type_expression | ||||
|         { | ||||
|             $$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $3); | ||||
|         } | ||||
|     | RECORD field_list END_BLOCK | ||||
|         { | ||||
|             $$ = new elna::source::record_type_expression(elna::source::make_position(@1), std::move($2)); | ||||
|         } | ||||
|     | UNION field_list END_BLOCK | ||||
|         { | ||||
|             $$ = new elna::source::union_type_expression(elna::source::make_position(@1), std::move($2)); | ||||
|         } | ||||
|     | IDENTIFIER | ||||
|         { | ||||
|             $$ = new elna::source::basic_type_expression(elna::source::make_position(@1), $1); | ||||
|         } | ||||
| variable_declaration: IDENTIFIER COLON type_expression | ||||
|         { | ||||
|             $$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3); | ||||
|         } | ||||
| variable_declarations: | ||||
|     variable_declaration COMMA variable_declarations | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), $1); | ||||
|         } | ||||
|     | variable_declaration { $$.emplace_back(std::move($1)); } | ||||
| variable_part: | ||||
|     /* no variable declarations */ {} | ||||
|     | VAR variable_declarations SEMICOLON { std::swap($$, $2); } | ||||
| constant_definition: IDENTIFIER EQUALS literal | ||||
|         { | ||||
|             $$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3); | ||||
|         } | ||||
| constant_definitions: | ||||
|     constant_definition COMMA constant_definitions | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), std::move($1)); | ||||
|         } | ||||
|     | constant_definition { $$.emplace_back(std::move($1)); } | ||||
| constant_part: | ||||
|     /* no constant definitions */ {} | ||||
|     | CONST constant_definitions SEMICOLON { std::swap($$, $2); } | ||||
| type_definition: IDENTIFIER EQUALS type_expression | ||||
|         { | ||||
|             $$ = new elna::source::type_definition(elna::source::make_position(@1), $1, $3); | ||||
|         } | ||||
| type_definitions: | ||||
|     type_definition COMMA type_definitions | ||||
|         { | ||||
|             std::swap($$, $3); | ||||
|             $$.emplace($$.cbegin(), std::move($1)); | ||||
|         } | ||||
|     | type_definition { $$.emplace_back(std::move($1)); } | ||||
| type_part: | ||||
|     /* no type definitions */ {} | ||||
|     | TYPE type_definitions SEMICOLON { std::swap($$, $2); } | ||||
| formal_parameter_list: | ||||
|     LEFT_PAREN RIGHT_PAREN {} | ||||
|     | LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); } | ||||
| actual_parameter_list: | ||||
|     LEFT_PAREN RIGHT_PAREN {} | ||||
|     | LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); } | ||||
| %% | ||||
|  | ||||
| void yy::parser::error(const location_type& loc, const std::string& message) | ||||
| { | ||||
|     driver.error(loc, message); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user