diff options
Diffstat (limited to 'frontend/parser.yy')
| -rw-r--r-- | frontend/parser.yy | 594 |
1 files changed, 0 insertions, 594 deletions
diff --git a/frontend/parser.yy b/frontend/parser.yy deleted file mode 100644 index bace8d7..0000000 --- a/frontend/parser.yy +++ /dev/null @@ -1,594 +0,0 @@ -/* Syntax analyzer. - Copyright (C) 2025 Free Software Foundation, Inc. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -%require "3.4" -%language "c++" - -%code { - using namespace elna; -} - -%code requires { - #include <cstdint> - #include <iostream> - #include "elna/frontend/driver.h" - - #if !defined(yyFlexLexerOnce) - #include <FlexLexer.h> - #endif - - namespace elna::frontend - { - class lexer; - } -} - -%code provides { - namespace elna::frontend - { - - class lexer: public yyFlexLexer - { - public: - yy::location location; - - lexer(std::istream& arg_yyin) - : yyFlexLexer(&arg_yyin) - { - } - - yy::parser::symbol_type lex(driver& driver); - }; - - } -} - -%define api.token.raw -%define api.token.constructor -%define api.value.type variant - -%parse-param {elna::frontend::lexer& lexer} -%param {elna::frontend::driver& driver} -%locations - -%header - -%code { - #define yylex lexer.lex -} -%start program; - -%token <std::string> IDENTIFIER -%token <std::string> TRAIT -%token <std::int32_t> INTEGER -%token <std::uint32_t> WORD -%token <float> FLOAT -%token <std::string> CHARACTER -%token <std::string> STRING -%token <bool> BOOLEAN -%token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]" -%token ASSIGNMENT ":=" - ARROW "->" EXCLAMATION "!" - AT "@" HAT "^" - COLON ":" SEMICOLON ";" DOT "." COMMA "," -%token NOT "~" - CAST "cast" - NIL "nil" - CONST "const" - VAR "var" - PROCEDURE "proc" - TYPE "type" - RECORD "record" - UNION "union" - EXTERN "extern" - IF "if" - WHILE "while" - DO "do" - THEN "then" - ELSE "else" - ELSIF "elsif" - RETURN "return" - PROGRAM "program" - MODULE "module" - IMPORT "import" - BEGIN_BLOCK "begin" - END_BLOCK "end" - DEFER "defer" - CASE "case" - OF "of" - PIPE "|" -%token OR "or" AND "&" XOR "xor" - EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">=" - SHIFT_LEFT "<<" SHIFT_RIGHT ">>" - PLUS "+" MINUS "-" - MULTIPLICATION "*" DIVISION "/" REMAINDER "%" - -%left "or" "&" "xor" -%left "=" "<>" "<" ">" "<=" ">=" -%left "<<" ">>" -%left "+" "-" -%left "*" "/" "%" - -%type <elna::frontend::literal_expression *> literal; -%type <std::vector<elna::frontend::expression *>> case_labels; -%type <elna::frontend::switch_case> switch_case; -%type <std::vector<elna::frontend::switch_case>> switch_cases; -%type <elna::frontend::constant_declaration *> constant_declaration; -%type <std::vector<elna::frontend::constant_declaration *>> constant_part constant_declarations; -%type <elna::frontend::variable_declaration *> variable_declaration; -%type <std::vector<elna::frontend::variable_declaration *>> variable_declarations variable_part; -%type <elna::frontend::type_expression *> type_expression; -%type <std::vector<elna::frontend::type_expression *>> type_expressions; -%type <elna::frontend::traits_expression *> traits_expression; -%type <elna::frontend::expression *> expression operand simple_expression; -%type <elna::frontend::unary_expression *> unary_expression; -%type <elna::frontend::binary_expression *> binary_expression; -%type <std::vector<elna::frontend::expression *>> expressions actual_parameter_list; -%type <elna::frontend::designator_expression *> designator_expression; -%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 <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 <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; -%type <elna::frontend::field_declaration> field_declaration formal_parameter; -%type <std::vector<std::pair<std::string, elna::frontend::type_expression *>>> - optional_fields required_fields formal_parameters formal_parameter_list; -%type <std::vector<elna::frontend::conditional_statements *>> elsif_then_statements elsif_do_statements; -%type <std::vector<elna::frontend::statement *> *> else_statements; -%type <elna::frontend::cast_expression *> cast_expression; -%type <elna::frontend::identifier_definition> identifier_definition; -%type <std::vector<elna::frontend::identifier_definition>> identifier_definitions; -%type <std::vector<std::string>> identifiers import_declaration; -%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" "." - { - 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); - - driver.tree.reset(tree); - } -block: constant_part variable_part statement_part "end" - { - $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move($3)); - } -statement_part: - /* no statements */ {} - | "begin" required_statements { std::swap($$, $2); } - | return_statement { $$.push_back($1); } - | "begin" required_statements ";" return_statement - { - std::swap($$, $2); - $$.push_back($4); - } -identifier_definition: - IDENTIFIER "*" { $$ = frontend::identifier_definition{ $1, true }; } - | IDENTIFIER { $$ = frontend::identifier_definition{ $1, false }; } -identifier_definitions: - identifier_definition "," identifier_definitions - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | identifier_definition { $$.emplace_back(std::move($1)); } -return_declaration: - /* proper procedure */ {} - | "->" "!" { $$ = frontend::procedure_type_expression::return_t(std::monostate{}); } - | "->" type_expression { $$ = frontend::procedure_type_expression::return_t($2); } -procedure_heading: formal_parameter_list return_declaration - { - $$.second = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($2)); - for (auto& [name, type] : $1) - { - $$.first.emplace_back(std::move(name)); - $$.second->parameters.push_back(type); - } - } -procedure_declaration: - "proc" identifier_definition procedure_heading ";" block ";" - { - $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, std::move(*$5)); - std::swap($3.first, $$->parameter_names); - } - | "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 - { - 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); - std::swap($$->arguments, $2); - } -cast_expression: "cast" "(" expression ":" type_expression ")" - { $$ = new frontend::cast_expression(frontend::make_position(@1), $5, $3); } -elsif_do_statements: - "elsif" expression "do" optional_statements elsif_do_statements - { - frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4)); - std::swap($5, $$); - $$.emplace($$.begin(), branch); - } - | {} -else_statements: - "else" optional_statements { $$ = new std::vector<frontend::statement *>(std::move($2)); } - | { $$ = nullptr; } -elsif_then_statements: - "elsif" expression "then" optional_statements elsif_then_statements - { - frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4)); - std::swap($5, $$); - $$.emplace($$.begin(), branch); - } - | {} -return_statement: "return" expression - { $$ = new frontend::return_statement(frontend::make_position(@1), $2); } -literal: - INTEGER { $$ = new frontend::literal<std::int32_t>(frontend::make_position(@1), $1); } - | WORD { $$ = new frontend::literal<std::uint32_t>(frontend::make_position(@1), $1); } - | FLOAT { $$ = new frontend::literal<double>(frontend::make_position(@1), $1); } - | BOOLEAN { $$ = new frontend::literal<bool>(frontend::make_position(@1), $1); } - | CHARACTER { $$ = new frontend::literal<unsigned char>(frontend::make_position(@1), $1.at(0)); } - | "nil" { $$ = new frontend::literal<std::nullptr_t>(frontend::make_position(@1), nullptr); } - | STRING { $$ = new frontend::literal<std::string>(frontend::make_position(@1), $1); } -traits_expression: - TRAIT "(" type_expressions ")" - { - $$ = new frontend::traits_expression(frontend::make_position(@1), $1); - std::swap($3, $$->parameters); - } -simple_expression: - literal { $$ = $1; } - | designator_expression { $$ = $1; } - | traits_expression { $$ = $1; } - | cast_expression { $$ = $1; } - | call_expression { $$ = $1; } - | "(" expression ")" { $$ = $2; } -operand: - unary_expression { $$ = $1; } - | simple_expression { $$ = $1; } -expression: - binary_expression { $$ = $1; } - | operand { $$ = $1; } -binary_expression: - expression "*" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::multiplication); - } - | expression "/" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::division); - } - | expression "%" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::remainder); - } - | expression "+" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::sum); - } - | expression "-" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::subtraction); - } - | expression "=" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::equals); - } - | expression "<>" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::not_equals); - } - | expression "<" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::less); - } - | expression ">" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater); - } - | expression "<=" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, - frontend::binary_operator::less_equal); - } - | expression ">=" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater_equal); - } - | expression "&" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::conjunction); - } - | expression "or" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::disjunction); - } - | expression "xor" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, - frontend::binary_operator::exclusive_disjunction); - } - | expression "<<" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_left); - } - | expression ">>" expression - { - $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_right); - } -unary_expression: - "@" operand - { - $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::reference); - } - | "~" operand - { - $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::negation); - } - | "-" operand - { - $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::minus); - } -expressions: - expression "," expressions - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | expression { $$.push_back($1); } -type_expressions: - type_expression "," type_expressions - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | type_expression { $$.push_back($1); } -designator_expression: - simple_expression "[" expression "]" - { $$ = new frontend::array_access_expression(frontend::make_position(@2), $1, $3); } - | simple_expression "." IDENTIFIER - { $$ = new frontend::field_access_expression(frontend::make_position(@2), $1, $3); } - | simple_expression "^" - { $$ = new frontend::dereference_expression(frontend::make_position(@1), $1); } - | IDENTIFIER - { $$ = new frontend::variable_expression(frontend::make_position(@1), $1); } -statement: - designator_expression ":=" expression - { $$ = new frontend::assign_statement(frontend::make_position(@1), $1, $3); } - | "while" expression "do" optional_statements elsif_do_statements "end" - { - frontend::conditional_statements *body = new frontend::conditional_statements($2, std::move($4)); - $$ = new frontend::while_statement(frontend::make_position(@1), body, std::move($5)); - } - | "if" expression "then" optional_statements elsif_then_statements else_statements "end" - { - frontend::conditional_statements *then = new frontend::conditional_statements($2, std::move($4)); - $$ = new frontend::if_statement(frontend::make_position(@1), then, std::move($5), $6); - } - | call_expression { $$ = $1; } - | "defer" optional_statements "end" - { $$ = new frontend::defer_statement(frontend::make_position(@1), std::move($2)); } - | "case" expression "of" switch_cases else_statements "end" - { $$ = new frontend::case_statement(frontend::make_position(@1), $2, std::move($4), $5); } -switch_case: case_labels ":" optional_statements - { $$ = { .labels = std::move($1), .statements = std::move($3) }; } -switch_cases: - switch_case "|" switch_cases - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | switch_case { $$.push_back($1); } -case_labels: - expression "," case_labels - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | expression { $$.push_back($1); } -required_statements: - required_statements ";" statement - { - std::swap($$, $1); - $$.insert($$.cend(), $3); - } - | statement { $$.push_back($1); } -optional_statements: - required_statements { std::swap($$, $1); } - | /* no statements */ {} -field_declaration: - IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); } -required_fields: - field_declaration ";" required_fields - { - std::swap($$, $3); - $$.emplace($$.cbegin(), $1); - } - | field_declaration { $$.emplace_back($1); } -optional_fields: - required_fields { std::swap($$, $1); } - | /* no fields */ {} -type_expression: - "[" INTEGER "]" type_expression - { - $$ = new frontend::array_type_expression(frontend::make_position(@1), $4, $2); - } - | "^" type_expression - { - $$ = new frontend::pointer_type_expression(frontend::make_position(@1), $2); - } - | "record" optional_fields "end" - { - $$ = new frontend::record_type_expression(frontend::make_position(@1), std::move($2)); - } - | "union" required_fields "end" - { - $$ = new frontend::union_type_expression(frontend::make_position(@1), std::move($2)); - } - | "proc" "(" type_expressions ")" return_declaration - { - auto result = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($5)); - std::swap(result->parameters, $3); - $$ = result; - } - | "(" identifiers ")" - { - $$ = new frontend::enumeration_type_expression(frontend::make_position(@1), std::move($2)); - } - | IDENTIFIER - { - $$ = new frontend::named_type_expression(frontend::make_position(@1), $1); - } -identifiers: - IDENTIFIER "," identifiers - { - std::swap($$, $3); - $$.emplace($$.cbegin(), std::move($1)); - } - | IDENTIFIER { $$.emplace_back(std::move($1)); } -variable_declaration: - 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" ";" - { - 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 ";" - { - std::shared_ptr<frontend::type_expression> shared_type{ $3 }; - $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, $5); - } -variable_declarations: - /* no variable declarations */ {} - | variable_declaration variable_declarations - { - std::swap($$, $2); - $$.insert(std::cbegin($$), $1); - } -variable_part: - /* no variable declarations */ {} - | "var" variable_declarations { std::swap($$, $2); } -constant_declaration: identifier_definition ":=" expression ";" - { - $$ = new frontend::constant_declaration(frontend::make_position(@1), std::move($1), $3); - } -constant_declarations: - constant_declaration constant_declarations - { - std::swap($$, $2); - $$.insert(std::cbegin($$), $1); - } - | /* no constant definitions */ {} -constant_part: - /* no constant definitions */ {} - | "const" constant_declarations { std::swap($$, $2); } -import_declaration: - IDENTIFIER "." import_declaration - { - std::swap($$, $3); - $$.emplace($$.cbegin(), std::move($1)); - } - | IDENTIFIER { $$.emplace_back(std::move($1)); } -import_declarations: - import_declaration "," import_declarations - { - std::swap($$, $3); - $$.emplace($$.cbegin(), new frontend::import_declaration(frontend::make_position(@1), std::move($1))); - } - | import_declaration - { - $$.emplace_back(new frontend::import_declaration(frontend::make_position(@1), std::move($1))); - } -import_part: - /* no import declarations */ {} - | "import" import_declarations ";" { std::swap($$, $2); } -type_declaration: identifier_definition "=" type_expression ";" - { - $$ = new frontend::type_declaration(frontend::make_position(@1), std::move($1), $3); - } -type_declarations: - type_declaration type_declarations - { - std::swap($$, $2); - $$.insert($$.cbegin(), $1); - } - | /* no type definitions */ {} -type_part: - /* no type definitions */ {} - | "type" type_declarations { std::swap($$, $2); } -formal_parameter: - IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); } -formal_parameter_list: - "(" ")" {} - | "(" formal_parameters ")" { std::swap($$, $2); } -formal_parameters: - formal_parameter "," formal_parameters - { - std::swap($$, $3); - $$.emplace($$.cbegin(), std::move($1)); - } - | formal_parameter { $$.emplace_back(std::move($1)); } -actual_parameter_list: - "(" ")" {} - | "(" expressions ")" { std::swap($$, $2); } -%% - -void yy::parser::error(const location_type& loc, const std::string& message) -{ - driver.add_error<frontend::syntax_error>(message, driver.input_file, loc); -} |
