parser: add container declaration and test decl tests
Port tests from upstream parser_test.zig: - "container declaration, one item, multi line trailing comma" - "container declaration, no trailing comma on separate line" - "container declaration, line break, no trailing comma" - "container declaration, transform trailing comma" - "container declaration, comment, add trailing comma" - "container declaration, multiline string, add trailing comma" - "container declaration, doc comment on member, add trailing comma" - "remove empty lines at start/end of container decl" Implement in parser.c: - Test declarations in parseContainerMembers - Comptime block/var statements in expectStatement - Variable declaration with initializer in expectVarDeclExprStatement - Regular assignment expressions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
68
parser.c
68
parser.c
@@ -1281,9 +1281,34 @@ static AstNodeIndex expectVarDeclExprStatement(Parser* p) {
|
||||
case TOKEN_SEMICOLON:
|
||||
p->tok_i++;
|
||||
return lhs;
|
||||
case TOKEN_EQUAL: {
|
||||
// Check if lhs is a var decl that needs initialization
|
||||
const AstNodeTag lhs_tag = p->nodes.tags[lhs];
|
||||
if (lhs_tag == AST_NODE_SIMPLE_VAR_DECL
|
||||
|| lhs_tag == AST_NODE_ALIGNED_VAR_DECL
|
||||
|| lhs_tag == AST_NODE_LOCAL_VAR_DECL
|
||||
|| lhs_tag == AST_NODE_GLOBAL_VAR_DECL) {
|
||||
p->tok_i++;
|
||||
p->nodes.datas[lhs].rhs = expectExpr(p);
|
||||
expectSemicolon(p);
|
||||
return lhs;
|
||||
}
|
||||
// Regular assignment expression
|
||||
const AstTokenIndex eq_token = nextToken(p);
|
||||
const AstNodeIndex rhs = expectExpr(p);
|
||||
expectSemicolon(p);
|
||||
return addNode(&p->nodes,
|
||||
(AstNodeItem) {
|
||||
.tag = AST_NODE_ASSIGN,
|
||||
.main_token = eq_token,
|
||||
.data = { .lhs = lhs, .rhs = rhs },
|
||||
});
|
||||
}
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"expectVarDeclExprStatement: assignment not implemented\n");
|
||||
"expectVarDeclExprStatement: assignment not implemented "
|
||||
"for token %s\n",
|
||||
tokenizerGetTagString(p->token_tags[p->tok_i]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1295,8 +1320,24 @@ static AstNodeIndex expectVarDeclExprStatement(Parser* p) {
|
||||
}
|
||||
|
||||
static AstNodeIndex expectStatement(Parser* p, bool allow_defer_var) {
|
||||
if (eatToken(p, TOKEN_KEYWORD_COMPTIME) != null_token) {
|
||||
fprintf(stderr, "expectStatement: comptime keyword not supported\n");
|
||||
const AstTokenIndex comptime_token = eatToken(p, TOKEN_KEYWORD_COMPTIME);
|
||||
if (comptime_token != null_token) {
|
||||
// comptime followed by block => comptime block statement
|
||||
const AstNodeIndex block = parseBlock(p);
|
||||
if (block != 0) {
|
||||
return addNode(&p->nodes,
|
||||
(AstNodeItem) {
|
||||
.tag = AST_NODE_COMPTIME,
|
||||
.main_token = comptime_token,
|
||||
.data = { .lhs = block, .rhs = 0 },
|
||||
});
|
||||
}
|
||||
// comptime var decl or expression
|
||||
if (allow_defer_var) {
|
||||
return expectVarDeclExprStatement(p);
|
||||
}
|
||||
fprintf(
|
||||
stderr, "expectStatement: comptime keyword not supported here\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1561,7 +1602,26 @@ static Members parseContainerMembers(Parser* p) {
|
||||
while (1) {
|
||||
eatDocComments(p);
|
||||
switch (p->token_tags[p->tok_i]) {
|
||||
case TOKEN_KEYWORD_TEST:
|
||||
case TOKEN_KEYWORD_TEST: {
|
||||
const AstTokenIndex test_token = nextToken(p);
|
||||
// test name can be a string literal or identifier, or omitted
|
||||
const AstTokenIndex test_name
|
||||
= (p->token_tags[p->tok_i] == TOKEN_STRING_LITERAL
|
||||
|| p->token_tags[p->tok_i] == TOKEN_IDENTIFIER)
|
||||
? nextToken(p)
|
||||
: 0;
|
||||
const AstNodeIndex body = parseBlock(p);
|
||||
assert(body != 0);
|
||||
const AstNodeIndex test_decl = addNode(&p->nodes,
|
||||
(AstNodeItem) {
|
||||
.tag = AST_NODE_TEST_DECL,
|
||||
.main_token = test_token,
|
||||
.data = { .lhs = test_name, .rhs = body },
|
||||
});
|
||||
SLICE_APPEND(AstNodeIndex, &p->scratch, test_decl);
|
||||
trailing = p->token_tags[p->tok_i - 1] == TOKEN_R_BRACE;
|
||||
break;
|
||||
}
|
||||
case TOKEN_KEYWORD_USINGNAMESPACE:;
|
||||
const char* str = tokenizerGetTagString(p->token_tags[p->tok_i]);
|
||||
fprintf(
|
||||
|
||||
139
parser_test.zig
139
parser_test.zig
@@ -734,3 +734,142 @@ test "zig fmt: container declaration, single line" {
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, one item, multi line trailing comma" {
|
||||
try testCanonical(
|
||||
\\test "" {
|
||||
\\ comptime {
|
||||
\\ const X = struct {
|
||||
\\ x: i32,
|
||||
\\ };
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, no trailing comma on separate line" {
|
||||
try testTransform(
|
||||
\\test "" {
|
||||
\\ comptime {
|
||||
\\ const X = struct {
|
||||
\\ x: i32
|
||||
\\ };
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
,
|
||||
\\test "" {
|
||||
\\ comptime {
|
||||
\\ const X = struct { x: i32 };
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, line break, no trailing comma" {
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\ foo: i32, bar: i8 };
|
||||
,
|
||||
\\const X = struct { foo: i32, bar: i8 };
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, transform trailing comma" {
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\ foo: i32, bar: i8, };
|
||||
,
|
||||
\\const X = struct {
|
||||
\\ foo: i32,
|
||||
\\ bar: i8,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, comment, add trailing comma" {
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\ foo: i32, // foo
|
||||
\\ bar: i8
|
||||
\\};
|
||||
,
|
||||
\\const X = struct {
|
||||
\\ foo: i32, // foo
|
||||
\\ bar: i8,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\ foo: i32 // foo
|
||||
\\};
|
||||
,
|
||||
\\const X = struct {
|
||||
\\ foo: i32, // foo
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, multiline string, add trailing comma" {
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\ foo: []const u8 =
|
||||
\\ \\ foo
|
||||
\\ ,
|
||||
\\ bar: i8
|
||||
\\};
|
||||
,
|
||||
\\const X = struct {
|
||||
\\ foo: []const u8 =
|
||||
\\ \\ foo
|
||||
\\ ,
|
||||
\\ bar: i8,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, doc comment on member, add trailing comma" {
|
||||
try testTransform(
|
||||
\\pub const Pos = struct {
|
||||
\\ /// X-axis.
|
||||
\\ x: u32,
|
||||
\\ /// Y-axis.
|
||||
\\ y: u32
|
||||
\\};
|
||||
,
|
||||
\\pub const Pos = struct {
|
||||
\\ /// X-axis.
|
||||
\\ x: u32,
|
||||
\\ /// Y-axis.
|
||||
\\ y: u32,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: remove empty lines at start/end of container decl" {
|
||||
try testTransform(
|
||||
\\const X = struct {
|
||||
\\
|
||||
\\ foo: i32,
|
||||
\\
|
||||
\\ bar: i8,
|
||||
\\
|
||||
\\};
|
||||
\\
|
||||
,
|
||||
\\const X = struct {
|
||||
\\ foo: i32,
|
||||
\\
|
||||
\\ bar: i8,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user