Improve parsing for label: #reverse for and label: #partial switch

This commit is contained in:
gingerBill
2024-06-10 14:18:33 +01:00
parent bedeaa34d9
commit 1945218f6d
2 changed files with 40 additions and 3 deletions

View File

@@ -1455,7 +1455,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
case "unroll":
return parse_unrolled_for_loop(p, tag)
case "reverse":
stmt := parse_for_stmt(p)
stmt := parse_stmt(p)
if range, is_range := stmt.derived.(^ast.Range_Stmt); is_range {
if range.reverse {
@@ -3515,6 +3515,25 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
case op.kind == .Colon:
expect_token_after(p, .Colon, "identifier list")
if .Label in flags && len(lhs) == 1 {
is_partial := false
is_reverse := false
partial_token: tokenizer.Token
if p.curr_tok.kind == .Hash {
name := peek_token(p)
if name.kind == .Ident && name.text == "partial" &&
peek_token(p, 1).kind == .Switch {
partial_token = expect_token(p, .Hash)
expect_token(p, .Ident)
is_partial = true
} else if name.kind == .Ident && name.text == "reverse" &&
peek_token(p, 1).kind == .For {
partial_token = expect_token(p, .Hash)
expect_token(p, .Ident)
is_reverse = true
}
}
#partial switch p.curr_tok.kind {
case .Open_Brace, .If, .For, .Switch:
label := lhs[0]
@@ -3529,6 +3548,22 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
case ^ast.Type_Switch_Stmt: n.label = label
case ^ast.Range_Stmt: n.label = label
}
if is_partial {
#partial switch n in stmt.derived_stmt {
case ^ast.Switch_Stmt: n.partial = true
case ^ast.Type_Switch_Stmt: n.partial = true
case:
error(p, partial_token.pos, "incorrect use of directive, use '%s: #partial switch'", partial_token.text)
}
}
if is_reverse {
#partial switch n in stmt.derived_stmt {
case ^ast.Range_Stmt: n.reverse = true
case:
error(p, partial_token.pos, "incorrect use of directive, use '%s: #reverse for'", partial_token.text)
}
}
}
return stmt

View File

@@ -3747,8 +3747,10 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
case Ast_TypeSwitchStmt:
stmt->TypeSwitchStmt.partial = true;
break;
default:
syntax_error(partial_token, "Incorrect use of directive, use '%.*s: #partial switch'", LIT(ast_token(name).string));
break;
}
syntax_error(partial_token, "Incorrect use of directive, use '#partial %.*s: switch'", LIT(ast_token(name).string));
} else if (is_reverse) {
switch (stmt->kind) {
case Ast_RangeStmt:
@@ -5176,7 +5178,7 @@ gb_internal Ast *parse_stmt(AstFile *f) {
} else if (tag == "unroll") {
return parse_unrolled_for_loop(f, name);
} else if (tag == "reverse") {
Ast *for_stmt = parse_for_stmt(f);
Ast *for_stmt = parse_stmt(f);
if (for_stmt->kind == Ast_RangeStmt) {
if (for_stmt->RangeStmt.reverse) {
syntax_error(token, "#reverse already applied to a 'for in' statement");