Switch statement
This commit is contained in:
parent
bb57af7642
commit
fa4ec4c156
168
src/compiler.bbb
168
src/compiler.bbb
@ -2738,9 +2738,27 @@ StatementWhile = struct
|
||||
block: &Block,
|
||||
}
|
||||
|
||||
StatementSwitchDiscriminantId = enum
|
||||
{
|
||||
single,
|
||||
range,
|
||||
}
|
||||
|
||||
StatementSwitchDiscriminantContent = union
|
||||
{
|
||||
single: &Value,
|
||||
range: [2]&Value,
|
||||
}
|
||||
|
||||
StatementSwitchDiscriminant = struct
|
||||
{
|
||||
content: StatementSwitchDiscriminantContent,
|
||||
id: StatementSwitchDiscriminantId,
|
||||
}
|
||||
|
||||
StatementSwitchClause = struct
|
||||
{
|
||||
values: []&Value,
|
||||
values: []StatementSwitchDiscriminant,
|
||||
block: &Block,
|
||||
}
|
||||
|
||||
@ -6014,7 +6032,148 @@ parse_statement = fn (module: &Module, scope: &Scope) &Statement
|
||||
},
|
||||
.switch =>
|
||||
{
|
||||
#trap();
|
||||
skip_space(module);
|
||||
expect_character(module, left_parenthesis);
|
||||
skip_space(module);
|
||||
|
||||
>discriminant = parse_value(module, scope, zero);
|
||||
|
||||
skip_space(module);
|
||||
expect_character(module, right_parenthesis);
|
||||
|
||||
skip_space(module);
|
||||
expect_character(module, left_brace);
|
||||
|
||||
>clause_buffer: [64]StatementSwitchClause = undefined;
|
||||
>clause_count: u64 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
>is_else: u1 = 0;
|
||||
if (is_identifier_start(module.content[module.offset]))
|
||||
{
|
||||
>else_checkpoint = get_checkpoint(module);
|
||||
>i = parse_identifier(module);
|
||||
is_else = string_equal(i, "else");
|
||||
|
||||
if (!is_else)
|
||||
{
|
||||
set_checkpoint(module, else_checkpoint);
|
||||
}
|
||||
}
|
||||
|
||||
>clause_values: []StatementSwitchDiscriminant = zero;
|
||||
|
||||
if (is_else)
|
||||
{
|
||||
skip_space(module);
|
||||
expect_character(module, '=');
|
||||
expect_character(module, '>');
|
||||
}
|
||||
else
|
||||
{
|
||||
>case_buffer: [64]StatementSwitchDiscriminant = undefined;
|
||||
>case_count: u64 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
>first_case_value = parse_value(module, scope, zero);
|
||||
|
||||
skip_space(module);
|
||||
|
||||
>checkpoint = get_checkpoint(module);
|
||||
>token = tokenize(module);
|
||||
|
||||
>clause_discriminant: StatementSwitchDiscriminant = undefined;
|
||||
|
||||
switch (token.id)
|
||||
{
|
||||
.triple_dot =>
|
||||
{
|
||||
>last_case_value = parse_value(module, scope, zero);
|
||||
clause_discriminant = {
|
||||
.content = {
|
||||
.range = [ first_case_value, last_case_value ],
|
||||
},
|
||||
.id = .range,
|
||||
};
|
||||
},
|
||||
else =>
|
||||
{
|
||||
if (token.id != .comma)
|
||||
{
|
||||
set_checkpoint(module, checkpoint);
|
||||
}
|
||||
|
||||
clause_discriminant = {
|
||||
.content = {
|
||||
.single = first_case_value,
|
||||
},
|
||||
.id = .single,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
switch (clause_discriminant.id)
|
||||
{
|
||||
.single => { assert(clause_discriminant.content.single != zero); },
|
||||
.range =>
|
||||
{
|
||||
assert(clause_discriminant.content.range[0] != zero);
|
||||
assert(clause_discriminant.content.range[1] != zero);
|
||||
},
|
||||
}
|
||||
|
||||
case_buffer[case_count] = clause_discriminant;
|
||||
case_count += 1;
|
||||
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, '='))
|
||||
{
|
||||
expect_character(module, '>');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clause_values = arena_allocate_slice[StatementSwitchDiscriminant](module.arena, case_count);
|
||||
memcpy(#pointer_cast(clause_values.pointer), #pointer_cast(&case_buffer), case_count * #byte_size(StatementSwitchDiscriminant));
|
||||
}
|
||||
|
||||
skip_space(module);
|
||||
|
||||
>clause_block = parse_block(module, scope);
|
||||
|
||||
clause_buffer[clause_count] = {
|
||||
.values = clause_values,
|
||||
.block = clause_block,
|
||||
};
|
||||
clause_count += 1;
|
||||
|
||||
consume_character_if_match(module, ',');
|
||||
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, right_brace))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
>clauses = arena_allocate_slice[StatementSwitchClause](module.arena, clause_count);
|
||||
memcpy(#pointer_cast(clauses.pointer), #pointer_cast(&clause_buffer), clause_count * #byte_size(StatementSwitchClause));
|
||||
|
||||
require_semicolon = 0;
|
||||
|
||||
statement.content = {
|
||||
.switch = {
|
||||
.discriminant = discriminant,
|
||||
.clauses = clauses,
|
||||
},
|
||||
};
|
||||
statement.id = .switch;
|
||||
},
|
||||
.break =>
|
||||
{
|
||||
@ -13013,6 +13172,10 @@ analyze_statement = fn (module: &Module, scope: &Scope, statement: &Statement) v
|
||||
},
|
||||
}
|
||||
},
|
||||
.switch =>
|
||||
{
|
||||
#trap();
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -14457,6 +14620,7 @@ names: [_][]u8 =
|
||||
"string_to_enum",
|
||||
"empty_if",
|
||||
"else_if",
|
||||
"else_if_complicated",
|
||||
];
|
||||
|
||||
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32
|
||||
|
Loading…
x
Reference in New Issue
Block a user