| ... | @@ -2152,14 +2152,14 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { | ... | @@ -2152,14 +2152,14 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { |
| 2152 | .keyword_inline => { | 2152 | .keyword_inline => { |
| 2153 | p.tok_i += 3; | 2153 | p.tok_i += 3; |
| 2154 | switch (p.token_tags[p.tok_i]) { | 2154 | switch (p.token_tags[p.tok_i]) { |
| 2155 | .keyword_for => return p.parseForExpr(), | 2155 | .keyword_for => return p.parseFor(expectExpr), |
| 2156 | .keyword_while => return p.parseWhileExpr(), | 2156 | .keyword_while => return p.parseWhileExpr(), |
| 2157 | else => return p.fail(.expected_inlinable), | 2157 | else => return p.fail(.expected_inlinable), |
| 2158 | } | 2158 | } |
| 2159 | }, | 2159 | }, |
| 2160 | .keyword_for => { | 2160 | .keyword_for => { |
| 2161 | p.tok_i += 2; | 2161 | p.tok_i += 2; |
| 2162 | return p.parseForExpr(); | 2162 | return p.parseFor(expectExpr); |
| 2163 | }, | 2163 | }, |
| 2164 | .keyword_while => { | 2164 | .keyword_while => { |
| 2165 | p.tok_i += 2; | 2165 | p.tok_i += 2; |
| ... | @@ -2178,12 +2178,12 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { | ... | @@ -2178,12 +2178,12 @@ fn parsePrimaryExpr(p: *Parse) !Node.Index { |
| 2178 | .keyword_inline => { | 2178 | .keyword_inline => { |
| 2179 | p.tok_i += 1; | 2179 | p.tok_i += 1; |
| 2180 | switch (p.token_tags[p.tok_i]) { | 2180 | switch (p.token_tags[p.tok_i]) { |
| 2181 | .keyword_for => return p.parseForExpr(), | 2181 | .keyword_for => return p.parseFor(expectExpr), |
| 2182 | .keyword_while => return p.parseWhileExpr(), | 2182 | .keyword_while => return p.parseWhileExpr(), |
| 2183 | else => return p.fail(.expected_inlinable), | 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 | .keyword_while => return p.parseWhileExpr(), | 2187 | .keyword_while => return p.parseWhileExpr(), |
| 2188 | .l_brace => return p.parseBlock(), | 2188 | .l_brace => return p.parseBlock(), |
| 2189 | else => return p.parseCurlySuffixExpr(), | 2189 | else => return p.parseCurlySuffixExpr(), |
| ... | @@ -2248,46 +2248,6 @@ fn parseBlock(p: *Parse) !Node.Index { | ... | @@ -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 | /// ForPrefix <- KEYWORD_for LPAREN ForInput (COMMA ForInput)* COMMA? RPAREN ForPayload | 2251 | /// ForPrefix <- KEYWORD_for LPAREN ForInput (COMMA ForInput)* COMMA? RPAREN ForPayload |
| 2292 | /// | 2252 | /// |
| 2293 | /// ForInput <- Expr (DOT2 Expr?)? | 2253 | /// ForInput <- Expr (DOT2 Expr?)? |
| ... | @@ -2784,14 +2744,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { | ... | @@ -2784,14 +2744,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2784 | .keyword_inline => { | 2744 | .keyword_inline => { |
| 2785 | p.tok_i += 3; | 2745 | p.tok_i += 3; |
| 2786 | switch (p.token_tags[p.tok_i]) { | 2746 | switch (p.token_tags[p.tok_i]) { |
| 2787 | .keyword_for => return p.parseForTypeExpr(), | 2747 | .keyword_for => return p.parseFor(expectTypeExpr), |
| 2788 | .keyword_while => return p.parseWhileTypeExpr(), | 2748 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2789 | else => return p.fail(.expected_inlinable), | 2749 | else => return p.fail(.expected_inlinable), |
| 2790 | } | 2750 | } |
| 2791 | }, | 2751 | }, |
| 2792 | .keyword_for => { | 2752 | .keyword_for => { |
| 2793 | p.tok_i += 2; | 2753 | p.tok_i += 2; |
| 2794 | return p.parseForTypeExpr(); | 2754 | return p.parseFor(expectTypeExpr); |
| 2795 | }, | 2755 | }, |
| 2796 | .keyword_while => { | 2756 | .keyword_while => { |
| 2797 | p.tok_i += 2; | 2757 | p.tok_i += 2; |
| ... | @@ -2822,12 +2782,12 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { | ... | @@ -2822,12 +2782,12 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2822 | .keyword_inline => { | 2782 | .keyword_inline => { |
| 2823 | p.tok_i += 1; | 2783 | p.tok_i += 1; |
| 2824 | switch (p.token_tags[p.tok_i]) { | 2784 | switch (p.token_tags[p.tok_i]) { |
| 2825 | .keyword_for => return p.parseForTypeExpr(), | 2785 | .keyword_for => return p.parseFor(expectTypeExpr), |
| 2826 | .keyword_while => return p.parseWhileTypeExpr(), | 2786 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2827 | else => return p.fail(.expected_inlinable), | 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 | .keyword_while => return p.parseWhileTypeExpr(), | 2791 | .keyword_while => return p.parseWhileTypeExpr(), |
| 2832 | .period => switch (p.token_tags[p.tok_i + 1]) { | 2792 | .period => switch (p.token_tags[p.tok_i + 1]) { |
| 2833 | .identifier => return p.addNode(.{ | 2793 | .identifier => return p.addNode(.{ |
| ... | @@ -3020,46 +2980,6 @@ fn expectPrimaryTypeExpr(p: *Parse) !Node.Index { | ... | @@ -3020,46 +2980,6 @@ fn expectPrimaryTypeExpr(p: *Parse) !Node.Index { |
| 3020 | return node; | 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 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? | 2983 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 3064 | /// | 2984 | /// |
| 3065 | /// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? | 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,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 | /// Skips over doc comment tokens. Returns the first one, if any. | 3986 | /// Skips over doc comment tokens. Returns the first one, if any. |
| 4025 | fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { | 3987 | fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { |
| 4026 | if (p.eatToken(.doc_comment)) |tok| { | 3988 | if (p.eatToken(.doc_comment)) |tok| { |