parser: add struct field value declaration test
Port "zig fmt: respect line breaks in struct field value declaration" test from upstream parser_test.zig. Implement in parser.c: - Slice types ([]T, [:s]T) in parseTypeExpr - Array types ([N]T, [N:s]T) in parseTypeExpr - Multiline string literals in parsePrimaryTypeExpr - Add comments explaining why const/volatile/allowzero pointer modifiers are consumed (not stored in AST; renderer re-derives them from token positions) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
81
parser.c
81
parser.c
@@ -483,10 +483,18 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) {
|
|||||||
.main_token = nextToken(p),
|
.main_token = nextToken(p),
|
||||||
.data = { .lhs = parseTypeExpr(p), .rhs = 0 },
|
.data = { .lhs = parseTypeExpr(p), .rhs = 0 },
|
||||||
});
|
});
|
||||||
case TOKEN_MULTILINE_STRING_LITERAL_LINE:
|
case TOKEN_MULTILINE_STRING_LITERAL_LINE: {
|
||||||
fprintf(stderr, "parsePrimaryTypeExpr does not support %s\n",
|
const AstTokenIndex first = nextToken(p);
|
||||||
tokenizerGetTagString(tok));
|
AstTokenIndex last = first;
|
||||||
exit(1);
|
while (p->token_tags[p->tok_i] == TOKEN_MULTILINE_STRING_LITERAL_LINE)
|
||||||
|
last = nextToken(p);
|
||||||
|
return addNode(&p->nodes,
|
||||||
|
(AstNodeItem) {
|
||||||
|
.tag = AST_NODE_MULTILINE_STRING_LITERAL,
|
||||||
|
.main_token = first,
|
||||||
|
.data = { .lhs = first, .rhs = last },
|
||||||
|
});
|
||||||
|
}
|
||||||
case TOKEN_IDENTIFIER:
|
case TOKEN_IDENTIFIER:
|
||||||
if (p->token_tags[p->tok_i + 1] == TOKEN_COLON) {
|
if (p->token_tags[p->tok_i + 1] == TOKEN_COLON) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -670,7 +678,9 @@ static AstNodeIndex parseTypeExpr(Parser* p) {
|
|||||||
const AstNodeIndex align_expr = parseByteAlign(p);
|
const AstNodeIndex align_expr = parseByteAlign(p);
|
||||||
const AstNodeIndex sentinel
|
const AstNodeIndex sentinel
|
||||||
= eatToken(p, TOKEN_COLON) != null_token ? parseExpr(p) : 0;
|
= eatToken(p, TOKEN_COLON) != null_token ? parseExpr(p) : 0;
|
||||||
// skip const/volatile/allowzero modifiers
|
// const/volatile/allowzero are pointer modifiers consumed here.
|
||||||
|
// They are not stored in the AST node; the renderer re-derives
|
||||||
|
// them from token positions.
|
||||||
while (p->token_tags[p->tok_i] == TOKEN_KEYWORD_CONST
|
while (p->token_tags[p->tok_i] == TOKEN_KEYWORD_CONST
|
||||||
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_VOLATILE
|
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_VOLATILE
|
||||||
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_ALLOWZERO)
|
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_ALLOWZERO)
|
||||||
@@ -703,10 +713,63 @@ static AstNodeIndex parseTypeExpr(Parser* p) {
|
|||||||
fprintf(stderr, "parseTypeExpr not supported for %s\n",
|
fprintf(stderr, "parseTypeExpr not supported for %s\n",
|
||||||
tokenizerGetTagString(tok));
|
tokenizerGetTagString(tok));
|
||||||
exit(1);
|
exit(1);
|
||||||
case TOKEN_L_BRACKET:
|
case TOKEN_L_BRACKET: {
|
||||||
fprintf(stderr, "parseTypeExpr not supported for %s\n",
|
const AstTokenIndex lbracket = nextToken(p);
|
||||||
tokenizerGetTagString(tok));
|
if (p->token_tags[p->tok_i] == TOKEN_ASTERISK) {
|
||||||
exit(1);
|
fprintf(
|
||||||
|
stderr, "parseTypeExpr: [*] pointer types not implemented\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
const AstNodeIndex len_expr = parseExpr(p);
|
||||||
|
const AstNodeIndex sentinel
|
||||||
|
= eatToken(p, TOKEN_COLON) != null_token ? expectExpr(p) : 0;
|
||||||
|
expectToken(p, TOKEN_R_BRACKET);
|
||||||
|
if (len_expr == 0) {
|
||||||
|
// Slice type: []T or [:s]T
|
||||||
|
// const/volatile/allowzero are pointer modifiers consumed here.
|
||||||
|
// They are not stored in the AST node; the renderer re-derives
|
||||||
|
// them from token positions.
|
||||||
|
while (p->token_tags[p->tok_i] == TOKEN_KEYWORD_CONST
|
||||||
|
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_VOLATILE
|
||||||
|
|| p->token_tags[p->tok_i] == TOKEN_KEYWORD_ALLOWZERO)
|
||||||
|
p->tok_i++;
|
||||||
|
const AstNodeIndex elem_type = parseTypeExpr(p);
|
||||||
|
if (sentinel != 0) {
|
||||||
|
return addNode(&p->nodes,
|
||||||
|
(AstNodeItem) {
|
||||||
|
.tag = AST_NODE_PTR_TYPE_SENTINEL,
|
||||||
|
.main_token = lbracket,
|
||||||
|
.data = { .lhs = sentinel, .rhs = elem_type },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return addNode(&p->nodes,
|
||||||
|
(AstNodeItem) {
|
||||||
|
.tag = AST_NODE_PTR_TYPE_ALIGNED,
|
||||||
|
.main_token = lbracket,
|
||||||
|
.data = { .lhs = 0, .rhs = elem_type },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Array type: [N]T or [N:s]T
|
||||||
|
const AstNodeIndex elem_type = parseTypeExpr(p);
|
||||||
|
if (sentinel == 0) {
|
||||||
|
return addNode(&p->nodes,
|
||||||
|
(AstNodeItem) {
|
||||||
|
.tag = AST_NODE_ARRAY_TYPE,
|
||||||
|
.main_token = lbracket,
|
||||||
|
.data = { .lhs = len_expr, .rhs = elem_type },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return addNode(&p->nodes,
|
||||||
|
(AstNodeItem) {
|
||||||
|
.tag = AST_NODE_ARRAY_TYPE_SENTINEL,
|
||||||
|
.main_token = lbracket,
|
||||||
|
.data = {
|
||||||
|
.lhs = len_expr,
|
||||||
|
.rhs = addExtra(p,
|
||||||
|
(AstNodeIndex[]) { sentinel, elem_type }, 2),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return parseErrorUnionExpr(p);
|
return parseErrorUnionExpr(p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -574,3 +574,28 @@ test "zig fmt: tuple struct" {
|
|||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "zig fmt: respect line breaks in struct field value declaration" {
|
||||||
|
try testCanonical(
|
||||||
|
\\const Foo = struct {
|
||||||
|
\\ bar: u32 =
|
||||||
|
\\ 42,
|
||||||
|
\\ bar: u32 =
|
||||||
|
\\ // a comment
|
||||||
|
\\ 42,
|
||||||
|
\\ bar: u32 =
|
||||||
|
\\ 42,
|
||||||
|
\\ // a comment
|
||||||
|
\\ bar: []const u8 =
|
||||||
|
\\ \\ foo
|
||||||
|
\\ \\ bar
|
||||||
|
\\ \\ baz
|
||||||
|
\\ ,
|
||||||
|
\\ bar: u32 =
|
||||||
|
\\ blk: {
|
||||||
|
\\ break :blk 42;
|
||||||
|
\\ },
|
||||||
|
\\};
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user