authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-03 13:10:26-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-03 13:10:26-08:00
logce480dedbb1e8b9a13a0f138d8aa1ec04b7884c8
treeaf6dc37df0dc6a3ff4278cecb0655579aa8e880b
parenta9337bef2d54201ab304bb3428479339ecaacbac
parent75b3feee05eb8b08fc6441a7e45fd9269ae7bee4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #18403 from FnControlOption/parse

std.zig: Miscellaneous cleanup

2 files changed, 78 insertions(+), 126 deletions(-)

lib/std/zig/Ast.zig+8-8
...@@ -1433,8 +1433,8 @@ pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {...@@ -1433,8 +1433,8 @@ pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {
1433 return tree.fullContainerFieldComponents(.{1433 return tree.fullContainerFieldComponents(.{
1434 .main_token = main_token,1434 .main_token = main_token,
1435 .type_expr = data.lhs,1435 .type_expr = data.lhs,
1436 .value_expr = extra.value_expr,
1437 .align_expr = extra.align_expr,1436 .align_expr = extra.align_expr,
1437 .value_expr = extra.value_expr,
1438 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1438 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1439 tree.tokens.items(.tag)[main_token + 1] != .colon,1439 tree.tokens.items(.tag)[main_token + 1] != .colon,
1440 });1440 });
...@@ -1447,8 +1447,8 @@ pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {...@@ -1447,8 +1447,8 @@ pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {
1447 return tree.fullContainerFieldComponents(.{1447 return tree.fullContainerFieldComponents(.{
1448 .main_token = main_token,1448 .main_token = main_token,
1449 .type_expr = data.lhs,1449 .type_expr = data.lhs,
1450 .value_expr = data.rhs,
1451 .align_expr = 0,1450 .align_expr = 0,
1451 .value_expr = data.rhs,
1452 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1452 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1453 tree.tokens.items(.tag)[main_token + 1] != .colon,1453 tree.tokens.items(.tag)[main_token + 1] != .colon,
1454 });1454 });
...@@ -1461,8 +1461,8 @@ pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {...@@ -1461,8 +1461,8 @@ pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {
1461 return tree.fullContainerFieldComponents(.{1461 return tree.fullContainerFieldComponents(.{
1462 .main_token = main_token,1462 .main_token = main_token,
1463 .type_expr = data.lhs,1463 .type_expr = data.lhs,
1464 .value_expr = 0,
1465 .align_expr = data.rhs,1464 .align_expr = data.rhs,
1465 .value_expr = 0,
1466 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1466 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1467 tree.tokens.items(.tag)[main_token + 1] != .colon,1467 tree.tokens.items(.tag)[main_token + 1] != .colon,
1468 });1468 });
...@@ -2565,8 +2565,8 @@ pub const full = struct {...@@ -2565,8 +2565,8 @@ pub const full = struct {
2565 pub const Components = struct {2565 pub const Components = struct {
2566 main_token: TokenIndex,2566 main_token: TokenIndex,
2567 type_expr: Node.Index,2567 type_expr: Node.Index,
2568 value_expr: Node.Index,
2569 align_expr: Node.Index,2568 align_expr: Node.Index,
2569 value_expr: Node.Index,
2570 tuple_like: bool,2570 tuple_like: bool,
2571 };2571 };
25722572
...@@ -3269,13 +3269,13 @@ pub const Node = struct {...@@ -3269,13 +3269,13 @@ pub const Node = struct {
3269 /// main_token is the `fn` keyword.3269 /// main_token is the `fn` keyword.
3270 /// extern function declarations use this tag.3270 /// extern function declarations use this tag.
3271 fn_proto_multi,3271 fn_proto_multi,
3272 /// `fn (a: b) rhs addrspace(e) linksection(f) callconv(g)`. `FnProtoOne[lhs]`.3272 /// `fn (a: b) addrspace(e) linksection(f) callconv(g) rhs`. `FnProtoOne[lhs]`.
3273 /// zero or one parameters.3273 /// zero or one parameters.
3274 /// anytype and ... parameters are omitted from the AST tree.3274 /// anytype and ... parameters are omitted from the AST tree.
3275 /// main_token is the `fn` keyword.3275 /// main_token is the `fn` keyword.
3276 /// extern function declarations use this tag.3276 /// extern function declarations use this tag.
3277 fn_proto_one,3277 fn_proto_one,
3278 /// `fn (a: b, c: d) rhs addrspace(e) linksection(f) callconv(g)`. `FnProto[lhs]`.3278 /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) rhs`. `FnProto[lhs]`.
3279 /// anytype and ... parameters are omitted from the AST tree.3279 /// anytype and ... parameters are omitted from the AST tree.
3280 /// main_token is the `fn` keyword.3280 /// main_token is the `fn` keyword.
3281 /// extern function declarations use this tag.3281 /// extern function declarations use this tag.
...@@ -3427,8 +3427,8 @@ pub const Node = struct {...@@ -3427,8 +3427,8 @@ pub const Node = struct {
3427 };3427 };
34283428
3429 pub const ArrayTypeSentinel = struct {3429 pub const ArrayTypeSentinel = struct {
3430 elem_type: Index,
3431 sentinel: Index,3430 sentinel: Index,
3431 elem_type: Index,
3432 };3432 };
34333433
3434 pub const PtrType = struct {3434 pub const PtrType = struct {
...@@ -3458,8 +3458,8 @@ pub const Node = struct {...@@ -3458,8 +3458,8 @@ pub const Node = struct {
3458 };3458 };
34593459
3460 pub const ContainerField = struct {3460 pub const ContainerField = struct {
3461 value_expr: Index,
3462 align_expr: Index,3461 align_expr: Index,
3462 value_expr: Index,
3463 };3463 };
34643464
3465 pub const GlobalVarDecl = struct {3465 pub const GlobalVarDecl = struct {
lib/std/zig/Parse.zig+70-118
...@@ -210,7 +210,7 @@ pub fn parseZon(p: *Parse) !void {...@@ -210,7 +210,7 @@ pub fn parseZon(p: *Parse) !void {
210/// ContainerDeclaration <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl210/// ContainerDeclaration <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl
211///211///
212/// ComptimeDecl <- KEYWORD_comptime Block212/// ComptimeDecl <- KEYWORD_comptime Block
213fn parseContainerMembers(p: *Parse) !Members {213fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
214 const scratch_top = p.scratch.items.len;214 const scratch_top = p.scratch.items.len;
215 defer p.scratch.shrinkRetainingCapacity(scratch_top);215 defer p.scratch.shrinkRetainingCapacity(scratch_top);
216216
...@@ -565,12 +565,9 @@ fn findNextStmt(p: *Parse) void {...@@ -565,12 +565,9 @@ fn findNextStmt(p: *Parse) void {
565/// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block565/// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block
566fn expectTestDecl(p: *Parse) !Node.Index {566fn expectTestDecl(p: *Parse) !Node.Index {
567 const test_token = p.assertToken(.keyword_test);567 const test_token = p.assertToken(.keyword_test);
568 const name_token = switch (p.token_tags[p.nextToken()]) {568 const name_token = switch (p.token_tags[p.tok_i]) {
569 .string_literal, .identifier => p.tok_i - 1,569 .string_literal, .identifier => p.nextToken(),
570 else => blk: {570 else => null,
571 p.tok_i -= 1;
572 break :blk null;
573 },
574 };571 };
575 const block_node = try p.parseBlock();572 const block_node = try p.parseBlock();
576 if (block_node == 0) return p.fail(.expected_block);573 if (block_node == 0) return p.fail(.expected_block);
...@@ -922,8 +919,8 @@ fn expectContainerField(p: *Parse) !Node.Index {...@@ -922,8 +919,8 @@ fn expectContainerField(p: *Parse) !Node.Index {
922 .data = .{919 .data = .{
923 .lhs = type_expr,920 .lhs = type_expr,
924 .rhs = try p.addExtra(Node.ContainerField{921 .rhs = try p.addExtra(Node.ContainerField{
925 .value_expr = value_expr,
926 .align_expr = align_expr,922 .align_expr = align_expr,
923 .value_expr = value_expr,
927 }),924 }),
928 },925 },
929 });926 });
...@@ -2051,9 +2048,9 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {...@@ -2051,9 +2048,9 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
2051 .main_token = lbracket,2048 .main_token = lbracket,
2052 .data = .{2049 .data = .{
2053 .lhs = len_expr,2050 .lhs = len_expr,
2054 .rhs = try p.addExtra(.{2051 .rhs = try p.addExtra(Node.ArrayTypeSentinel{
2055 .elem_type = elem_type,
2056 .sentinel = sentinel,2052 .sentinel = sentinel,
2053 .elem_type = elem_type,
2057 }),2054 }),
2058 },2055 },
2059 });2056 });
...@@ -2090,10 +2087,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2090,10 +2087,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2090 .keyword_asm => return p.expectAsmExpr(),2087 .keyword_asm => return p.expectAsmExpr(),
2091 .keyword_if => return p.parseIfExpr(),2088 .keyword_if => return p.parseIfExpr(),
2092 .keyword_break => {2089 .keyword_break => {
2093 p.tok_i += 1;
2094 return p.addNode(.{2090 return p.addNode(.{
2095 .tag = .@"break",2091 .tag = .@"break",
2096 .main_token = p.tok_i - 1,2092 .main_token = p.nextToken(),
2097 .data = .{2093 .data = .{
2098 .lhs = try p.parseBreakLabel(),2094 .lhs = try p.parseBreakLabel(),
2099 .rhs = try p.parseExpr(),2095 .rhs = try p.parseExpr(),
...@@ -2101,10 +2097,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2101,10 +2097,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2101 });2097 });
2102 },2098 },
2103 .keyword_continue => {2099 .keyword_continue => {
2104 p.tok_i += 1;
2105 return p.addNode(.{2100 return p.addNode(.{
2106 .tag = .@"continue",2101 .tag = .@"continue",
2107 .main_token = p.tok_i - 1,2102 .main_token = p.nextToken(),
2108 .data = .{2103 .data = .{
2109 .lhs = try p.parseBreakLabel(),2104 .lhs = try p.parseBreakLabel(),
2110 .rhs = undefined,2105 .rhs = undefined,
...@@ -2112,10 +2107,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2112,10 +2107,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2112 });2107 });
2113 },2108 },
2114 .keyword_comptime => {2109 .keyword_comptime => {
2115 p.tok_i += 1;
2116 return p.addNode(.{2110 return p.addNode(.{
2117 .tag = .@"comptime",2111 .tag = .@"comptime",
2118 .main_token = p.tok_i - 1,2112 .main_token = p.nextToken(),
2119 .data = .{2113 .data = .{
2120 .lhs = try p.expectExpr(),2114 .lhs = try p.expectExpr(),
2121 .rhs = undefined,2115 .rhs = undefined,
...@@ -2123,10 +2117,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2123,10 +2117,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2123 });2117 });
2124 },2118 },
2125 .keyword_nosuspend => {2119 .keyword_nosuspend => {
2126 p.tok_i += 1;
2127 return p.addNode(.{2120 return p.addNode(.{
2128 .tag = .@"nosuspend",2121 .tag = .@"nosuspend",
2129 .main_token = p.tok_i - 1,2122 .main_token = p.nextToken(),
2130 .data = .{2123 .data = .{
2131 .lhs = try p.expectExpr(),2124 .lhs = try p.expectExpr(),
2132 .rhs = undefined,2125 .rhs = undefined,
...@@ -2134,10 +2127,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2134,10 +2127,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2134 });2127 });
2135 },2128 },
2136 .keyword_resume => {2129 .keyword_resume => {
2137 p.tok_i += 1;
2138 return p.addNode(.{2130 return p.addNode(.{
2139 .tag = .@"resume",2131 .tag = .@"resume",
2140 .main_token = p.tok_i - 1,2132 .main_token = p.nextToken(),
2141 .data = .{2133 .data = .{
2142 .lhs = try p.expectExpr(),2134 .lhs = try p.expectExpr(),
2143 .rhs = undefined,2135 .rhs = undefined,
...@@ -2145,10 +2137,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2145,10 +2137,9 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2145 });2137 });
2146 },2138 },
2147 .keyword_return => {2139 .keyword_return => {
2148 p.tok_i += 1;
2149 return p.addNode(.{2140 return p.addNode(.{
2150 .tag = .@"return",2141 .tag = .@"return",
2151 .main_token = p.tok_i - 1,2142 .main_token = p.nextToken(),
2152 .data = .{2143 .data = .{
2153 .lhs = try p.parseExpr(),2144 .lhs = try p.parseExpr(),
2154 .rhs = undefined,2145 .rhs = undefined,
...@@ -2161,14 +2152,14 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2161,14 +2152,14 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2161 .keyword_inline => {2152 .keyword_inline => {
2162 p.tok_i += 3;2153 p.tok_i += 3;
2163 switch (p.token_tags[p.tok_i]) {2154 switch (p.token_tags[p.tok_i]) {
2164 .keyword_for => return p.parseForExpr(),2155 .keyword_for => return p.parseFor(expectExpr),
2165 .keyword_while => return p.parseWhileExpr(),2156 .keyword_while => return p.parseWhileExpr(),
2166 else => return p.fail(.expected_inlinable),2157 else => return p.fail(.expected_inlinable),
2167 }2158 }
2168 },2159 },
2169 .keyword_for => {2160 .keyword_for => {
2170 p.tok_i += 2;2161 p.tok_i += 2;
2171 return p.parseForExpr();2162 return p.parseFor(expectExpr);
2172 },2163 },
2173 .keyword_while => {2164 .keyword_while => {
2174 p.tok_i += 2;2165 p.tok_i += 2;
...@@ -2187,12 +2178,12 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {...@@ -2187,12 +2178,12 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index {
2187 .keyword_inline => {2178 .keyword_inline => {
2188 p.tok_i += 1;2179 p.tok_i += 1;
2189 switch (p.token_tags[p.tok_i]) {2180 switch (p.token_tags[p.tok_i]) {
2190 .keyword_for => return p.parseForExpr(),2181 .keyword_for => return p.parseFor(expectExpr),
2191 .keyword_while => return p.parseWhileExpr(),2182 .keyword_while => return p.parseWhileExpr(),
2192 else => return p.fail(.expected_inlinable),2183 else => return p.fail(.expected_inlinable),
2193 }2184 }
2194 },2185 },
2195 .keyword_for => return p.parseForExpr(),2186 .keyword_for => return p.parseFor(expectExpr),
2196 .keyword_while => return p.parseWhileExpr(),2187 .keyword_while => return p.parseWhileExpr(),
2197 .l_brace => return p.parseBlock(),2188 .l_brace => return p.parseBlock(),
2198 else => return p.parseCurlySuffixExpr(),2189 else => return p.parseCurlySuffixExpr(),
...@@ -2257,46 +2248,6 @@ fn parseBlock(p: *Parse) !Node.Index {...@@ -2257,46 +2248,6 @@ fn parseBlock(p: *Parse) !Node.Index {
2257 }2248 }
2258}2249}
22592250
2260/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
2261fn parseForExpr(p: *Parse) !Node.Index {
2262 const for_token = p.eatToken(.keyword_for) orelse return null_node;
2263
2264 const scratch_top = p.scratch.items.len;
2265 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2266 const inputs = try p.forPrefix();
2267
2268 const then_expr = try p.expectExpr();
2269 var has_else = false;
2270 if (p.eatToken(.keyword_else)) |_| {
2271 try p.scratch.append(p.gpa, then_expr);
2272 const else_expr = try p.expectExpr();
2273 try p.scratch.append(p.gpa, else_expr);
2274 has_else = true;
2275 } else if (inputs == 1) {
2276 return p.addNode(.{
2277 .tag = .for_simple,
2278 .main_token = for_token,
2279 .data = .{
2280 .lhs = p.scratch.items[scratch_top],
2281 .rhs = then_expr,
2282 },
2283 });
2284 } else {
2285 try p.scratch.append(p.gpa, then_expr);
2286 }
2287 return p.addNode(.{
2288 .tag = .@"for",
2289 .main_token = for_token,
2290 .data = .{
2291 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,
2292 .rhs = @as(u32, @bitCast(Node.For{
2293 .inputs = @as(u31, @intCast(inputs)),
2294 .has_else = has_else,
2295 })),
2296 },
2297 });
2298}
2299
2300/// ForPrefix <- KEYWORD_for LPAREN ForInput (COMMA ForInput)* COMMA? RPAREN ForPayload2251/// ForPrefix <- KEYWORD_for LPAREN ForInput (COMMA ForInput)* COMMA? RPAREN ForPayload
2301///2252///
2302/// ForInput <- Expr (DOT2 Expr?)?2253/// ForInput <- Expr (DOT2 Expr?)?
...@@ -2793,14 +2744,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2793,14 +2744,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2793 .keyword_inline => {2744 .keyword_inline => {
2794 p.tok_i += 3;2745 p.tok_i += 3;
2795 switch (p.token_tags[p.tok_i]) {2746 switch (p.token_tags[p.tok_i]) {
2796 .keyword_for => return p.parseForTypeExpr(),2747 .keyword_for => return p.parseFor(expectTypeExpr),
2797 .keyword_while => return p.parseWhileTypeExpr(),2748 .keyword_while => return p.parseWhileTypeExpr(),
2798 else => return p.fail(.expected_inlinable),2749 else => return p.fail(.expected_inlinable),
2799 }2750 }
2800 },2751 },
2801 .keyword_for => {2752 .keyword_for => {
2802 p.tok_i += 2;2753 p.tok_i += 2;
2803 return p.parseForTypeExpr();2754 return p.parseFor(expectTypeExpr);
2804 },2755 },
2805 .keyword_while => {2756 .keyword_while => {
2806 p.tok_i += 2;2757 p.tok_i += 2;
...@@ -2831,12 +2782,12 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2831,12 +2782,12 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2831 .keyword_inline => {2782 .keyword_inline => {
2832 p.tok_i += 1;2783 p.tok_i += 1;
2833 switch (p.token_tags[p.tok_i]) {2784 switch (p.token_tags[p.tok_i]) {
2834 .keyword_for => return p.parseForTypeExpr(),2785 .keyword_for => return p.parseFor(expectTypeExpr),
2835 .keyword_while => return p.parseWhileTypeExpr(),2786 .keyword_while => return p.parseWhileTypeExpr(),
2836 else => return p.fail(.expected_inlinable),2787 else => return p.fail(.expected_inlinable),
2837 }2788 }
2838 },2789 },
2839 .keyword_for => return p.parseForTypeExpr(),2790 .keyword_for => return p.parseFor(expectTypeExpr),
2840 .keyword_while => return p.parseWhileTypeExpr(),2791 .keyword_while => return p.parseWhileTypeExpr(),
2841 .period => switch (p.token_tags[p.tok_i + 1]) {2792 .period => switch (p.token_tags[p.tok_i + 1]) {
2842 .identifier => return p.addNode(.{2793 .identifier => return p.addNode(.{
...@@ -3029,46 +2980,6 @@ fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -3029,46 +2980,6 @@ fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {
3029 return node;2980 return node;
3030}2981}
30312982
3032/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3033fn parseForTypeExpr(p: *Parse) !Node.Index {
3034 const for_token = p.eatToken(.keyword_for) orelse return null_node;
3035
3036 const scratch_top = p.scratch.items.len;
3037 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3038 const inputs = try p.forPrefix();
3039
3040 const then_expr = try p.expectTypeExpr();
3041 var has_else = false;
3042 if (p.eatToken(.keyword_else)) |_| {
3043 try p.scratch.append(p.gpa, then_expr);
3044 const else_expr = try p.expectTypeExpr();
3045 try p.scratch.append(p.gpa, else_expr);
3046 has_else = true;
3047 } else if (inputs == 1) {
3048 return p.addNode(.{
3049 .tag = .for_simple,
3050 .main_token = for_token,
3051 .data = .{
3052 .lhs = p.scratch.items[scratch_top],
3053 .rhs = then_expr,
3054 },
3055 });
3056 } else {
3057 try p.scratch.append(p.gpa, then_expr);
3058 }
3059 return p.addNode(.{
3060 .tag = .@"for",
3061 .main_token = for_token,
3062 .data = .{
3063 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3064 .rhs = @as(u32, @bitCast(Node.For{
3065 .inputs = @as(u31, @intCast(inputs)),
3066 .has_else = has_else,
3067 })),
3068 },
3069 });
3070}
3071
3072/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?2983/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
3073///2984///
3074/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?2985/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
...@@ -3279,7 +3190,7 @@ fn parseAsmInputItem(p: *Parse) !Node.Index {...@@ -3279,7 +3190,7 @@ fn parseAsmInputItem(p: *Parse) !Node.Index {
32793190
3280/// BreakLabel <- COLON IDENTIFIER3191/// BreakLabel <- COLON IDENTIFIER
3281fn parseBreakLabel(p: *Parse) !TokenIndex {3192fn parseBreakLabel(p: *Parse) !TokenIndex {
3282 _ = p.eatToken(.colon) orelse return @as(TokenIndex, 0);3193 _ = p.eatToken(.colon) orelse return null_node;
3283 return p.expectToken(.identifier);3194 return p.expectToken(.identifier);
3284}3195}
32853196
...@@ -3397,7 +3308,7 @@ fn expectParamDecl(p: *Parse) !Node.Index {...@@ -3397,7 +3308,7 @@ fn expectParamDecl(p: *Parse) !Node.Index {
33973308
3398/// Payload <- PIPE IDENTIFIER PIPE3309/// Payload <- PIPE IDENTIFIER PIPE
3399fn parsePayload(p: *Parse) !TokenIndex {3310fn parsePayload(p: *Parse) !TokenIndex {
3400 _ = p.eatToken(.pipe) orelse return @as(TokenIndex, 0);3311 _ = p.eatToken(.pipe) orelse return null_node;
3401 const identifier = try p.expectToken(.identifier);3312 const identifier = try p.expectToken(.identifier);
3402 _ = try p.expectToken(.pipe);3313 _ = try p.expectToken(.pipe);
3403 return identifier;3314 return identifier;
...@@ -3405,7 +3316,7 @@ fn parsePayload(p: *Parse) !TokenIndex {...@@ -3405,7 +3316,7 @@ fn parsePayload(p: *Parse) !TokenIndex {
34053316
3406/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE3317/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
3407fn parsePtrPayload(p: *Parse) !TokenIndex {3318fn parsePtrPayload(p: *Parse) !TokenIndex {
3408 _ = p.eatToken(.pipe) orelse return @as(TokenIndex, 0);3319 _ = p.eatToken(.pipe) orelse return null_node;
3409 _ = p.eatToken(.asterisk);3320 _ = p.eatToken(.asterisk);
3410 const identifier = try p.expectToken(.identifier);3321 const identifier = try p.expectToken(.identifier);
3411 _ = try p.expectToken(.pipe);3322 _ = try p.expectToken(.pipe);
...@@ -3416,7 +3327,7 @@ fn parsePtrPayload(p: *Parse) !TokenIndex {...@@ -3416,7 +3327,7 @@ fn parsePtrPayload(p: *Parse) !TokenIndex {
3416///3327///
3417/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE3328/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
3418fn parsePtrIndexPayload(p: *Parse) !TokenIndex {3329fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
3419 _ = p.eatToken(.pipe) orelse return @as(TokenIndex, 0);3330 _ = p.eatToken(.pipe) orelse return null_node;
3420 _ = p.eatToken(.asterisk);3331 _ = p.eatToken(.asterisk);
3421 const identifier = try p.expectToken(.identifier);3332 const identifier = try p.expectToken(.identifier);
3422 if (p.eatToken(.comma) != null) {3333 if (p.eatToken(.comma) != null) {
...@@ -3925,8 +3836,7 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {...@@ -3925,8 +3836,7 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
3925/// ExprList <- (Expr COMMA)* Expr?3836/// ExprList <- (Expr COMMA)* Expr?
3926fn parseBuiltinCall(p: *Parse) !Node.Index {3837fn parseBuiltinCall(p: *Parse) !Node.Index {
3927 const builtin_token = p.assertToken(.builtin);3838 const builtin_token = p.assertToken(.builtin);
3928 if (p.token_tags[p.nextToken()] != .l_paren) {3839 _ = p.eatToken(.l_paren) orelse {
3929 p.tok_i -= 1;
3930 try p.warn(.expected_param_list);3840 try p.warn(.expected_param_list);
3931 // Pretend this was an identifier so we can continue parsing.3841 // Pretend this was an identifier so we can continue parsing.
3932 return p.addNode(.{3842 return p.addNode(.{
...@@ -3937,7 +3847,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3937,7 +3847,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3937 .rhs = undefined,3847 .rhs = undefined,
3938 },3848 },
3939 });3849 });
3940 }3850 };
3941 const scratch_top = p.scratch.items.len;3851 const scratch_top = p.scratch.items.len;
3942 defer p.scratch.shrinkRetainingCapacity(scratch_top);3852 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3943 while (true) {3853 while (true) {
...@@ -4031,8 +3941,50 @@ fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !No...@@ -4031,8 +3941,50 @@ fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !No
4031 });3941 });
4032}3942}
40333943
3944/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
3945///
3946/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3947fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {
3948 const for_token = p.eatToken(.keyword_for) orelse return null_node;
3949
3950 const scratch_top = p.scratch.items.len;
3951 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3952 const inputs = try p.forPrefix();
3953
3954 const then_expr = try bodyParseFn(p);
3955 var has_else = false;
3956 if (p.eatToken(.keyword_else)) |_| {
3957 try p.scratch.append(p.gpa, then_expr);
3958 const else_expr = try bodyParseFn(p);
3959 try p.scratch.append(p.gpa, else_expr);
3960 has_else = true;
3961 } else if (inputs == 1) {
3962 return p.addNode(.{
3963 .tag = .for_simple,
3964 .main_token = for_token,
3965 .data = .{
3966 .lhs = p.scratch.items[scratch_top],
3967 .rhs = then_expr,
3968 },
3969 });
3970 } else {
3971 try p.scratch.append(p.gpa, then_expr);
3972 }
3973 return p.addNode(.{
3974 .tag = .@"for",
3975 .main_token = for_token,
3976 .data = .{
3977 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3978 .rhs = @as(u32, @bitCast(Node.For{
3979 .inputs = @as(u31, @intCast(inputs)),
3980 .has_else = has_else,
3981 })),
3982 },
3983 });
3984}
3985
4034/// Skips over doc comment tokens. Returns the first one, if any.3986/// Skips over doc comment tokens. Returns the first one, if any.
4035fn eatDocComments(p: *Parse) !?TokenIndex {3987fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
4036 if (p.eatToken(.doc_comment)) |tok| {3988 if (p.eatToken(.doc_comment)) |tok| {
4037 var first_line = tok;3989 var first_line = tok;
4038 if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) {3990 if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) {