Allow only one return statement
This commit is contained in:
@ -145,10 +145,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
||||
%type <elna::boot::designator_expression *> designator_expression;
|
||||
%type <elna::boot::procedure_call*> call_expression;
|
||||
%type <elna::boot::while_statement *> while_statement;
|
||||
%type <elna::boot::return_statement *> return_statement;
|
||||
%type <elna::boot::statement *> statement;
|
||||
%type <std::vector<elna::boot::statement *>> statements;
|
||||
%type <std::vector<elna::boot::statement *>> required_statements optional_statements statement_part;
|
||||
%type <elna::boot::procedure_definition *> procedure_definition;
|
||||
%type <std::pair<std::vector<std::string>, elna::boot::procedure_type_expression *>> procedure_heading;
|
||||
%type <elna::boot::procedure_type_expression::return_t> return_declaration;
|
||||
@ -158,7 +157,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <std::unique_ptr<elna::boot::block>> block;
|
||||
%type <elna::boot::field_declaration> field_declaration formal_parameter;
|
||||
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>>
|
||||
optional_fields required_fields formal_parameters;
|
||||
optional_fields required_fields formal_parameters formal_parameter_list;
|
||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
|
||||
%type <std::vector<elna::boot::statement *> *> else_statements;
|
||||
%type <elna::boot::cast_expression *> cast_expression;
|
||||
@ -168,7 +167,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <std::vector<elna::boot::import_declaration *>> import_declarations import_part;
|
||||
%%
|
||||
program:
|
||||
"program" import_part constant_part type_part variable_part procedure_part "begin" statements "end" "."
|
||||
"program" import_part constant_part type_part variable_part procedure_part "begin" optional_statements "end" "."
|
||||
{
|
||||
auto tree = new boot::program(boot::make_position(@7));
|
||||
|
||||
@ -193,9 +192,18 @@ program:
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
block: constant_part variable_part "begin" statements "end"
|
||||
block: constant_part variable_part statement_part "end"
|
||||
{
|
||||
$$ = std::make_unique<boot::block>(std::move($1), std::move($2), std::move($4));
|
||||
$$ = std::make_unique<boot::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 "*" { $$ = boot::identifier_definition{ $1, true }; }
|
||||
@ -211,11 +219,10 @@ return_declaration:
|
||||
/* proper procedure */ {}
|
||||
| "->" "!" { $$ = boot::procedure_type_expression::return_t(std::monostate{}); }
|
||||
| "->" type_expression { $$ = boot::procedure_type_expression::return_t($2); }
|
||||
procedure_heading:
|
||||
"(" formal_parameters ")" return_declaration
|
||||
procedure_heading: formal_parameter_list return_declaration
|
||||
{
|
||||
$$.second = new boot::procedure_type_expression(boot::make_position(@1), std::move($4));
|
||||
for (auto& [name, type] : $2)
|
||||
$$.second = new boot::procedure_type_expression(boot::make_position(@1), std::move($2));
|
||||
for (auto& [name, type] : $1)
|
||||
{
|
||||
$$.first.emplace_back(std::move(name));
|
||||
$$.second->parameters.push_back(type);
|
||||
@ -250,7 +257,7 @@ call_expression: designator_expression actual_parameter_list
|
||||
cast_expression: "cast" "(" expression ":" type_expression ")"
|
||||
{ $$ = new boot::cast_expression(boot::make_position(@1), $5, $3); }
|
||||
elsif_do_statements:
|
||||
"elsif" expression "do" statements elsif_do_statements
|
||||
"elsif" expression "do" optional_statements elsif_do_statements
|
||||
{
|
||||
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
|
||||
std::swap($5, $$);
|
||||
@ -258,36 +265,18 @@ elsif_do_statements:
|
||||
}
|
||||
| {}
|
||||
else_statements:
|
||||
"else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
|
||||
"else" optional_statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
|
||||
| { $$ = nullptr; }
|
||||
while_statement:
|
||||
"while" expression "do" statements elsif_do_statements else_statements "end"
|
||||
{
|
||||
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
|
||||
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5), $6);
|
||||
}
|
||||
| "while" expression "," IDENTIFIER "do" statements elsif_do_statements else_statements "end"
|
||||
{
|
||||
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($6));
|
||||
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($7), $4, $8);
|
||||
}
|
||||
elsif_then_statements:
|
||||
"elsif" expression "then" statements elsif_then_statements
|
||||
"elsif" expression "then" optional_statements elsif_then_statements
|
||||
{
|
||||
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
|
||||
std::swap($5, $$);
|
||||
$$.emplace($$.begin(), branch);
|
||||
}
|
||||
| {}
|
||||
return_statement:
|
||||
"return" expression
|
||||
{
|
||||
$$ = new boot::return_statement(boot::make_position(@1), $2);
|
||||
}
|
||||
| "return"
|
||||
{
|
||||
$$ = new boot::return_statement(boot::make_position(@1));
|
||||
}
|
||||
return_statement: "return" expression
|
||||
{ $$ = new boot::return_statement(boot::make_position(@1), $2); }
|
||||
literal:
|
||||
INTEGER { $$ = new boot::literal<std::int32_t>(boot::make_position(@1), $1); }
|
||||
| WORD { $$ = new boot::literal<std::uint32_t>(boot::make_position(@1), $1); }
|
||||
@ -421,18 +410,23 @@ designator_expression:
|
||||
statement:
|
||||
designator_expression ":=" expression
|
||||
{ $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); }
|
||||
| while_statement { $$ = $1; }
|
||||
| "if" expression "then" statements elsif_then_statements else_statements "end"
|
||||
| "while" expression "do" optional_statements elsif_do_statements else_statements "end"
|
||||
{
|
||||
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
|
||||
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5), $6);
|
||||
}
|
||||
| "if" expression "then" optional_statements elsif_then_statements else_statements "end"
|
||||
{
|
||||
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
|
||||
$$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6);
|
||||
}
|
||||
| return_statement { $$ = $1; }
|
||||
| call_expression { $$ = $1; }
|
||||
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
||||
| "defer" optional_statements "end"
|
||||
{ $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
||||
| "case" expression "of" switch_cases else_statements "end"
|
||||
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4), $5); }
|
||||
switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
||||
switch_case: case_labels ":" optional_statements
|
||||
{ $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
||||
switch_cases:
|
||||
switch_case "|" switch_cases
|
||||
{
|
||||
@ -447,13 +441,15 @@ case_labels:
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| expression { $$.push_back($1); }
|
||||
statements:
|
||||
statement ";" statements
|
||||
required_statements:
|
||||
required_statements ";" statement
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.insert($$.cbegin(), $1);
|
||||
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); }
|
||||
@ -578,9 +574,11 @@ type_part:
|
||||
| "type" type_definitions { std::swap($$, $2); }
|
||||
formal_parameter:
|
||||
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
|
||||
formal_parameter_list:
|
||||
"(" ")" {}
|
||||
| "(" formal_parameters ")" { std::swap($$, $2); }
|
||||
formal_parameters:
|
||||
/* no formal parameters */ {}
|
||||
| formal_parameter "," formal_parameters
|
||||
formal_parameter "," formal_parameters
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
|
Reference in New Issue
Block a user