diff --git a/parser.c b/parser.c index 0b9440a228..8dec9f51a7 100644 --- a/parser.c +++ b/parser.c @@ -862,9 +862,71 @@ static AstNodeIndex parseTypeExpr(Parser* p) { case TOKEN_L_BRACKET: { const AstTokenIndex lbracket = nextToken(p); if (p->token_tags[p->tok_i] == TOKEN_ASTERISK) { - fprintf( - stderr, "parseTypeExpr: [*] pointer types not implemented\n"); - exit(1); + // [*] many-item pointer, [*c] C pointer, [*:s] sentinel + p->tok_i++; // consume * + AstNodeIndex sentinel = 0; + if (p->token_tags[p->tok_i] == TOKEN_IDENTIFIER) { + // Check for 'c' modifier: [*c] + // The 'c' is a regular identifier token + const char c = p->source[p->token_starts[p->tok_i]]; + if (c == 'c' + && p->token_starts[p->tok_i + 1] + - p->token_starts[p->tok_i] + <= 2) { + p->tok_i++; // consume 'c' + } + } else if (eatToken(p, TOKEN_COLON) != null_token) { + sentinel = expectExpr(p); + } + expectToken(p, TOKEN_R_BRACKET); + // const/volatile/allowzero pointer modifiers + 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 align_expr = parseByteAlign(p); + const AstNodeIndex addrspace_expr = parseAddrSpace(p); + // const/volatile/allowzero again (can appear before or after + // align) + 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) { + if (addrspace_expr != 0) { + fprintf(stderr, + "parseTypeExpr: [*:s] with addrspace not " + "implemented\n"); + exit(1); + } + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_PTR_TYPE_SENTINEL, + .main_token = lbracket, + .data = { .lhs = sentinel, .rhs = elem_type }, + }); + } + if (addrspace_expr != 0) { + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_PTR_TYPE, + .main_token = lbracket, + .data = { + .lhs = addExtra(p, + (AstNodeIndex[]) { + 0, align_expr, addrspace_expr }, + 3), + .rhs = elem_type, + }, + }); + } + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_PTR_TYPE_ALIGNED, + .main_token = lbracket, + .data = { .lhs = align_expr, .rhs = elem_type }, + }); } const AstNodeIndex len_expr = parseExpr(p); const AstNodeIndex sentinel diff --git a/parser_test.zig b/parser_test.zig index 98058ad810..6c0d6966d0 100644 --- a/parser_test.zig +++ b/parser_test.zig @@ -1810,6 +1810,13 @@ test "zig fmt: nosuspend block" { ); } +test "zig fmt: c pointer type" { + try testCanonical( + \\pub extern fn repro() [*c]const u8; + \\ + ); +} + test "zig fmt: top-level tuple function call type" { try testCanonical( \\foo()