Add an else to the case statement

This commit is contained in:
Eugen Wissner 2025-04-11 15:28:43 +02:00
parent f68667d5e5
commit 6fd1bda112
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
6 changed files with 173 additions and 169 deletions

View File

@ -794,8 +794,8 @@ namespace elna::boot
} }
case_statement::case_statement(const struct position position, case_statement::case_statement(const struct position position,
expression *condition, std::vector<switch_case>&& cases) expression *condition, std::vector<switch_case>&& cases, std::vector<statement *> *alternative)
: node(position), m_condition(condition), cases(std::move(cases)) : node(position), m_condition(condition), cases(std::move(cases)), alternative(alternative)
{ {
} }
@ -862,7 +862,7 @@ namespace elna::boot
if_statement::if_statement(const struct position position, conditional_statements *body, if_statement::if_statement(const struct position position, conditional_statements *body,
std::vector<statement *> *alternative) std::vector<statement *> *alternative)
: node(position), m_body(body), m_alternative(alternative) : node(position), m_body(body), alternative(alternative)
{ {
} }
@ -881,11 +881,6 @@ namespace elna::boot
return *m_body; return *m_body;
} }
std::vector<statement *> *if_statement::alternative()
{
return m_alternative;
}
if_statement::~if_statement() if_statement::~if_statement()
{ {
delete m_body; delete m_body;
@ -893,7 +888,7 @@ namespace elna::boot
{ {
delete branch; delete branch;
} }
delete m_alternative; delete this->alternative;
} }
while_statement::while_statement(const struct position position, conditional_statements *body) while_statement::while_statement(const struct position position, conditional_statements *body)

View File

@ -143,7 +143,6 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::designator_expression *> designator_expression; %type <elna::boot::designator_expression *> designator_expression;
%type <elna::boot::procedure_call*> call_expression; %type <elna::boot::procedure_call*> call_expression;
%type <elna::boot::while_statement *> while_statement; %type <elna::boot::while_statement *> while_statement;
%type <elna::boot::if_statement *> if_statement;
%type <elna::boot::return_statement *> return_statement; %type <elna::boot::return_statement *> return_statement;
%type <elna::boot::statement *> statement; %type <elna::boot::statement *> statement;
%type <std::vector<elna::boot::statement *>> statements; %type <std::vector<elna::boot::statement *>> statements;
@ -158,6 +157,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> %type <std::vector<std::pair<std::string, elna::boot::type_expression *>>>
optional_fields required_fields formal_parameters; optional_fields required_fields formal_parameters;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements; %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; %type <elna::boot::cast_expression *> cast_expression;
%type <std::pair<std::string, bool>> identifier_definition; %type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions; %type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
@ -253,6 +253,9 @@ elsif_do_statements:
$$.emplace($$.begin(), branch); $$.emplace($$.begin(), branch);
} }
| {} | {}
else_statements:
"else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
| { $$ = nullptr; }
while_statement: "while" expression "do" statements elsif_do_statements "end" while_statement: "while" expression "do" statements elsif_do_statements "end"
{ {
auto body = new boot::conditional_statements($2); auto body = new boot::conditional_statements($2);
@ -269,22 +272,6 @@ elsif_then_statements:
$$.emplace($$.begin(), branch); $$.emplace($$.begin(), branch);
} }
| {} | {}
if_statement:
"if" expression "then" statements elsif_then_statements "end"
{
auto then = new boot::conditional_statements($2);
std::swap($4, then->statements);
$$ = new boot::if_statement(boot::make_position(@1), then);
std::swap($5, $$->branches);
}
| "if" expression "then" statements elsif_then_statements "else" statements "end"
{
auto then = new boot::conditional_statements($2);
std::swap($4, then->statements);
auto _else = new std::vector<boot::statement *>(std::move($7));
$$ = new boot::if_statement(boot::make_position(@1), then, _else);
std::swap($5, $$->branches);
}
return_statement: return_statement:
"return" expression "return" expression
{ {
@ -428,12 +415,19 @@ statement:
designator_expression ":=" expression designator_expression ":=" expression
{ $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); } { $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); }
| while_statement { $$ = $1; } | while_statement { $$ = $1; }
| if_statement { $$ = $1; } | "if" expression "then" statements elsif_then_statements else_statements "end"
{
auto then = new boot::conditional_statements($2);
std::swap($4, then->statements);
auto result = new boot::if_statement(boot::make_position(@1), then, $6);
std::swap($5, result->branches);
$$ = result;
}
| return_statement { $$ = $1; } | return_statement { $$ = $1; }
| call_expression { $$ = $1; } | call_expression { $$ = $1; }
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); } | "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
| "case" expression "of" switch_cases "end" | "case" expression "of" switch_cases else_statements "end"
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4)); } { $$ = 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 ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
switch_cases: switch_cases:
switch_case "|" switch_cases switch_case "|" switch_cases

View File

@ -230,9 +230,9 @@ namespace elna::boot
statement->accept(this); statement->accept(this);
} }
} }
if (statement->alternative() != nullptr) if (statement->alternative != nullptr)
{ {
for (struct statement *const statement : *statement->alternative()) for (struct statement *const statement : *statement->alternative)
{ {
statement->accept(this); statement->accept(this);
} }

View File

@ -1183,10 +1183,10 @@ namespace elna::gcc
{ {
make_if_branch(*branch, goto_endif); make_if_branch(*branch, goto_endif);
} }
if (statement->alternative() != nullptr) if (statement->alternative != nullptr)
{ {
enter_scope(); enter_scope();
visit_statements(*statement->alternative()); visit_statements(*statement->alternative);
tree mapping = leave_scope(); tree mapping = leave_scope();
append_statement(mapping); append_statement(mapping);
} }
@ -1465,11 +1465,24 @@ namespace elna::gcc
enter_scope(); enter_scope();
visit_statements(case_block.statements); visit_statements(case_block.statements);
append_to_statement_list(leave_scope(), &switch_statements); append_to_statement_list(leave_scope(), &switch_statements);
tree goto_end = fold_build1(GOTO_EXPR, void_type_node, end_label_declaration); tree goto_end = build1(GOTO_EXPR, void_type_node, end_label_declaration);
append_to_statement_list(goto_end, &switch_statements); append_to_statement_list(goto_end, &switch_statements);
TREE_USED(end_label_declaration) = 1; TREE_USED(end_label_declaration) = 1;
} }
if (statement->alternative != nullptr)
{
tree case_label_declaration = create_artificial_label(UNKNOWN_LOCATION);
tree case_expression = build_case_label(NULL_TREE, NULL_TREE, case_label_declaration);
append_to_statement_list(case_expression, &switch_statements);
enter_scope();
visit_statements(*statement->alternative);
append_to_statement_list(leave_scope(), &switch_statements);
TREE_USED(end_label_declaration) = 1;
}
tree switch_expression = build2(SWITCH_EXPR, TREE_TYPE(condition_expression), tree switch_expression = build2(SWITCH_EXPR, TREE_TYPE(condition_expression),
condition_expression, switch_statements); condition_expression, switch_statements);

View File

@ -461,8 +461,10 @@ namespace elna::boot
public: public:
const std::vector<switch_case> cases; const std::vector<switch_case> cases;
const std::vector<statement *> *alternative;
case_statement(const struct position position, expression *condition, std::vector<switch_case>&& cases); case_statement(const struct position position, expression *condition,
std::vector<switch_case>&& cases, std::vector<statement *> *alternative = nullptr);
void accept(parser_visitor *visitor) override; void accept(parser_visitor *visitor) override;
expression& condition(); expression& condition();
}; };
@ -592,10 +594,10 @@ namespace elna::boot
class if_statement : public statement class if_statement : public statement
{ {
conditional_statements *m_body; conditional_statements *m_body;
std::vector<statement *> *m_alternative;
public: public:
std::vector<conditional_statements *> branches; std::vector<conditional_statements *> branches;
const std::vector<statement *> *alternative;
if_statement(const struct position position, conditional_statements *body, if_statement(const struct position position, conditional_statements *body,
std::vector<statement *> *alternative = nullptr); std::vector<statement *> *alternative = nullptr);
@ -603,7 +605,6 @@ namespace elna::boot
virtual if_statement *is_if() override; virtual if_statement *is_if() override;
conditional_statements& body(); conditional_statements& body();
std::vector<statement *> *alternative();
virtual ~if_statement() override; virtual ~if_statement() override;
}; };

View File

@ -518,133 +518,134 @@ begin
while i < tokens_size do while i < tokens_size do
current_token := tokens + i; current_token := tokens + i;
if current_token^.kind = TokenKind._if then case current_token^.kind of
TokenKind._if:
write_s("IF") write_s("IF")
elsif current_token^.kind = TokenKind._then then | TokenKind._then:
write_s("THEN") write_s("THEN")
elsif current_token^.kind = TokenKind._else then | TokenKind._else:
write_s("ELSE") write_s("ELSE")
elsif current_token^.kind = TokenKind._elsif then | TokenKind._elsif:
write_s("ELSIF") write_s("ELSIF")
elsif current_token^.kind = TokenKind._while then | TokenKind._while:
write_s("WHILE") write_s("WHILE")
elsif current_token^.kind = TokenKind._do then | TokenKind._do:
write_s("DO") write_s("DO")
elsif current_token^.kind = TokenKind._proc then | TokenKind._proc:
write_s("PROC") write_s("PROC")
elsif current_token^.kind = TokenKind._begin then | TokenKind._begin:
write_s("BEGIN") write_s("BEGIN")
elsif current_token^.kind = TokenKind._end then | TokenKind._end:
write_s("END") write_s("END")
elsif current_token^.kind = TokenKind._extern then | TokenKind._extern:
write_s("EXTERN") write_s("EXTERN")
elsif current_token^.kind = TokenKind._const then | TokenKind._const:
write_s("CONST") write_s("CONST")
elsif current_token^.kind = TokenKind._var then | TokenKind._var:
write_s("VAR") write_s("VAR")
elsif current_token^.kind = TokenKind.array then | TokenKind.array:
write_s("ARRAY") write_s("ARRAY")
elsif current_token^.kind = TokenKind._of then | TokenKind._of:
write_s("OF") write_s("OF")
elsif current_token^.kind = TokenKind._type then | TokenKind._type:
write_s("TYPE") write_s("TYPE")
elsif current_token^.kind = TokenKind._record then | TokenKind._record:
write_s("RECORD") write_s("RECORD")
elsif current_token^.kind = TokenKind._union then | TokenKind._union:
write_s("UNION") write_s("UNION")
elsif current_token^.kind = TokenKind.pointer then | TokenKind.pointer:
write_s("POINTER") write_s("POINTER")
elsif current_token^.kind = TokenKind.to then | TokenKind.to:
write_s("TO") write_s("TO")
elsif current_token^.kind = TokenKind.boolean then | TokenKind.boolean:
write_s("BOOLEAN<"); write_s("BOOLEAN<");
write_b(current_token^.value.boolean_value); write_b(current_token^.value.boolean_value);
write_c('>') write_c('>')
elsif current_token^.kind = TokenKind._nil then | TokenKind._nil:
write_s("NIL") write_s("NIL")
elsif current_token^.kind = TokenKind.and then | TokenKind.and:
write_s("AND") write_s("AND")
elsif current_token^.kind = TokenKind._or then | TokenKind._or:
write_s("OR") write_s("OR")
elsif current_token^.kind = TokenKind.not then | TokenKind.not:
write_s("NOT") write_s("NOT")
elsif current_token^.kind = TokenKind._return then | TokenKind._return:
write_s("RETURN") write_s("RETURN")
elsif current_token^.kind = TokenKind._cast then | TokenKind._cast:
write_s("CAST") write_s("CAST")
elsif current_token^.kind = TokenKind.shift_left then | TokenKind.shift_left:
write_s("<<") write_s("<<")
elsif current_token^.kind = TokenKind.shift_right then | TokenKind.shift_right:
write_s(">>") write_s(">>")
elsif current_token^.kind = TokenKind.identifier then | TokenKind.identifier:
write_c('<'); write_c('<');
write_s(current_token^.value.string); write_s(current_token^.value.string);
write_c('>') write_c('>')
elsif current_token^.kind = TokenKind.left_paren then | TokenKind.left_paren:
write_s("(") write_s("(")
elsif current_token^.kind = TokenKind.right_paren then | TokenKind.right_paren:
write_s(")") write_s(")")
elsif current_token^.kind = TokenKind.left_square then | TokenKind.left_square:
write_s("[") write_s("[")
elsif current_token^.kind = TokenKind.right_square then | TokenKind.right_square:
write_s("]") write_s("]")
elsif current_token^.kind = TokenKind.greater_equal then | TokenKind.greater_equal:
write_s(">=") write_s(">=")
elsif current_token^.kind = TokenKind.less_equal then | TokenKind.less_equal:
write_s("<=") write_s("<=")
elsif current_token^.kind = TokenKind.greater_than then | TokenKind.greater_than:
write_s(">") write_s(">")
elsif current_token^.kind = TokenKind.less_than then | TokenKind.less_than:
write_s("<") write_s("<")
elsif current_token^.kind = TokenKind.equal then | TokenKind.equal:
write_s("=") write_s("=")
elsif current_token^.kind = TokenKind.not_equal then | TokenKind.not_equal:
write_s("<>") write_s("<>")
elsif current_token^.kind = TokenKind.semicolon then | TokenKind.semicolon:
write_c(';') write_c(';')
elsif current_token^.kind = TokenKind.dot then | TokenKind.dot:
write_c('.') write_c('.')
elsif current_token^.kind = TokenKind.comma then | TokenKind.comma:
write_c(',') write_c(',')
elsif current_token^.kind = TokenKind.plus then | TokenKind.plus:
write_c('+') write_c('+')
elsif current_token^.kind = TokenKind.minus then | TokenKind.minus:
write_c('-') write_c('-')
elsif current_token^.kind = TokenKind.multiplication then | TokenKind.multiplication:
write_c('*') write_c('*')
elsif current_token^.kind = TokenKind.division then | TokenKind.division:
write_c('/') write_c('/')
elsif current_token^.kind = TokenKind.remainder then | TokenKind.remainder:
write_c('%') write_c('%')
elsif current_token^.kind = TokenKind.assignment then | TokenKind.assignment:
write_s(":=") write_s(":=")
elsif current_token^.kind = TokenKind.colon then | TokenKind.colon:
write_c(':') write_c(':')
elsif current_token^.kind = TokenKind.hat then | TokenKind.hat:
write_c('^') write_c('^')
elsif current_token^.kind = TokenKind.at then | TokenKind.at:
write_c('@') write_c('@')
elsif current_token^.kind = TokenKind.comment then | TokenKind.comment:
write_s("(* COMMENT *)") write_s("(* COMMENT *)")
elsif current_token^.kind = TokenKind.integer then | TokenKind.integer:
write_c('<'); write_c('<');
write_i(current_token^.value.int_value); write_i(current_token^.value.int_value);
write_c('>') write_c('>')
elsif current_token^.kind = TokenKind.word then | TokenKind.word:
write_c('<'); write_c('<');
write_i(current_token^.value.int_value); write_i(current_token^.value.int_value);
write_s("u>") write_s("u>")
elsif current_token^.kind = TokenKind.character then | TokenKind.character:
write_c('<'); write_c('<');
write_i(cast(current_token^.value.char_value: Int)); write_i(cast(current_token^.value.char_value: Int));
write_s("c>") write_s("c>")
elsif current_token^.kind = TokenKind.string then | TokenKind.string:
write_s("\"...\"") write_s("\"...\"")
elsif current_token^.kind = TokenKind._defer then | TokenKind._defer:
write_s("DEFER") write_s("DEFER")
elsif current_token^.kind = TokenKind.exclamation then | TokenKind.exclamation:
write_c('!') write_c('!')
elsif current_token^.kind = TokenKind.arrow then | TokenKind.arrow:
write_s("->") write_s("->")
else else
write_s("UNKNOWN<"); write_s("UNKNOWN<");