| ... | ... | @@ -2152,14 +2152,14 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { |
| 2152 | 2152 | .keyword_inline => { |
| 2153 | 2153 | p.tok_i += 3; |
| 2154 | 2154 | switch (p.token_tags[p.tok_i]) { |
| 2155 | | .keyword_for => return p.parseForExpr(), |
| 2155 | .keyword_for => return p.parseFor(expectExpr), |
| 2156 | 2156 | .keyword_while => return p.parseWhileExpr(), |
| 2157 | 2157 | else => return p.fail(.expected_inlinable), |
| 2158 | 2158 | } |
| 2159 | 2159 | }, |
| 2160 | 2160 | .keyword_for => { |
| 2161 | 2161 | p.tok_i += 2; |
| 2162 | | return p.parseForExpr(); |
| 2162 | return p.parseFor(expectExpr); |
| 2163 | 2163 | }, |
| 2164 | 2164 | .keyword_while => { |
| 2165 | 2165 | p.tok_i += 2; |
| ... | ... | @@ -2178,12 +2178,12 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { |
| 2178 | 2178 | .keyword_inline => { |
| 2179 | 2179 | p.tok_i += 1; |
| 2180 | 2180 | switch (p.token_tags[p.tok_i]) { |
| 2181 | | .keyword_for => return p.parseForExpr(), |
| 2181 | .keyword_for => return p.parseFor(expectExpr), |
| 2182 | 2182 | .keyword_while => return p.parseWhileExpr(), |
| 2183 | 2183 | else => return p.fail(.expected_inlinable), |
| 2184 | 2184 | } |
| 2185 | 2185 | }, |
| 2186 | | .keyword_for => return p.parseForExpr(), |
| 2186 | .keyword_for => return p.parseFor(expectExpr), |
| 2187 | 2187 | .keyword_while => return p.parseWhileExpr(), |
| 2188 | 2188 | .l_brace => return p.parseBlock(), |
| 2189 | 2189 | else => return p.parseCurlySuffixExpr(), |
| ... | ... | @@ -2248,46 +2248,6 @@ fn parseBlock(p: *Parse) !Node.Index { |
| 2248 | 2248 | } |
| 2249 | 2249 | } |
| 2250 | 2250 | |
| 2251 | | /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? |
| 2252 | | fn parseForExpr(p: *Parse) !Node.Index { |
| 2253 | | const for_token = p.eatToken(.keyword_for) orelse return null_node; |
| 2254 | | |
| 2255 | | const scratch_top = p.scratch.items.len; |
| 2256 | | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2257 | | const inputs = try p.forPrefix(); |
| 2258 | | |
| 2259 | | const then_expr = try p.expectExpr(); |
| 2260 | | var has_else = false; |
| 2261 | | if (p.eatToken(.keyword_else)) |_| { |
| 2262 | | try p.scratch.append(p.gpa, then_expr); |
| 2263 | | const else_expr = try p.expectExpr(); |
| 2264 | | try p.scratch.append(p.gpa, else_expr); |
| 2265 | | has_else = true; |
| 2266 | | } else if (inputs == 1) { |
| 2267 | | return p.addNode(.{ |
| 2268 | | .tag = .for_simple, |
| 2269 | | .main_token = for_token, |
| 2270 | | .data = .{ |
| 2271 | | .lhs = p.scratch.items[scratch_top], |
| 2272 | | .rhs = then_expr, |
| 2273 | | }, |
| 2274 | | }); |
| 2275 | | } else { |
| 2276 | | try p.scratch.append(p.gpa, then_expr); |
| 2277 | | } |
| 2278 | | return p.addNode(.{ |
| 2279 | | .tag = .@"for", |
| 2280 | | .main_token = for_token, |
| 2281 | | .data = .{ |
| 2282 | | .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start, |
| 2283 | | .rhs = @as(u32, @bitCast(Node.For{ |
| 2284 | | .inputs = @as(u31, @intCast(inputs)), |
| 2285 | | .has_else = has_else, |
| 2286 | | })), |
| 2287 | | }, |
| 2288 | | }); |
| 2289 | | } |
| 2290 | | |
| 2291 | 2251 | /// ForPrefix <- KEYWORD_for LPAREN ForInput (COMMA ForInput)* COMMA? RPAREN ForPayload |
| 2292 | 2252 | /// |
| 2293 | 2253 | /// ForInput <- Expr (DOT2 Expr?)? |
| ... | ... | @@ -2784,14 +2744,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2784 | 2744 | .keyword_inline => { |
| 2785 | 2745 | p.tok_i += 3; |
| 2786 | 2746 | switch (p.token_tags[p.tok_i]) { |
| 2787 | | .keyword_for => return p.parseForTypeExpr(), |
| 2747 | .keyword_for => return p.parseFor(expectTypeExpr), |
| 2788 | 2748 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2789 | 2749 | else => return p.fail(.expected_inlinable), |
| 2790 | 2750 | } |
| 2791 | 2751 | }, |
| 2792 | 2752 | .keyword_for => { |
| 2793 | 2753 | p.tok_i += 2; |
| 2794 | | return p.parseForTypeExpr(); |
| 2754 | return p.parseFor(expectTypeExpr); |
| 2795 | 2755 | }, |
| 2796 | 2756 | .keyword_while => { |
| 2797 | 2757 | p.tok_i += 2; |
| ... | ... | @@ -2822,12 +2782,12 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2822 | 2782 | .keyword_inline => { |
| 2823 | 2783 | p.tok_i += 1; |
| 2824 | 2784 | switch (p.token_tags[p.tok_i]) { |
| 2825 | | .keyword_for => return p.parseForTypeExpr(), |
| 2785 | .keyword_for => return p.parseFor(expectTypeExpr), |
| 2826 | 2786 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2827 | 2787 | else => return p.fail(.expected_inlinable), |
| 2828 | 2788 | } |
| 2829 | 2789 | }, |
| 2830 | | .keyword_for => return p.parseForTypeExpr(), |
| 2790 | .keyword_for => return p.parseFor(expectTypeExpr), |
| 2831 | 2791 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2832 | 2792 | .period => switch (p.token_tags[p.tok_i + 1]) { |
| 2833 | 2793 | .identifier => return p.addNode(.{ |
| ... | ... | @@ -3020,46 +2980,6 @@ fn expectPrimaryTypeExpr(p: *Parse) !Node.Index { |
| 3020 | 2980 | return node; |
| 3021 | 2981 | } |
| 3022 | 2982 | |
| 3023 | | /// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? |
| 3024 | | fn parseForTypeExpr(p: *Parse) !Node.Index { |
| 3025 | | const for_token = p.eatToken(.keyword_for) orelse return null_node; |
| 3026 | | |
| 3027 | | const scratch_top = p.scratch.items.len; |
| 3028 | | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3029 | | const inputs = try p.forPrefix(); |
| 3030 | | |
| 3031 | | const then_expr = try p.expectTypeExpr(); |
| 3032 | | var has_else = false; |
| 3033 | | if (p.eatToken(.keyword_else)) |_| { |
| 3034 | | try p.scratch.append(p.gpa, then_expr); |
| 3035 | | const else_expr = try p.expectTypeExpr(); |
| 3036 | | try p.scratch.append(p.gpa, else_expr); |
| 3037 | | has_else = true; |
| 3038 | | } else if (inputs == 1) { |
| 3039 | | return p.addNode(.{ |
| 3040 | | .tag = .for_simple, |
| 3041 | | .main_token = for_token, |
| 3042 | | .data = .{ |
| 3043 | | .lhs = p.scratch.items[scratch_top], |
| 3044 | | .rhs = then_expr, |
| 3045 | | }, |
| 3046 | | }); |
| 3047 | | } else { |
| 3048 | | try p.scratch.append(p.gpa, then_expr); |
| 3049 | | } |
| 3050 | | return p.addNode(.{ |
| 3051 | | .tag = .@"for", |
| 3052 | | .main_token = for_token, |
| 3053 | | .data = .{ |
| 3054 | | .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start, |
| 3055 | | .rhs = @as(u32, @bitCast(Node.For{ |
| 3056 | | .inputs = @as(u31, @intCast(inputs)), |
| 3057 | | .has_else = has_else, |
| 3058 | | })), |
| 3059 | | }, |
| 3060 | | }); |
| 3061 | | } |
| 3062 | | |
| 3063 | 2983 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 3064 | 2984 | /// |
| 3065 | 2985 | /// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? |
| ... | ... | @@ -4021,6 +3941,48 @@ fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !No |
| 4021 | 3941 | }); |
| 4022 | 3942 | } |
| 4023 | 3943 | |
| 3944 | /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? |
| 3945 | /// |
| 3946 | /// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? |
| 3947 | fn 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 | |
| 4024 | 3986 | /// Skips over doc comment tokens. Returns the first one, if any. |
| 4025 | 3987 | fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { |
| 4026 | 3988 | if (p.eatToken(.doc_comment)) |tok| { |