Allow only one return

This commit is contained in:
2025-03-01 00:00:36 +01:00
parent f091344cce
commit 18602d00a1
10 changed files with 39 additions and 198 deletions

View File

@ -106,7 +106,6 @@ along with GCC; see the file COPYING3. If not see
RETURN "return"
BEGIN_BLOCK "begin"
END_BLOCK "end"
DEFER "defer"
%token OR "or" AND "and" XOR "xor"
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
@ -134,12 +133,12 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::procedure_call*> call_expression;
%type <elna::boot::while_statement *> while_statement;
%type <elna::boot::if_statement *> if_statement;
%type <elna::boot::return_statement *> return_statement;
%type <elna::boot::expression *> return_statement;
%type <elna::boot::statement *> statement;
%type <std::vector<elna::boot::statement *>> statements optional_statements;
%type <std::vector<elna::boot::statement *>> statements statement_part;
%type <elna::boot::procedure_definition *> procedure_definition;
%type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions;
%type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block;
@ -147,12 +146,11 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields fields;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
%type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
%%
program:
constant_part type_part variable_part procedure_part "begin" optional_statements "end" "."
constant_part type_part variable_part procedure_definitions "begin" statements "end" "."
{
auto tree = new elna::boot::program(elna::boot::make_position(@5));
@ -164,13 +162,13 @@ program:
driver.tree.reset(tree);
}
block: constant_part variable_part "begin" optional_statements "end"
block: constant_part variable_part statement_part
{
$$ = new elna::boot::block(elna::boot::make_position(@3));
$$ = new elna::boot::block(elna::boot::make_position(@1));
std::swap($$->constants, $1);
std::swap($$->variables, $2);
std::swap($$->body, $4);
std::swap($$->body, $3);
}
identifier_definition:
IDENTIFIER "*"
@ -205,9 +203,10 @@ procedure_heading:
std::swap($1, $$->parameters);
}
procedure_definition:
"proc" identifier_definition procedure_heading ";" block
"proc" identifier_definition procedure_heading ";" block return_statement "end"
{
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second,
$3, $5, $6);
}
| "proc" identifier_definition procedure_heading ";" "extern"
{
@ -219,10 +218,7 @@ 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); }
| /* no procedure definitions */ {}
assign_statement: designator_expression ":=" expression
{
$$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
@ -237,7 +233,7 @@ cast_expression: "cast" "(" expression ":" type_expression ")"
$$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
}
elsif_do_statements:
"elsif" expression "do" optional_statements elsif_do_statements
"elsif" expression "do" statements elsif_do_statements
{
elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
std::swap(branch->statements, $4);
@ -245,7 +241,7 @@ elsif_do_statements:
$$.emplace($$.begin(), branch);
}
| {}
while_statement: "while" expression "do" optional_statements elsif_do_statements "end"
while_statement: "while" expression "do" statements elsif_do_statements "end"
{
auto body = new elna::boot::conditional_statements($2);
std::swap($4, body->statements);
@ -253,7 +249,7 @@ while_statement: "while" expression "do" optional_statements elsif_do_statements
std::swap($5, $$->branches);
}
elsif_then_statements:
"elsif" expression "then" optional_statements elsif_then_statements
"elsif" expression "then" statements elsif_then_statements
{
elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
std::swap(branch->statements, $4);
@ -262,14 +258,14 @@ elsif_then_statements:
}
| {}
if_statement:
"if" expression "then" optional_statements elsif_then_statements "end"
"if" expression "then" statements elsif_then_statements "end"
{
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_then_statements "else" optional_statements "end"
| "if" expression "then" statements elsif_then_statements "else" statements "end"
{
auto then = new elna::boot::conditional_statements($2);
std::swap($4, then->statements);
@ -277,15 +273,12 @@ if_statement:
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
std::swap($5, $$->branches);
}
return_statement: "return" expression
return_statement:
"return" expression
{
$$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
}
defer_statement: DEFER optional_statements "end"
{
$$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
std::swap($2, $$->statements);
$$ = $2;
}
| /* no return statement */ { $$ = nullptr; }
literal:
INTEGER
{
@ -454,19 +447,17 @@ statement:
assign_statement { $$ = $1; }
| while_statement { $$ = $1; }
| if_statement { $$ = $1; }
| return_statement { $$ = $1; }
| call_expression { $$ = $1; }
| defer_statement { $$ = $1; }
statements:
statement statements
{
std::swap($$, $2);
$$.emplace($$.cbegin(), $1);
}
| statement { $$.push_back($1); }
optional_statements:
statements { std::swap($$, $1); }
| /* no statements */ {}
statement_part:
"begin" statements { std::swap($$, $2); }
| {}
field_declaration:
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
fields: