authorgravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2023-12-29 07:59:55-08:00
committergravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2023-12-29 07:59:55-08:00
log20cde3f480462a3b609131dd118623978c26bace
treeaaa7ca6de7a8787ddde2bba4bd31d63aacf3e46c
parent2091ee2e61676b87c5735ecd503af93f3b8a108d

std.zig.Parse: Add parseFor helper method


1 files changed, 50 insertions(+), 88 deletions(-)

lib/std/zig/Parse.zig+50-88
...@@ -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}
22502250
2251/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
2252fn 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 ForPayload2251/// 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}
30222982
3023/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3024fn 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}
40233943
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
4024/// Skips over doc comment tokens. Returns the first one, if any.3986/// Skips over doc comment tokens. Returns the first one, if any.
4025fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {3987fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
4026 if (p.eatToken(.doc_comment)) |tok| {3988 if (p.eatToken(.doc_comment)) |tok| {