parser: add slicing and tagged union tests

Port tests from upstream parser_test.zig:
- "slices" (open, closed, sentinel-terminated)
- "tagged union with enum values"
- "tagged union enum tag last token"

Implement in parser.c:
- Slice expressions in parseSuffixOp: slice_open, slice,
  slice_sentinel
- Handle OptionalIndex encoding for absent slice end expr

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-02-10 13:02:01 +00:00
parent 8705fd0197
commit b2b1d8f188
2 changed files with 89 additions and 3 deletions

View File

@@ -571,9 +571,49 @@ static AstNodeIndex parseSuffixOp(Parser* p, AstNodeIndex lhs) {
.main_token = lbracket, .main_token = lbracket,
.data = { .lhs = lhs, .rhs = index_expr }, .data = { .lhs = lhs, .rhs = index_expr },
}); });
case TOKEN_ELLIPSIS2: case TOKEN_ELLIPSIS2: {
fprintf(stderr, "parseSuffixOp: slicing not implemented\n"); p->tok_i++; // consume ..
exit(1); const AstNodeIndex end_expr = parseExpr(p);
if (eatToken(p, TOKEN_COLON) != null_token) {
const AstNodeIndex sentinel = expectExpr(p);
expectToken(p, TOKEN_R_BRACKET);
// end_expr 0 means "no end" — encode as ~0 for
// OptionalIndex.none
const AstNodeIndex opt_end
= end_expr == 0 ? ~(AstNodeIndex)0 : end_expr;
return addNode(&p->nodes,
(AstNodeItem) {
.tag = AST_NODE_SLICE_SENTINEL,
.main_token = lbracket,
.data = {
.lhs = lhs,
.rhs = addExtra(p,
(AstNodeIndex[]) {
index_expr, opt_end, sentinel },
3),
},
});
}
expectToken(p, TOKEN_R_BRACKET);
if (end_expr == 0) {
return addNode(&p->nodes,
(AstNodeItem) {
.tag = AST_NODE_SLICE_OPEN,
.main_token = lbracket,
.data = { .lhs = lhs, .rhs = index_expr },
});
}
return addNode(&p->nodes,
(AstNodeItem) {
.tag = AST_NODE_SLICE,
.main_token = lbracket,
.data = {
.lhs = lhs,
.rhs = addExtra(p,
(AstNodeIndex[]) { index_expr, end_expr }, 2),
},
});
}
default: default:
fprintf( fprintf(
stderr, "parseSuffixOp: expected ] or .. after index expr\n"); stderr, "parseSuffixOp: expected ] or .. after index expr\n");

View File

@@ -1206,3 +1206,49 @@ test "zig fmt: array literal 3 element comma" {
\\ \\
); );
} }
test "zig fmt: slices" {
try testCanonical(
\\const a = b[0..];
\\const c = d[0..1];
\\const d = f[0.. :0];
\\const e = f[0..1 :0];
\\
);
}
test "zig fmt: tagged union with enum values" {
try testCanonical(
\\const MultipleChoice2 = union(enum(u32)) {
\\ Unspecified1: i32,
\\ A: f32 = 20,
\\ Unspecified2: void,
\\ B: bool = 40,
\\ Unspecified3: i32,
\\ C: i8 = 60,
\\ Unspecified4: void,
\\ D: void = 1000,
\\ Unspecified5: i32,
\\};
\\
);
}
test "zig fmt: tagged union enum tag last token" {
try testCanonical(
\\test {
\\ const U = union(enum(u32)) {};
\\}
\\
\\test {
\\ const U = union(enum(u32)) { foo };
\\}
\\
\\test {
\\ const U = union(enum(u32)) {
\\ foo,
\\ };
\\}
\\
);
}