diff --git a/parser.c b/parser.c index 95e10c67ce..b832beaf38 100644 --- a/parser.c +++ b/parser.c @@ -533,16 +533,67 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { } static AstNodeIndex parseSuffixOp(Parser* p, AstNodeIndex lhs) { - (void)lhs; const TokenizerTag tok = p->token_tags[p->tok_i]; switch (tok) { - case TOKEN_L_BRACKET: + case TOKEN_L_BRACKET: { + const AstTokenIndex lbracket = nextToken(p); + const AstNodeIndex index_expr = expectExpr(p); + switch (p->token_tags[p->tok_i]) { + case TOKEN_R_BRACKET: + p->tok_i++; + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_ARRAY_ACCESS, + .main_token = lbracket, + .data = { .lhs = lhs, .rhs = index_expr }, + }); + case TOKEN_ELLIPSIS2: + fprintf(stderr, "parseSuffixOp: slicing not implemented\n"); + exit(1); + default: + fprintf( + stderr, "parseSuffixOp: expected ] or .. after index expr\n"); + exit(1); + } + return 0; // tcc + } case TOKEN_PERIOD_ASTERISK: case TOKEN_INVALID_PERIODASTERISKS: - case TOKEN_PERIOD: fprintf(stderr, "parseSuffixOp does not support %s\n", tokenizerGetTagString(tok)); exit(1); + case TOKEN_PERIOD: + if (p->token_tags[p->tok_i + 1] == TOKEN_IDENTIFIER) { + const AstTokenIndex dot = nextToken(p); + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_FIELD_ACCESS, + .main_token = dot, + .data = { .lhs = lhs, .rhs = nextToken(p) }, + }); + } + if (p->token_tags[p->tok_i + 1] == TOKEN_ASTERISK) { + const AstTokenIndex dot = nextToken(p); + nextToken(p); // consume the * + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_DEREF, + .main_token = dot, + .data = { .lhs = lhs, .rhs = 0 }, + }); + } + if (p->token_tags[p->tok_i + 1] == TOKEN_QUESTION_MARK) { + const AstTokenIndex dot = nextToken(p); + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_UNWRAP_OPTIONAL, + .main_token = dot, + .data = { .lhs = lhs, .rhs = nextToken(p) }, + }); + } + fprintf(stderr, "parseSuffixOp: unsupported period suffix\n"); + exit(1); + return 0; // tcc default: return null_node; } @@ -1521,13 +1572,13 @@ static Members parseContainerMembers(Parser* p) { // block/decl. Check if it's followed by a block (comptime { ... // }). if (p->token_tags[p->tok_i + 1] == TOKEN_L_BRACE) { - p->tok_i++; + const AstTokenIndex comptime_token = nextToken(p); const AstNodeIndex block_node = parseBlock(p); SLICE_APPEND(AstNodeIndex, &p->scratch, addNode(&p->nodes, (AstNodeItem) { .tag = AST_NODE_COMPTIME, - .main_token = p->tok_i - 1, + .main_token = comptime_token, .data = { .lhs = block_node, .rhs = 0 }, })); trailing = p->token_tags[p->tok_i - 1] == TOKEN_R_BRACE; diff --git a/parser_test.zig b/parser_test.zig index d8429c1dd6..0bcd3a0b0f 100644 --- a/parser_test.zig +++ b/parser_test.zig @@ -234,8 +234,6 @@ fn zigData(tag: Ast.Node.Tag, lhs: u32, rhs: u32) Ast.Node.Data { .container_field_align, .error_union, .@"catch", - .field_access, - .unwrap_optional, .equal_equal, .bang_equal, .less_than, @@ -378,6 +376,8 @@ fn zigData(tag: Ast.Node.Tag, lhs: u32, rhs: u32) Ast.Node.Data { // .node_and_token .grouped_expression, .asm_input, + .field_access, + .unwrap_optional, => .{ .node_and_token = .{ toIndex(lhs), rhs } }, // .opt_node_and_token @@ -599,3 +599,53 @@ test "zig fmt: respect line breaks in struct field value declaration" { \\ ); } + +test "zig fmt: respect line breaks before functions" { + try testCanonical( + \\const std = @import("std"); + \\ + \\inline fn foo() void {} + \\ + \\noinline fn foo() void {} + \\ + \\export fn foo() void {} + \\ + \\extern fn foo() void; + \\ + \\extern "foo" fn foo() void; + \\ + ); +} + +test "zig fmt: simple top level comptime block" { + try testCanonical( + \\// line comment + \\comptime {} + \\ + ); +} + +test "zig fmt: two spaced line comments before decl" { + try testCanonical( + \\// line comment + \\ + \\// another + \\comptime {} + \\ + ); +} + +test "zig fmt: respect line breaks after var declarations" { + try testCanonical( + \\const crc = + \\ lookup_tables[0][p[7]] ^ + \\ lookup_tables[1][p[6]] ^ + \\ lookup_tables[2][p[5]] ^ + \\ lookup_tables[3][p[4]] ^ + \\ lookup_tables[4][@as(u8, self.crc >> 24)] ^ + \\ lookup_tables[5][@as(u8, self.crc >> 16)] ^ + \\ lookup_tables[6][@as(u8, self.crc >> 8)] ^ + \\ lookup_tables[7][@as(u8, self.crc >> 0)]; + \\ + ); +}