diff options
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/ast.cc | 86 | ||||
| -rw-r--r-- | frontend/lexer.ll | 6 | ||||
| -rw-r--r-- | frontend/parser.yy | 97 | ||||
| -rw-r--r-- | frontend/semantic.cc | 88 |
4 files changed, 162 insertions, 115 deletions
diff --git a/frontend/ast.cc b/frontend/ast.cc index e067937..9a1f96b 100644 --- a/frontend/ast.cc +++ b/frontend/ast.cc @@ -24,7 +24,7 @@ namespace elna::frontend __builtin_unreachable(); } - void empty_visitor::visit(named_type_expression *) + void empty_visitor::visit(type_expression *) { not_implemented(); } @@ -149,7 +149,7 @@ namespace elna::frontend not_implemented(); } - void empty_visitor::visit(variable_expression *) + void empty_visitor::visit(named_expression *) { not_implemented(); } @@ -253,12 +253,7 @@ namespace elna::frontend return nullptr; } - type_expression::type_expression(const struct position position) - : node(position) - { - } - - named_type_expression *type_expression::is_named() + named_expression *type_expression::is_named() { return nullptr; } @@ -293,24 +288,46 @@ namespace elna::frontend return nullptr; } - named_type_expression::named_type_expression(const struct position position, const std::string& name) - : type_expression(position), name(name) + void type_expression::accept(parser_visitor *visitor) { + if (named_expression *node = is_named()) + { + return visitor->visit(node); + } + else if (array_type_expression *node = is_array()) + { + return visitor->visit(node); + } + else if (pointer_type_expression *node = is_pointer()) + { + return visitor->visit(node); + } + else if (record_type_expression *node = is_record()) + { + return visitor->visit(node); + } + else if (union_type_expression *node = is_union()) + { + return visitor->visit(node); + } + else if (procedure_type_expression *node = is_procedure()) + { + return visitor->visit(node); + } + else if (enumeration_type_expression *node = is_enumeration()) + { + return visitor->visit(node); + } + __builtin_unreachable(); } - void named_type_expression::accept(parser_visitor *visitor) - { - visitor->visit(this); - } - - named_type_expression *named_type_expression::is_named() + type_expression::~type_expression() { - return this; } array_type_expression::array_type_expression(const struct position position, type_expression *base, const std::uint32_t size) - : type_expression(position), m_base(base), size(size) + : node(position), m_base(base), size(size) { } @@ -336,7 +353,7 @@ namespace elna::frontend pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base) - : type_expression(position), m_base(base) + : node(position), m_base(base) { } @@ -362,7 +379,7 @@ namespace elna::frontend record_type_expression::record_type_expression(const struct position position, std::vector<field_declaration>&& fields) - : type_expression(position), fields(std::move(fields)) + : node(position), fields(std::move(fields)) { } @@ -386,7 +403,7 @@ namespace elna::frontend union_type_expression::union_type_expression(const struct position position, std::vector<field_declaration>&& fields) - : type_expression(position), fields(std::move(fields)) + : node(position), fields(std::move(fields)) { } @@ -464,7 +481,7 @@ namespace elna::frontend } procedure_type_expression::procedure_type_expression(const struct position position, return_t return_type) - : type_expression(position), return_type(return_type) + : node(position), return_type(return_type) { } @@ -491,7 +508,7 @@ namespace elna::frontend } enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members) - : type_expression(position), members(members) + : node(position), members(members) { } @@ -559,6 +576,11 @@ namespace elna::frontend { } + block::block(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables) + : m_variables(std::move(variables)), m_constants(std::move(constants)) + { + } + block::block(block&& that) : m_variables(std::move(that.m_variables)), m_constants(std::move(that.m_constants)), m_body(std::move(that.m_body)) @@ -657,10 +679,6 @@ namespace elna::frontend } } - literal_expression::literal_expression() - { - } - literal_expression *literal_expression::is_literal() { return this; @@ -684,10 +702,6 @@ namespace elna::frontend } } - designator_expression::designator_expression() - { - } - designator_expression::~designator_expression() { } @@ -699,7 +713,7 @@ namespace elna::frontend void designator_expression::accept(parser_visitor *visitor) { - if (variable_expression *node = is_variable()) + if (named_expression *node = is_named()) { return visitor->visit(node); } @@ -718,17 +732,17 @@ namespace elna::frontend __builtin_unreachable(); } - variable_expression::variable_expression(const struct position position, const std::string& name) + named_expression::named_expression(const struct position position, const std::string& name) : node(position), name(name) { } - void variable_expression::accept(parser_visitor *visitor) + void named_expression::accept(parser_visitor *visitor) { visitor->visit(this); } - variable_expression *variable_expression::is_variable() + named_expression *named_expression::is_named() { return this; } @@ -1039,7 +1053,7 @@ namespace elna::frontend visitor->visit(this); } - variable_expression *designator_expression::is_variable() + named_expression *designator_expression::is_named() { return nullptr; } diff --git a/frontend/lexer.ll b/frontend/lexer.ll index f14497b..7c18b32 100644 --- a/frontend/lexer.ll +++ b/frontend/lexer.ll @@ -130,12 +130,6 @@ or { return { return yy::parser::make_RETURN(this->location); } -module { - return yy::parser::make_MODULE(this->location); -} -program { - return yy::parser::make_PROGRAM(this->location); -} import { return yy::parser::make_IMPORT(this->location); } diff --git a/frontend/parser.yy b/frontend/parser.yy index bace8d7..5e3837b 100644 --- a/frontend/parser.yy +++ b/frontend/parser.yy @@ -102,8 +102,6 @@ along with GCC; see the file COPYING3. If not see ELSE "else" ELSIF "elsif" RETURN "return" - PROGRAM "program" - MODULE "module" IMPORT "import" BEGIN_BLOCK "begin" END_BLOCK "end" @@ -142,11 +140,12 @@ along with GCC; see the file COPYING3. If not see %type <elna::frontend::procedure_call*> call_expression; %type <elna::frontend::return_statement *> return_statement; %type <elna::frontend::statement *> statement; -%type <std::vector<elna::frontend::statement *>> required_statements optional_statements statement_part; +%type <std::vector<elna::frontend::statement *>> required_statements optional_statements; +%type <std::unique_ptr<std::vector<elna::frontend::statement *>>> statement_part; %type <elna::frontend::procedure_declaration *> procedure_declaration; %type <std::pair<std::vector<std::string>, elna::frontend::procedure_type_expression *>> procedure_heading; %type <elna::frontend::procedure_type_expression::return_t> return_declaration; -%type <std::vector<elna::frontend::procedure_declaration *>> procedure_declarations procedure_part; +%type <std::vector<elna::frontend::procedure_declaration *>> procedure_part; %type <elna::frontend::type_declaration *> type_declaration; %type <std::vector<elna::frontend::type_declaration *>> type_declarations type_part; %type <std::unique_ptr<elna::frontend::block>> block; @@ -162,43 +161,47 @@ along with GCC; see the file COPYING3. If not see %type <std::vector<elna::frontend::import_declaration *>> import_declarations import_part; %% program: - "program" ";" import_part constant_part type_part variable_part procedure_part statement_part "end" "." + import_part constant_part type_part variable_part procedure_part statement_part "end" "." { - auto tree = new frontend::program(frontend::make_position(@1)); - - std::swap(tree->imports, $3); - std::swap(tree->constants, $4); - std::swap(tree->types , $5); - std::swap(tree->variables, $6); - std::swap(tree->procedures, $7); - std::swap(tree->body, $8); - - driver.tree.reset(tree); - } - | "module" ";" import_part constant_part type_part variable_part procedure_part "end" "." - { - auto tree = new frontend::unit(frontend::make_position(@1)); - - std::swap(tree->imports, $3); - std::swap(tree->constants, $4); - std::swap(tree->types , $5); - std::swap(tree->variables, $6); - std::swap(tree->procedures, $7); + if ($6) + { + frontend::program *tree = new frontend::program(frontend::make_position(@1)); + std::swap(tree->body, *$6.release()); - driver.tree.reset(tree); + driver.tree.reset(tree); + } + else + { + driver.tree.reset(new frontend::unit(frontend::make_position(@1))); + } + std::swap(driver.tree->imports, $1); + std::swap(driver.tree->constants, $2); + std::swap(driver.tree->types , $3); + std::swap(driver.tree->variables, $4); + std::swap(driver.tree->procedures, $5); } block: constant_part variable_part statement_part "end" { - $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move($3)); + if ($3) + { + $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move(*$3.release())); + } + else + { + $$ = std::make_unique<frontend::block>(std::move($1), std::move($2)); + } } statement_part: /* no statements */ {} - | "begin" required_statements { std::swap($$, $2); } - | return_statement { $$.push_back($1); } + | "begin" required_statements { $$ = std::make_unique<std::vector<frontend::statement *>>(std::move($2));; } + | return_statement + { + $$ = std::make_unique<std::vector<frontend::statement *>>(std::vector<frontend::statement *>{ $1 }); + } | "begin" required_statements ";" return_statement { - std::swap($$, $2); - $$.push_back($4); + $$ = std::make_unique<std::vector<frontend::statement *>>(std::move($2)); + $$->push_back($4); } identifier_definition: IDENTIFIER "*" { $$ = frontend::identifier_definition{ $1, true }; } @@ -224,26 +227,24 @@ procedure_heading: formal_parameter_list return_declaration } } procedure_declaration: - "proc" identifier_definition procedure_heading ";" block ";" + "proc" identifier_definition procedure_heading block { - $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, std::move(*$5)); + $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, + std::move(*$4)); std::swap($3.first, $$->parameter_names); } - | "proc" identifier_definition procedure_heading ";" "extern" ";" + | "proc" identifier_definition procedure_heading "extern" { $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second); std::swap($3.first, $$->parameter_names); } -procedure_declarations: - procedure_declaration procedure_declarations +procedure_part: + /* no procedure declarations */ {} + | procedure_declaration procedure_part { std::swap($$, $2); $$.emplace($$.cbegin(), std::move($1)); } - | procedure_declaration { $$.emplace_back(std::move($1)); } -procedure_part: - /* no procedure definitions */ {} - | procedure_declarations { std::swap($$, $1); } call_expression: designator_expression actual_parameter_list { $$ = new frontend::procedure_call(frontend::make_position(@1), $1); @@ -401,7 +402,7 @@ designator_expression: | simple_expression "^" { $$ = new frontend::dereference_expression(frontend::make_position(@1), $1); } | IDENTIFIER - { $$ = new frontend::variable_expression(frontend::make_position(@1), $1); } + { $$ = new frontend::named_expression(frontend::make_position(@1), $1); } statement: designator_expression ":=" expression { $$ = new frontend::assign_statement(frontend::make_position(@1), $1, $3); } @@ -487,7 +488,7 @@ type_expression: } | IDENTIFIER { - $$ = new frontend::named_type_expression(frontend::make_position(@1), $1); + $$ = new frontend::named_expression(frontend::make_position(@1), $1); } identifiers: IDENTIFIER "," identifiers @@ -497,18 +498,18 @@ identifiers: } | IDENTIFIER { $$.emplace_back(std::move($1)); } variable_declaration: - identifier_definitions ":" type_expression ";" + identifier_definitions ":" type_expression { std::shared_ptr<frontend::type_expression> shared_type{ $3 }; $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type); } - | identifier_definitions ":" type_expression ":=" "extern" ";" + | identifier_definitions ":" type_expression ":=" "extern" { std::shared_ptr<frontend::type_expression> shared_type{ $3 }; $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, std::monostate{}); } - | identifier_definitions ":" type_expression ":=" expression ";" + | identifier_definitions ":" type_expression ":=" expression { std::shared_ptr<frontend::type_expression> shared_type{ $3 }; $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, $5); @@ -523,7 +524,7 @@ variable_declarations: variable_part: /* no variable declarations */ {} | "var" variable_declarations { std::swap($$, $2); } -constant_declaration: identifier_definition ":=" expression ";" +constant_declaration: identifier_definition ":=" expression { $$ = new frontend::constant_declaration(frontend::make_position(@1), std::move($1), $3); } @@ -556,8 +557,8 @@ import_declarations: } import_part: /* no import declarations */ {} - | "import" import_declarations ";" { std::swap($$, $2); } -type_declaration: identifier_definition "=" type_expression ";" + | "import" import_declarations { std::swap($$, $2); } +type_declaration: identifier_definition "=" type_expression { $$ = new frontend::type_declaration(frontend::make_position(@1), std::move($1), $3); } diff --git a/frontend/semantic.cc b/frontend/semantic.cc index 36c75b8..ee18492 100644 --- a/frontend/semantic.cc +++ b/frontend/semantic.cc @@ -223,10 +223,20 @@ namespace elna::frontend { visit(static_cast<unit *>(program)); + this->bag.enter(); + auto variable_type = this->bag.lookup("Int")->is_type()->symbol; + this->bag.enter("count", std::make_shared<variable_info>(variable_type, false)); + + variable_type = this->bag.lookup("Char")->is_type()->symbol; + variable_type = type(std::make_shared<pointer_type>(variable_type)); + variable_type = type(std::make_shared<pointer_type>(variable_type)); + this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false)); + for (statement *const statement : program->body) { statement->accept(this); } + this->bag.leave(); } void name_analysis_visitor::visit(type_declaration *definition) @@ -239,23 +249,8 @@ namespace elna::frontend this->bag.enter(definition->identifier.name, info); } - void name_analysis_visitor::visit(named_type_expression *type_expression) + void name_analysis_visitor::visit(type_expression *) { - auto unresolved_alias = this->bag.declared(type_expression->name); - - if (unresolved_alias != nullptr) - { - this->current_type = type(unresolved_alias); - } - else if (auto from_symbol_table = this->bag.lookup(type_expression->name)) - { - this->current_type = from_symbol_table->is_type()->symbol; - } - else - { - add_error<undeclared_error>(type_expression->name, this->input_file, type_expression->position()); - this->current_type = type(); - } } void name_analysis_visitor::visit(pointer_type_expression *type_expression) @@ -267,7 +262,9 @@ namespace elna::frontend void name_analysis_visitor::visit(array_type_expression *type_expression) { type_expression->base().accept(this); - this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size)); + auto result_type{ std::make_shared<array_type>(this->current_type, type_expression->size) }; + + this->current_type = type(result_type); } std::vector<type_field> name_analysis_visitor::build_composite_type(const std::vector<field_declaration>& fields) @@ -324,20 +321,27 @@ namespace elna::frontend this->current_type = type(result_type); } + std::shared_ptr<variable_info> name_analysis_visitor::register_variable(const std::string& name, + const bool is_extern, const struct position position) + { + auto variable_symbol = std::make_shared<variable_info>(this->current_type, is_extern); + + if (!this->bag.enter(name, variable_symbol)) + { + add_error<already_declared_error>(name, this->input_file, position); + } + return variable_symbol; + } + void name_analysis_visitor::visit(variable_declaration *declaration) { declaration->variable_type().accept(this); for (const auto& variable_identifier : declaration->identifiers) { - auto variable_symbol = std::make_shared<variable_info>(this->current_type, declaration->is_extern); - + auto variable_symbol = register_variable(variable_identifier.name, declaration->is_extern, + declaration->position()); variable_symbol->exported = variable_identifier.exported; - if (!this->bag.enter(variable_identifier.name, variable_symbol)) - { - add_error<already_declared_error>(variable_identifier.name, this->input_file, - declaration->position()); - } } } @@ -358,7 +362,19 @@ namespace elna::frontend if (definition->body.has_value()) { info = std::make_shared<procedure_info>(heading, definition->parameter_names, this->bag.enter()); + auto name_iterator = std::cbegin(definition->parameter_names); + auto type_iterator = std::cbegin(heading.parameters); + while (name_iterator != std::cend(definition->parameter_names) + && type_iterator != std::cend(heading.parameters)) + { + this->current_type = *type_iterator; + auto variable_symbol = register_variable(*name_iterator, false, definition->heading().position()); + variable_symbol->exported = false; + + ++name_iterator; + ++type_iterator; + } for (constant_declaration *const constant : definition->body.value().constants()) { constant->accept(this); @@ -489,6 +505,10 @@ namespace elna::frontend { variable->accept(this); } + for (constant_declaration *const constant : unit->constants) + { + constant->accept(this); + } for (procedure_declaration *const procedure : unit->procedures) { procedure->accept(this); @@ -522,8 +542,26 @@ namespace elna::frontend expression->operand().accept(this); } - void name_analysis_visitor::visit(variable_expression *) + void name_analysis_visitor::visit(named_expression *type_expression) { + auto unresolved_alias = this->bag.declared(type_expression->name); + + if (unresolved_alias != nullptr) + { + this->current_type = type(unresolved_alias); + } + else if (auto from_symbol_table = this->bag.lookup(type_expression->name)) + { + if (auto type_symbol = from_symbol_table->is_type()) + { + this->current_type = type_symbol->symbol; + } + } + else + { + add_error<undeclared_error>(type_expression->name, this->input_file, type_expression->position()); + this->current_type = type(); + } } void name_analysis_visitor::visit(array_access_expression *expression) |
