parser: port switch, slice, array literal, formatting tests

Port tests:
- "switch cases trailing comma"
- "slice align"
- "add trailing comma to array literal"
- "first thing in file is line comment"
- "line comment after doc comment"
- "bit field alignment"
- "nested switch"
- "float literal with exponent"
- "if-else end of comptime"
- "nested blocks"
- "statements with comment between"
- "statements with empty line between"
- "ptr deref operator and unwrap optional operator"

Fix in parser.c:
- switch_case SubRange stored via addExtra (not inline)
- Switch case body uses parseAssignExpr (not expectExpr)
- TOKEN_PERIOD_ASTERISK for deref in parseSuffixOp

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-02-10 18:58:51 +00:00
parent 64ce9659de
commit 50ea349da4
2 changed files with 186 additions and 2 deletions

View File

@@ -638,6 +638,12 @@ static AstNodeIndex parseSuffixOp(Parser* p, AstNodeIndex lhs) {
return 0; // tcc
}
case TOKEN_PERIOD_ASTERISK:
return addNode(&p->nodes,
(AstNodeItem) {
.tag = AST_NODE_DEREF,
.main_token = nextToken(p),
.data = { .lhs = lhs, .rhs = 0 },
});
case TOKEN_INVALID_PERIODASTERISKS:
fprintf(stderr, "parseSuffixOp does not support %s\n",
tokenizerGetTagString(tok));
@@ -1825,7 +1831,8 @@ static AstNodeIndex parseSwitchExpr(Parser* p) {
const AstTokenIndex arrow
= expectToken(p, TOKEN_EQUAL_ANGLE_BRACKET_RIGHT);
parsePtrPayload(p);
const AstNodeIndex case_body = expectExpr(p);
const AstNodeIndex case_body = parseAssignExpr(p);
assert(case_body != 0);
const uint32_t items_len = p->scratch.len - items_old_len;
AstNodeIndex case_node;
@@ -1851,7 +1858,11 @@ static AstNodeIndex parseSwitchExpr(Parser* p) {
(AstNodeItem) {
.tag = AST_NODE_SWITCH_CASE,
.main_token = arrow,
.data = { .lhs = span.start, .rhs = case_body },
.data = {
.lhs = addExtra(p,
(AstNodeIndex[]) { span.start, span.end }, 2),
.rhs = case_body,
},
});
} break;
}

View File

@@ -2566,6 +2566,179 @@ test "zig fmt: extra newlines at the end" {
);
}
test "zig fmt: switch cases trailing comma" {
try testTransform(
\\test "switch cases trailing comma"{
\\ switch (x) {
\\ 1,2,3 => {},
\\ 4,5, => {},
\\ 6... 8, => {},
\\ 9 ...
\\ 10 => {},
\\ 11 => {},
\\ 12, => {},
\\ else => {},
\\ }
\\}
,
\\test "switch cases trailing comma" {
\\ switch (x) {
\\ 1, 2, 3 => {},
\\ 4,
\\ 5,
\\ => {},
\\ 6...8,
\\ => {},
\\ 9...10 => {},
\\ 11 => {},
\\ 12,
\\ => {},
\\ else => {},
\\ }
\\}
\\
);
}
test "zig fmt: slice align" {
try testCanonical(
\\const A = struct {
\\ items: []align(A) T,
\\};
\\
);
}
test "zig fmt: add trailing comma to array literal" {
try testTransform(
\\comptime {
\\ return []u16{'m', 's', 'y', 's', '-' // hi
\\ };
\\ return []u16{'m', 's', 'y', 's',
\\ '-'};
\\ return []u16{'m', 's', 'y', 's', '-'};
\\}
,
\\comptime {
\\ return []u16{
\\ 'm', 's', 'y', 's', '-', // hi
\\ };
\\ return []u16{ 'm', 's', 'y', 's', '-' };
\\ return []u16{ 'm', 's', 'y', 's', '-' };
\\}
\\
);
}
test "zig fmt: first thing in file is line comment" {
try testCanonical(
\\// Introspection and determination of system libraries needed by zig.
\\
\\// Introspection and determination of system libraries needed by zig.
\\
\\const std = @import("std");
\\
);
}
test "zig fmt: line comment after doc comment" {
try testCanonical(
\\/// doc comment
\\// line comment
\\fn foo() void {}
\\
);
}
test "zig fmt: bit field alignment" {
try testCanonical(
\\test {
\\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
\\}
\\
);
}
test "zig fmt: nested switch" {
try testCanonical(
\\test {
\\ switch (state) {
\\ TermState.Start => switch (c) {
\\ '\x1b' => state = TermState.Escape,
\\ else => try out.writeByte(c),
\\ },
\\ }
\\}
\\
);
}
test "zig fmt: float literal with exponent" {
try testCanonical(
\\pub const f64_true_min = 4.94065645841246544177e-324;
\\const threshold = 0x1.a827999fcef32p+1022;
\\
);
}
test "zig fmt: if-else end of comptime" {
try testCanonical(
\\comptime {
\\ if (a) {
\\ b();
\\ } else {
\\ b();
\\ }
\\}
\\
);
}
test "zig fmt: nested blocks" {
try testCanonical(
\\comptime {
\\ {
\\ {
\\ {
\\ a();
\\ }
\\ }
\\ }
\\}
\\
);
}
test "zig fmt: statements with comment between" {
try testCanonical(
\\comptime {
\\ a = b;
\\ // comment
\\ a = b;
\\}
\\
);
}
test "zig fmt: statements with empty line between" {
try testCanonical(
\\comptime {
\\ a = b;
\\
\\ a = b;
\\}
\\
);
}
test "zig fmt: ptr deref operator and unwrap optional operator" {
try testCanonical(
\\const a = b.*;
\\const a = b.?;
\\
);
}
test "zig fmt: nested struct literal with one item" {
try testCanonical(
\\const a = foo{