From 4011adbe2bf1d25be777359eb32163123d96f04b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 31 Jan 2025 09:46:17 +0100 Subject: [PATCH] Rename elna::source to elna:boot --- {source => boot}/ast.cc | 14 +- {source => boot}/driver.cc | 6 +- {source => boot}/lexer.ll | 8 +- boot/parser.yy | 482 +++++++++++++++++++++++++ {source => boot}/result.cc | 4 +- example.elna | 131 +++++-- gcc/Make-lang.in | 6 +- gcc/elna-diagnostic.cc | 2 +- gcc/elna-generic.cc | 144 ++++---- gcc/elna-tree.cc | 24 +- gcc/elna1.cc | 6 +- include/elna/{source => boot}/ast.h | 20 +- include/elna/{source => boot}/driver.h | 4 +- include/elna/{source => boot}/result.h | 2 +- include/elna/{source => boot}/symbol.h | 2 +- include/elna/gcc/elna-diagnostic.h | 4 +- include/elna/gcc/elna-generic.h | 70 ++-- include/elna/gcc/elna-tree.h | 5 +- source/parser.yy | 474 ------------------------ 19 files changed, 754 insertions(+), 654 deletions(-) rename {source => boot}/ast.cc (98%) rename {source => boot}/driver.cc (93%) rename {source => boot}/lexer.ll (97%) create mode 100644 boot/parser.yy rename {source => boot}/result.cc (91%) rename include/elna/{source => boot}/ast.h (97%) rename include/elna/{source => boot}/driver.h (95%) rename include/elna/{source => boot}/result.h (98%) rename include/elna/{source => boot}/symbol.h (99%) delete mode 100644 source/parser.yy 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/example.elna b/example.elna index 67fa872..df467ae 100644 --- a/example.elna +++ b/example.elna @@ -1,12 +1,22 @@ type + Position = record + line: Word; + column: Word + end, + Location = record + first: Position; + last: Position + end, TokenValue = union int_value: Int; string_value: pointer to Char; - boolean_value: Bool + boolean_value: Bool; + char_value: Char end, Token = record kind: Int; - value: TokenValue + value: TokenValue; + location: Location end, FILE = record dummy: Int @@ -27,7 +37,8 @@ const TOKEN_SEMICOLON = 40, TOKEN_DOT = 41, TOKEN_COMMA = 42, TOKEN_PLUS = 43, TOKEN_MINUS = 44, TOKEN_MULTIPLICATION = 45, TOKEN_DIVISION = 46, TOKEN_REMAINDER = 47, TOKEN_ASSIGNMENT = 48, TOKEN_COLON = 49, TOKEN_HAT = 50, - TOKEN_AT = 51, TOKEN_COMMENT = 52, TOKEN_INTEGER = 53; + TOKEN_AT = 51, TOKEN_COMMENT = 52, TOKEN_INTEGER = 53, TOKEN_WORD = 54, + TOKEN_CHARACTER = 55; (* External procedures. @@ -42,7 +53,7 @@ proc write(fd: Int, buf: pointer to Char, count: Int): Int; extern; proc malloc(size: Int): pointer to Char; extern; proc free(ptr: pointer to Char); extern; proc calloc(nmemb: Int, size: Int): pointer to Char; extern; -proc realloc(ptr: pointer to Char, size: Int): pointer to Char; extern; +proc realloc(ptr: pointer to Char, size: Word): pointer to Char; extern; proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern; @@ -85,6 +96,9 @@ begin n := 9; buffer[9] := '0'; + if value = 0 then + write_c('0') + end; while value <> 0 do digit := value % 10; value := value / 10; @@ -120,7 +134,7 @@ end; proc is_space(c: Char): Bool; begin - return c = ' ' or c = '\n' + return c = ' ' or c = '\n' or c = '\t' end; (* @@ -171,6 +185,49 @@ begin return input end; +proc escape_char(escape: Char, result: pointer to Char): Bool; +begin + if escape = 'n' then + result^ := '\n'; + return true + elsif escape = 'a' then + result^ := '\a'; + return true + elsif escape = 'b' then + result^ := '\b'; + return true + elsif escape = 't' then + result^ := '\t'; + return true + elsif escape = 'f' then + result^ := '\f'; + return true + elsif escape = 'r' then + result^ := '\r'; + return true + elsif escape = 'v' then + result^ := '\v'; + return true + elsif escape = '\\' then + result^ := '\\'; + return true + elsif escape = '\'' then + result^ := '\''; + return true + elsif escape = '"' then + result^ := '"'; + return true + elsif escape = '?' then + result^ := '\?'; + return true + elsif escape = '0' then + result^ := '\0'; + return true + else + return false + end +end; + proc skip_spaces(input: pointer to Char): pointer to Char; begin while is_space(input^) do @@ -203,12 +260,12 @@ begin return nil end; -proc print_tokens(tokens: pointer to Token, tokens_size: Int); +proc print_tokens(tokens: pointer to Token, tokens_size: Word); var current_token: pointer to Token, - i: Int; + i: Word; begin - i := 0; + i := 0u; while i < tokens_size do current_token := tokens + i; @@ -295,35 +352,43 @@ begin elsif current_token^.kind = TOKEN_NOT_EQUAL then write_s("<>") elsif current_token^.kind = TOKEN_SEMICOLON then - write_s(";") + write_c(';') elsif current_token^.kind = TOKEN_DOT then - write_s(".") + write_c('.') elsif current_token^.kind = TOKEN_COMMA then - write_s(",") + write_c(',') elsif current_token^.kind = TOKEN_PLUS then - write_s("+") + write_c('+') elsif current_token^.kind = TOKEN_MINUS then - write_s("-") + write_c('-') elsif current_token^.kind = TOKEN_MULTIPLICATION then - write_s("*") + write_c('*') elsif current_token^.kind = TOKEN_DIVISION then - write_s("/") + write_c('/') elsif current_token^.kind = TOKEN_REMAINDER then - write_s("%") + write_c('%') elsif current_token^.kind = TOKEN_ASSIGNMENT then write_s(":=") elsif current_token^.kind = TOKEN_COLON then - write_s(":") + write_c(':') elsif current_token^.kind = TOKEN_HAT then - write_s("^") + write_c('^') elsif current_token^.kind = TOKEN_AT then - write_s("@") + write_c('@') elsif current_token^.kind = TOKEN_COMMENT then write_s("COMMENT") elsif current_token^.kind = TOKEN_INTEGER then write_c('<'); write_i(current_token^.value.int_value); write_c('>') + elsif current_token^.kind = TOKEN_WORD then + write_c('<'); + write_i(current_token^.value.int_value); + write_s("u>") + elsif current_token^.kind = TOKEN_CHARACTER then + write_c('<'); + write_i(current_token^.value.char_value); + write_s("c>") else write_s("UNKNOWN<"); write_i(current_token^.kind); @@ -416,9 +481,9 @@ var token_length: Int, tokens: pointer to Token, current_token: pointer to Token, - tokens_size: Int; + tokens_size: Word; begin - tokens_size := 0; + tokens_size := 0u; tokens := cast(nil as pointer to Token); input := read_source("example.elna"); @@ -439,8 +504,14 @@ begin elsif is_digit(input_pointer^) then token_end := cast(nil as pointer to Char); current_token^.value.int_value := strtol(input_pointer, @token_end, 10); - current_token^.kind := TOKEN_INTEGER; - input_pointer := token_end + + if token_end^ = 'u' then + current_token^.kind := TOKEN_WORD; + input_pointer := token_end + 1 + else + current_token^.kind := TOKEN_INTEGER; + input_pointer := token_end + end elsif input_pointer^ = '(' then input_pointer := input_pointer + 1; if input_pointer^ = '*' then @@ -462,6 +533,20 @@ begin elsif input_pointer^ = ')' then current_token^.kind := TOKEN_RIGHT_PAREN; input_pointer := input_pointer + 1 + elsif input_pointer^ = '\'' then + input_pointer := input_pointer + 1; + if input_pointer^ = '\\' then + input_pointer := input_pointer + 1; + if escape_char(input_pointer^, @current_token^.value.char_value) then + input_pointer := input_pointer + 1 + end + elsif input_pointer^ <> '\0' then + current_token^.value.char_value := input_pointer^ + end; + if input_pointer^ = '\'' then + current_token^.kind := TOKEN_CHARACTER; + input_pointer := input_pointer + 1 + end elsif input_pointer^ = '[' then current_token^.kind := TOKEN_LEFT_SQUARE; input_pointer := input_pointer + 1 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..acdc10f 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,23 @@ 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)); + this->current_expression = build1(CONVERT_EXPR, + this->symbol_map->lookup("Word")->payload, TYPE_SIZE_UNIT(body_type)); } - void generic_visitor::visit(source::program *program) + bool generic_visitor::is_integral_type(tree type) + { + gcc_assert(TYPE_P(type)); + + return type == this->symbol_map->lookup("Int")->payload + || type == this->symbol_map->lookup("Word")->payload; + } + + void generic_visitor::visit(boot::program *program) { for (const auto definition : program->value_definitions) { @@ -119,7 +128,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 +142,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 +164,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 +196,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 +210,21 @@ 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()); + auto symbol = this->symbol_map->lookup("Int"); + + this->current_expression = build_int_cst(symbol->payload, 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()); + auto symbol = this->symbol_map->lookup("Word"); + + this->current_expression = build_int_cstu(symbol->payload, 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 +239,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 +276,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; @@ -282,9 +295,8 @@ namespace gcc tree_code operator_code = ERROR_MARK; tree target_type = error_mark_node; - if (is_pointer_type(left_type) - && (right_type == integer_type_node || right_type == unsigned_type_node) - && expression->operation() == source::binary_operator::sum) + if (is_pointer_type(left_type) && is_integral_type(right_type) + && expression->operation() == boot::binary_operator::sum) { tree convert_expression = build1_loc(expression_location, CONVERT_EXPR, sizetype, right); @@ -297,45 +309,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; @@ -344,17 +356,17 @@ namespace gcc } if (operator_code != ERROR_MARK) // An arithmetic operation. { - build_binary_operation(left_type == integer_type_node || left_type == double_type_node, + build_binary_operation(is_integral_type(left_type) || left_type == double_type_node, expression, operator_code, left, right, target_type); return; } 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 +381,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 +399,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 +447,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 +458,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 +477,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 +492,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 +506,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 +516,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 +548,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 +583,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 +591,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 +610,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 +625,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 +639,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 +671,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 +679,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 +711,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 +735,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 +779,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 +828,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..92c96ea 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -28,12 +28,6 @@ namespace gcc && TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node; } - bool is_integral_type(tree type) - { - gcc_assert(TYPE_P(type)); - return type == integer_type_node || type == unsigned_type_node; - } - tree tree_chain_base::head() { return first; @@ -74,17 +68,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(long_integer_type_node)); + initial_table->enter("Word", boot::make_info(size_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..cc9c471 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,56 @@ 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); + + bool is_integral_type(tree type); 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..6674185 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 { @@ -27,7 +27,6 @@ namespace gcc void init_ttree(); bool is_pointer_type(tree type); bool is_string_type(tree type); - bool is_integral_type(tree type); class tree_chain_base { @@ -60,6 +59,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); -}