Add an else to the case statement
This commit is contained in:
parent
f68667d5e5
commit
6fd1bda112
13
boot/ast.cc
13
boot/ast.cc
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
265
source.elna
265
source.elna
@ -518,138 +518,139 @@ 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
|
||||||
write_s("IF")
|
TokenKind._if:
|
||||||
elsif current_token^.kind = TokenKind._then then
|
write_s("IF")
|
||||||
write_s("THEN")
|
| TokenKind._then:
|
||||||
elsif current_token^.kind = TokenKind._else then
|
write_s("THEN")
|
||||||
write_s("ELSE")
|
| TokenKind._else:
|
||||||
elsif current_token^.kind = TokenKind._elsif then
|
write_s("ELSE")
|
||||||
write_s("ELSIF")
|
| TokenKind._elsif:
|
||||||
elsif current_token^.kind = TokenKind._while then
|
write_s("ELSIF")
|
||||||
write_s("WHILE")
|
| TokenKind._while:
|
||||||
elsif current_token^.kind = TokenKind._do then
|
write_s("WHILE")
|
||||||
write_s("DO")
|
| TokenKind._do:
|
||||||
elsif current_token^.kind = TokenKind._proc then
|
write_s("DO")
|
||||||
write_s("PROC")
|
| TokenKind._proc:
|
||||||
elsif current_token^.kind = TokenKind._begin then
|
write_s("PROC")
|
||||||
write_s("BEGIN")
|
| TokenKind._begin:
|
||||||
elsif current_token^.kind = TokenKind._end then
|
write_s("BEGIN")
|
||||||
write_s("END")
|
| TokenKind._end:
|
||||||
elsif current_token^.kind = TokenKind._extern then
|
write_s("END")
|
||||||
write_s("EXTERN")
|
| TokenKind._extern:
|
||||||
elsif current_token^.kind = TokenKind._const then
|
write_s("EXTERN")
|
||||||
write_s("CONST")
|
| TokenKind._const:
|
||||||
elsif current_token^.kind = TokenKind._var then
|
write_s("CONST")
|
||||||
write_s("VAR")
|
| TokenKind._var:
|
||||||
elsif current_token^.kind = TokenKind.array then
|
write_s("VAR")
|
||||||
write_s("ARRAY")
|
| TokenKind.array:
|
||||||
elsif current_token^.kind = TokenKind._of then
|
write_s("ARRAY")
|
||||||
write_s("OF")
|
| TokenKind._of:
|
||||||
elsif current_token^.kind = TokenKind._type then
|
write_s("OF")
|
||||||
write_s("TYPE")
|
| TokenKind._type:
|
||||||
elsif current_token^.kind = TokenKind._record then
|
write_s("TYPE")
|
||||||
write_s("RECORD")
|
| TokenKind._record:
|
||||||
elsif current_token^.kind = TokenKind._union then
|
write_s("RECORD")
|
||||||
write_s("UNION")
|
| TokenKind._union:
|
||||||
elsif current_token^.kind = TokenKind.pointer then
|
write_s("UNION")
|
||||||
write_s("POINTER")
|
| TokenKind.pointer:
|
||||||
elsif current_token^.kind = TokenKind.to then
|
write_s("POINTER")
|
||||||
write_s("TO")
|
| TokenKind.to:
|
||||||
elsif current_token^.kind = TokenKind.boolean then
|
write_s("TO")
|
||||||
write_s("BOOLEAN<");
|
| TokenKind.boolean:
|
||||||
write_b(current_token^.value.boolean_value);
|
write_s("BOOLEAN<");
|
||||||
write_c('>')
|
write_b(current_token^.value.boolean_value);
|
||||||
elsif current_token^.kind = TokenKind._nil then
|
write_c('>')
|
||||||
write_s("NIL")
|
| TokenKind._nil:
|
||||||
elsif current_token^.kind = TokenKind.and then
|
write_s("NIL")
|
||||||
write_s("AND")
|
| TokenKind.and:
|
||||||
elsif current_token^.kind = TokenKind._or then
|
write_s("AND")
|
||||||
write_s("OR")
|
| TokenKind._or:
|
||||||
elsif current_token^.kind = TokenKind.not then
|
write_s("OR")
|
||||||
write_s("NOT")
|
| TokenKind.not:
|
||||||
elsif current_token^.kind = TokenKind._return then
|
write_s("NOT")
|
||||||
write_s("RETURN")
|
| TokenKind._return:
|
||||||
elsif current_token^.kind = TokenKind._cast then
|
write_s("RETURN")
|
||||||
write_s("CAST")
|
| TokenKind._cast:
|
||||||
elsif current_token^.kind = TokenKind.shift_left then
|
write_s("CAST")
|
||||||
write_s("<<")
|
| TokenKind.shift_left:
|
||||||
elsif current_token^.kind = TokenKind.shift_right then
|
write_s("<<")
|
||||||
write_s(">>")
|
| TokenKind.shift_right:
|
||||||
elsif current_token^.kind = TokenKind.identifier then
|
write_s(">>")
|
||||||
write_c('<');
|
| TokenKind.identifier:
|
||||||
write_s(current_token^.value.string);
|
write_c('<');
|
||||||
write_c('>')
|
write_s(current_token^.value.string);
|
||||||
elsif current_token^.kind = TokenKind.left_paren then
|
write_c('>')
|
||||||
write_s("(")
|
| TokenKind.left_paren:
|
||||||
elsif current_token^.kind = TokenKind.right_paren then
|
write_s("(")
|
||||||
write_s(")")
|
| TokenKind.right_paren:
|
||||||
elsif current_token^.kind = TokenKind.left_square then
|
write_s(")")
|
||||||
write_s("[")
|
| TokenKind.left_square:
|
||||||
elsif current_token^.kind = TokenKind.right_square then
|
write_s("[")
|
||||||
write_s("]")
|
| TokenKind.right_square:
|
||||||
elsif current_token^.kind = TokenKind.greater_equal then
|
write_s("]")
|
||||||
write_s(">=")
|
| TokenKind.greater_equal:
|
||||||
elsif current_token^.kind = TokenKind.less_equal then
|
write_s(">=")
|
||||||
write_s("<=")
|
| TokenKind.less_equal:
|
||||||
elsif current_token^.kind = TokenKind.greater_than then
|
write_s("<=")
|
||||||
write_s(">")
|
| TokenKind.greater_than:
|
||||||
elsif current_token^.kind = TokenKind.less_than then
|
write_s(">")
|
||||||
write_s("<")
|
| TokenKind.less_than:
|
||||||
elsif current_token^.kind = TokenKind.equal then
|
write_s("<")
|
||||||
write_s("=")
|
| TokenKind.equal:
|
||||||
elsif current_token^.kind = TokenKind.not_equal then
|
write_s("=")
|
||||||
write_s("<>")
|
| TokenKind.not_equal:
|
||||||
elsif current_token^.kind = TokenKind.semicolon then
|
write_s("<>")
|
||||||
write_c(';')
|
| TokenKind.semicolon:
|
||||||
elsif current_token^.kind = TokenKind.dot then
|
write_c(';')
|
||||||
write_c('.')
|
| TokenKind.dot:
|
||||||
elsif current_token^.kind = TokenKind.comma then
|
write_c('.')
|
||||||
write_c(',')
|
| TokenKind.comma:
|
||||||
elsif current_token^.kind = TokenKind.plus then
|
write_c(',')
|
||||||
write_c('+')
|
| TokenKind.plus:
|
||||||
elsif current_token^.kind = TokenKind.minus then
|
write_c('+')
|
||||||
write_c('-')
|
| TokenKind.minus:
|
||||||
elsif current_token^.kind = TokenKind.multiplication then
|
write_c('-')
|
||||||
write_c('*')
|
| TokenKind.multiplication:
|
||||||
elsif current_token^.kind = TokenKind.division then
|
write_c('*')
|
||||||
write_c('/')
|
| TokenKind.division:
|
||||||
elsif current_token^.kind = TokenKind.remainder then
|
write_c('/')
|
||||||
write_c('%')
|
| TokenKind.remainder:
|
||||||
elsif current_token^.kind = TokenKind.assignment then
|
write_c('%')
|
||||||
write_s(":=")
|
| TokenKind.assignment:
|
||||||
elsif current_token^.kind = TokenKind.colon then
|
write_s(":=")
|
||||||
write_c(':')
|
| TokenKind.colon:
|
||||||
elsif current_token^.kind = TokenKind.hat then
|
write_c(':')
|
||||||
write_c('^')
|
| TokenKind.hat:
|
||||||
elsif current_token^.kind = TokenKind.at then
|
write_c('^')
|
||||||
write_c('@')
|
| TokenKind.at:
|
||||||
elsif current_token^.kind = TokenKind.comment then
|
write_c('@')
|
||||||
write_s("(* COMMENT *)")
|
| TokenKind.comment:
|
||||||
elsif current_token^.kind = TokenKind.integer then
|
write_s("(* COMMENT *)")
|
||||||
write_c('<');
|
| TokenKind.integer:
|
||||||
write_i(current_token^.value.int_value);
|
write_c('<');
|
||||||
write_c('>')
|
write_i(current_token^.value.int_value);
|
||||||
elsif current_token^.kind = TokenKind.word then
|
write_c('>')
|
||||||
write_c('<');
|
| TokenKind.word:
|
||||||
write_i(current_token^.value.int_value);
|
write_c('<');
|
||||||
write_s("u>")
|
write_i(current_token^.value.int_value);
|
||||||
elsif current_token^.kind = TokenKind.character then
|
write_s("u>")
|
||||||
write_c('<');
|
| TokenKind.character:
|
||||||
write_i(cast(current_token^.value.char_value: Int));
|
write_c('<');
|
||||||
write_s("c>")
|
write_i(cast(current_token^.value.char_value: Int));
|
||||||
elsif current_token^.kind = TokenKind.string then
|
write_s("c>")
|
||||||
write_s("\"...\"")
|
| TokenKind.string:
|
||||||
elsif current_token^.kind = TokenKind._defer then
|
write_s("\"...\"")
|
||||||
write_s("DEFER")
|
| TokenKind._defer:
|
||||||
elsif current_token^.kind = TokenKind.exclamation then
|
write_s("DEFER")
|
||||||
write_c('!')
|
| TokenKind.exclamation:
|
||||||
elsif current_token^.kind = TokenKind.arrow then
|
write_c('!')
|
||||||
write_s("->")
|
| TokenKind.arrow:
|
||||||
else
|
write_s("->")
|
||||||
write_s("UNKNOWN<");
|
else
|
||||||
write_i(cast(current_token^.kind: Int));
|
write_s("UNKNOWN<");
|
||||||
write_c('>')
|
write_i(cast(current_token^.kind: Int));
|
||||||
|
write_c('>')
|
||||||
end;
|
end;
|
||||||
write_c(' ');
|
write_c(' ');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user