diff --git a/parser.c b/parser.c index 3feb7aba35..af27234f64 100644 --- a/parser.c +++ b/parser.c @@ -638,6 +638,12 @@ static AstNodeIndex parseSuffixOp(Parser* p, AstNodeIndex lhs) { return 0; // tcc } case TOKEN_PERIOD_ASTERISK: + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_DEREF, + .main_token = nextToken(p), + .data = { .lhs = lhs, .rhs = 0 }, + }); case TOKEN_INVALID_PERIODASTERISKS: fprintf(stderr, "parseSuffixOp does not support %s\n", tokenizerGetTagString(tok)); @@ -1825,7 +1831,8 @@ static AstNodeIndex parseSwitchExpr(Parser* p) { const AstTokenIndex arrow = expectToken(p, TOKEN_EQUAL_ANGLE_BRACKET_RIGHT); parsePtrPayload(p); - const AstNodeIndex case_body = expectExpr(p); + const AstNodeIndex case_body = parseAssignExpr(p); + assert(case_body != 0); const uint32_t items_len = p->scratch.len - items_old_len; AstNodeIndex case_node; @@ -1851,7 +1858,11 @@ static AstNodeIndex parseSwitchExpr(Parser* p) { (AstNodeItem) { .tag = AST_NODE_SWITCH_CASE, .main_token = arrow, - .data = { .lhs = span.start, .rhs = case_body }, + .data = { + .lhs = addExtra(p, + (AstNodeIndex[]) { span.start, span.end }, 2), + .rhs = case_body, + }, }); } break; } diff --git a/parser_test.zig b/parser_test.zig index f44995c6e1..f22c8bc20d 100644 --- a/parser_test.zig +++ b/parser_test.zig @@ -2566,6 +2566,179 @@ test "zig fmt: extra newlines at the end" { ); } +test "zig fmt: switch cases trailing comma" { + try testTransform( + \\test "switch cases trailing comma"{ + \\ switch (x) { + \\ 1,2,3 => {}, + \\ 4,5, => {}, + \\ 6... 8, => {}, + \\ 9 ... + \\ 10 => {}, + \\ 11 => {}, + \\ 12, => {}, + \\ else => {}, + \\ } + \\} + , + \\test "switch cases trailing comma" { + \\ switch (x) { + \\ 1, 2, 3 => {}, + \\ 4, + \\ 5, + \\ => {}, + \\ 6...8, + \\ => {}, + \\ 9...10 => {}, + \\ 11 => {}, + \\ 12, + \\ => {}, + \\ else => {}, + \\ } + \\} + \\ + ); +} + +test "zig fmt: slice align" { + try testCanonical( + \\const A = struct { + \\ items: []align(A) T, + \\}; + \\ + ); +} + +test "zig fmt: add trailing comma to array literal" { + try testTransform( + \\comptime { + \\ return []u16{'m', 's', 'y', 's', '-' // hi + \\ }; + \\ return []u16{'m', 's', 'y', 's', + \\ '-'}; + \\ return []u16{'m', 's', 'y', 's', '-'}; + \\} + , + \\comptime { + \\ return []u16{ + \\ 'm', 's', 'y', 's', '-', // hi + \\ }; + \\ return []u16{ 'm', 's', 'y', 's', '-' }; + \\ return []u16{ 'm', 's', 'y', 's', '-' }; + \\} + \\ + ); +} + +test "zig fmt: first thing in file is line comment" { + try testCanonical( + \\// Introspection and determination of system libraries needed by zig. + \\ + \\// Introspection and determination of system libraries needed by zig. + \\ + \\const std = @import("std"); + \\ + ); +} + +test "zig fmt: line comment after doc comment" { + try testCanonical( + \\/// doc comment + \\// line comment + \\fn foo() void {} + \\ + ); +} + +test "zig fmt: bit field alignment" { + try testCanonical( + \\test { + \\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3); + \\} + \\ + ); +} + +test "zig fmt: nested switch" { + try testCanonical( + \\test { + \\ switch (state) { + \\ TermState.Start => switch (c) { + \\ '\x1b' => state = TermState.Escape, + \\ else => try out.writeByte(c), + \\ }, + \\ } + \\} + \\ + ); +} + +test "zig fmt: float literal with exponent" { + try testCanonical( + \\pub const f64_true_min = 4.94065645841246544177e-324; + \\const threshold = 0x1.a827999fcef32p+1022; + \\ + ); +} + +test "zig fmt: if-else end of comptime" { + try testCanonical( + \\comptime { + \\ if (a) { + \\ b(); + \\ } else { + \\ b(); + \\ } + \\} + \\ + ); +} + +test "zig fmt: nested blocks" { + try testCanonical( + \\comptime { + \\ { + \\ { + \\ { + \\ a(); + \\ } + \\ } + \\ } + \\} + \\ + ); +} + +test "zig fmt: statements with comment between" { + try testCanonical( + \\comptime { + \\ a = b; + \\ // comment + \\ a = b; + \\} + \\ + ); +} + +test "zig fmt: statements with empty line between" { + try testCanonical( + \\comptime { + \\ a = b; + \\ + \\ a = b; + \\} + \\ + ); +} + +test "zig fmt: ptr deref operator and unwrap optional operator" { + try testCanonical( + \\const a = b.*; + \\const a = b.?; + \\ + ); +} + test "zig fmt: nested struct literal with one item" { try testCanonical( \\const a = foo{