authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-13 19:49:41+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-06-13 19:49:41+03:00
logf58fbb1004e26982ad83c61b3fecf5e575fb9210
tree328036fa9c7eb125307437e0fdf0244d782c9736
parent46b9e061e07700ad1372ed2e9d2af9a29f24d76c
parent483933d88d4fbf00467a48df100075a40344766b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9074 from mattbork/parse-always-scratch

parse.zig: simplify parsing functions that build lists by always using scratch buffer

2 files changed, 342 insertions(+), 601 deletions(-)

lib/std/zig/parse.zig+341-600
......@@ -1850,65 +1850,54 @@ const Parser = struct {
18501850 /// Block <- LBRACE Statement* RBRACE
18511851 fn parseBlock(p: *Parser) !Node.Index {
18521852 const lbrace = p.eatToken(.l_brace) orelse return null_node;
1853
1854 if (p.eatToken(.r_brace)) |_| {
1855 return p.addNode(.{
1853 const scratch_top = p.scratch.items.len;
1854 defer p.scratch.shrinkRetainingCapacity(scratch_top);
1855 while (true) {
1856 if (p.token_tags[p.tok_i] == .r_brace) break;
1857 const statement = try p.expectStatementRecoverable();
1858 if (statement == 0) break;
1859 try p.scratch.append(p.gpa, statement);
1860 }
1861 _ = try p.expectToken(.r_brace);
1862 const semicolon = (p.token_tags[p.tok_i - 2] == .semicolon);
1863 const statements = p.scratch.items[scratch_top..];
1864 switch (statements.len) {
1865 0 => return p.addNode(.{
18561866 .tag = .block_two,
18571867 .main_token = lbrace,
18581868 .data = .{
18591869 .lhs = 0,
18601870 .rhs = 0,
18611871 },
1862 });
1863 }
1864
1865 const stmt_one = try p.expectStatementRecoverable();
1866 if (p.eatToken(.r_brace)) |_| {
1867 const semicolon = p.token_tags[p.tok_i - 2] == .semicolon;
1868 return p.addNode(.{
1872 }),
1873 1 => return p.addNode(.{
18691874 .tag = if (semicolon) .block_two_semicolon else .block_two,
18701875 .main_token = lbrace,
18711876 .data = .{
1872 .lhs = stmt_one,
1877 .lhs = statements[0],
18731878 .rhs = 0,
18741879 },
1875 });
1876 }
1877 const stmt_two = try p.expectStatementRecoverable();
1878 if (p.eatToken(.r_brace)) |_| {
1879 const semicolon = p.token_tags[p.tok_i - 2] == .semicolon;
1880 return p.addNode(.{
1880 }),
1881 2 => return p.addNode(.{
18811882 .tag = if (semicolon) .block_two_semicolon else .block_two,
18821883 .main_token = lbrace,
18831884 .data = .{
1884 .lhs = stmt_one,
1885 .rhs = stmt_two,
1885 .lhs = statements[0],
1886 .rhs = statements[1],
18861887 },
1887 });
1888 }
1889
1890 const scratch_top = p.scratch.items.len;
1891 defer p.scratch.shrinkRetainingCapacity(scratch_top);
1892
1893 try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two });
1894
1895 while (true) {
1896 const statement = try p.expectStatementRecoverable();
1897 if (statement == 0) break;
1898 try p.scratch.append(p.gpa, statement);
1899 if (p.token_tags[p.tok_i] == .r_brace) break;
1900 }
1901 _ = try p.expectToken(.r_brace);
1902 const semicolon = p.token_tags[p.tok_i - 2] == .semicolon;
1903 const statements_span = try p.listToSpan(p.scratch.items[scratch_top..]);
1904 return p.addNode(.{
1905 .tag = if (semicolon) .block_semicolon else .block,
1906 .main_token = lbrace,
1907 .data = .{
1908 .lhs = statements_span.start,
1909 .rhs = statements_span.end,
1888 }),
1889 else => {
1890 const span = try p.listToSpan(statements);
1891 return p.addNode(.{
1892 .tag = if (semicolon) .block_semicolon else .block,
1893 .main_token = lbrace,
1894 .data = .{
1895 .lhs = span.start,
1896 .rhs = span.end,
1897 },
1898 });
19101899 },
1911 });
1900 }
19121901 }
19131902
19141903 /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
......@@ -2010,114 +1999,86 @@ const Parser = struct {
20101999 // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne;
20112000 // otherwise we use the full ArrayInit/StructInit.
20122001
2013 if (p.eatToken(.r_brace)) |_| {
2014 return p.addNode(.{
2015 .tag = .struct_init_one,
2016 .main_token = lbrace,
2017 .data = .{
2018 .lhs = lhs,
2019 .rhs = 0,
2020 },
2021 });
2022 }
2002 const scratch_top = p.scratch.items.len;
2003 defer p.scratch.shrinkRetainingCapacity(scratch_top);
20232004 const field_init = try p.parseFieldInit();
20242005 if (field_init != 0) {
2025 const comma_one = p.eatToken(.comma);
2026 if (p.eatToken(.r_brace)) |_| {
2027 return p.addNode(.{
2028 .tag = if (comma_one != null) .struct_init_one_comma else .struct_init_one,
2029 .main_token = lbrace,
2030 .data = .{
2031 .lhs = lhs,
2032 .rhs = field_init,
2033 },
2034 });
2035 }
2036
2037 const scratch_top = p.scratch.items.len;
2038 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2039
20402006 try p.scratch.append(p.gpa, field_init);
2041
20422007 while (true) {
2008 switch (p.token_tags[p.tok_i]) {
2009 .comma => p.tok_i += 1,
2010 .r_brace => { p.tok_i += 1; break; },
2011 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
2012 // Likely just a missing comma; give error but continue parsing.
2013 else => try p.warnExpected(.comma),
2014 }
2015 if (p.eatToken(.r_brace)) |_| break;
20432016 const next = try p.expectFieldInit();
20442017 try p.scratch.append(p.gpa, next);
2045
2046 switch (p.token_tags[p.nextToken()]) {
2047 .comma => {
2048 if (p.eatToken(.r_brace)) |_| break;
2049 continue;
2050 },
2051 .r_brace => break,
2052 .colon, .r_paren, .r_bracket => {
2053 p.tok_i -= 1;
2054 return p.failExpected(.r_brace);
2018 }
2019 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2020 const inits = p.scratch.items[scratch_top..];
2021 switch (inits.len) {
2022 0 => unreachable,
2023 1 => return p.addNode(.{
2024 .tag = if (comma) .struct_init_one_comma else .struct_init_one,
2025 .main_token = lbrace,
2026 .data = .{
2027 .lhs = lhs,
2028 .rhs = inits[0],
20552029 },
2056 else => {
2057 // This is likely just a missing comma;
2058 // give an error but continue parsing this list.
2059 p.tok_i -= 1;
2060 try p.warnExpected(.comma);
2030 }),
2031 else => return p.addNode(.{
2032 .tag = if (comma) .struct_init_comma else .struct_init,
2033 .main_token = lbrace,
2034 .data = .{
2035 .lhs = lhs,
2036 .rhs = try p.addExtra(try p.listToSpan(inits)),
20612037 },
2062 }
2038 }),
20632039 }
2064 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2065 return p.addNode(.{
2066 .tag = if (p.token_tags[p.tok_i - 2] == .comma) .struct_init_comma else .struct_init,
2040 }
2041
2042 while (true) {
2043 if (p.eatToken(.r_brace)) |_| break;
2044 const elem_init = try p.expectExpr();
2045 try p.scratch.append(p.gpa, elem_init);
2046 switch (p.token_tags[p.tok_i]) {
2047 .comma => p.tok_i += 1,
2048 .r_brace => { p.tok_i += 1; break; },
2049 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
2050 // Likely just a missing comma; give error but continue parsing.
2051 else => try p.warnExpected(.comma),
2052 }
2053 }
2054 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2055 const inits = p.scratch.items[scratch_top..];
2056 switch (inits.len) {
2057 0 => return p.addNode(.{
2058 .tag = .struct_init_one,
20672059 .main_token = lbrace,
20682060 .data = .{
20692061 .lhs = lhs,
2070 .rhs = try p.addExtra(Node.SubRange{
2071 .start = span.start,
2072 .end = span.end,
2073 }),
2062 .rhs = 0,
20742063 },
2075 });
2076 }
2077
2078 const elem_init = try p.expectExpr();
2079 const comma_one = p.eatToken(.comma);
2080 if (p.eatToken(.r_brace)) |_| {
2081 return p.addNode(.{
2082 .tag = if (comma_one != null) .array_init_one_comma else .array_init_one,
2064 }),
2065 1 => return p.addNode(.{
2066 .tag = if (comma) .array_init_one_comma else .array_init_one,
20832067 .main_token = lbrace,
20842068 .data = .{
20852069 .lhs = lhs,
2086 .rhs = elem_init,
2070 .rhs = inits[0],
20872071 },
2088 });
2089 }
2090 if (comma_one == null) {
2091 try p.warnExpected(.comma);
2092 }
2093
2094 const scratch_top = p.scratch.items.len;
2095 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2096
2097 try p.scratch.append(p.gpa, elem_init);
2098
2099 var trailing_comma = true;
2100 var next = try p.parseExpr();
2101 while (next != 0) : (next = try p.parseExpr()) {
2102 try p.scratch.append(p.gpa, next);
2103 if (p.eatToken(.comma) == null) {
2104 trailing_comma = false;
2105 break;
2106 }
2072 }),
2073 else => return p.addNode(.{
2074 .tag = if (comma) .array_init_comma else .array_init,
2075 .main_token = lbrace,
2076 .data = .{
2077 .lhs = lhs,
2078 .rhs = try p.addExtra(try p.listToSpan(inits)),
2079 },
2080 }),
21072081 }
2108 _ = try p.expectToken(.r_brace);
2109 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2110 return p.addNode(.{
2111 .tag = if (trailing_comma) .array_init_comma else .array_init,
2112 .main_token = lbrace,
2113 .data = .{
2114 .lhs = lhs,
2115 .rhs = try p.addExtra(Node.SubRange{
2116 .start = span.start,
2117 .end = span.end,
2118 }),
2119 },
2120 });
21212082 }
21222083
21232084 /// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
......@@ -2143,184 +2104,109 @@ const Parser = struct {
21432104 fn parseSuffixExpr(p: *Parser) !Node.Index {
21442105 if (p.eatToken(.keyword_async)) |async_token| {
21452106 var res = try p.expectPrimaryTypeExpr();
2146
21472107 while (true) {
21482108 const node = try p.parseSuffixOp(res);
21492109 if (node == 0) break;
21502110 res = node;
21512111 }
2152 const lparen = p.nextToken();
2153 if (p.token_tags[lparen] != .l_paren) {
2154 p.tok_i -= 1;
2112 const lparen = p.eatToken(.l_paren) orelse {
21552113 try p.warn(.expected_param_list);
21562114 return res;
2115 };
2116 const scratch_top = p.scratch.items.len;
2117 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2118 while (true) {
2119 if (p.eatToken(.r_paren)) |_| break;
2120 const param = try p.expectExpr();
2121 try p.scratch.append(p.gpa, param);
2122 switch (p.token_tags[p.tok_i]) {
2123 .comma => p.tok_i += 1,
2124 .r_paren => { p.tok_i += 1; break; },
2125 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
2126 // Likely just a missing comma; give error but continue parsing.
2127 else => try p.warnExpected(.comma),
2128 }
21572129 }
2158 if (p.eatToken(.r_paren)) |_| {
2159 return p.addNode(.{
2160 .tag = .async_call_one,
2130 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2131 const params = p.scratch.items[scratch_top..];
2132 switch(params.len) {
2133 0 => return p.addNode(.{
2134 .tag = if (comma) .async_call_one_comma else .async_call_one,
21612135 .main_token = lparen,
21622136 .data = .{
21632137 .lhs = res,
21642138 .rhs = 0,
21652139 },
2166 });
2167 }
2168 const param_one = try p.expectExpr();
2169 const comma_one = p.eatToken(.comma);
2170 if (p.eatToken(.r_paren)) |_| {
2171 return p.addNode(.{
2172 .tag = if (comma_one == null) .async_call_one else .async_call_one_comma,
2140 }),
2141 1 => return p.addNode(.{
2142 .tag = if (comma) .async_call_one_comma else .async_call_one,
21732143 .main_token = lparen,
21742144 .data = .{
21752145 .lhs = res,
2176 .rhs = param_one,
2177 },
2178 });
2179 }
2180 if (comma_one == null) {
2181 try p.warnExpected(.comma);
2182 }
2183
2184 const scratch_top = p.scratch.items.len;
2185 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2186
2187 try p.scratch.append(p.gpa, param_one);
2188
2189 while (true) {
2190 const next = try p.expectExpr();
2191 try p.scratch.append(p.gpa, next);
2192 switch (p.token_tags[p.nextToken()]) {
2193 .comma => {
2194 if (p.eatToken(.r_paren)) |_| {
2195 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2196 return p.addNode(.{
2197 .tag = .async_call_comma,
2198 .main_token = lparen,
2199 .data = .{
2200 .lhs = res,
2201 .rhs = try p.addExtra(Node.SubRange{
2202 .start = span.start,
2203 .end = span.end,
2204 }),
2205 },
2206 });
2207 } else {
2208 continue;
2209 }
2210 },
2211 .r_paren => {
2212 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2213 return p.addNode(.{
2214 .tag = .async_call,
2215 .main_token = lparen,
2216 .data = .{
2217 .lhs = res,
2218 .rhs = try p.addExtra(Node.SubRange{
2219 .start = span.start,
2220 .end = span.end,
2221 }),
2222 },
2223 });
2146 .rhs = params[0],
22242147 },
2225 .colon, .r_brace, .r_bracket => {
2226 p.tok_i -= 1;
2227 return p.failExpected(.r_paren);
2228 },
2229 else => {
2230 p.tok_i -= 1;
2231 try p.warnExpected(.comma);
2148 }),
2149 else => return p.addNode(.{
2150 .tag = if (comma) .async_call_comma else .async_call,
2151 .main_token = lparen,
2152 .data = .{
2153 .lhs = res,
2154 .rhs = try p.addExtra(try p.listToSpan(params)),
22322155 },
2233 }
2156 }),
22342157 }
22352158 }
2159
22362160 var res = try p.parsePrimaryTypeExpr();
22372161 if (res == 0) return res;
2238
22392162 while (true) {
22402163 const suffix_op = try p.parseSuffixOp(res);
22412164 if (suffix_op != 0) {
22422165 res = suffix_op;
22432166 continue;
22442167 }
2245 res = res: {
2246 const lparen = p.eatToken(.l_paren) orelse return res;
2247 if (p.eatToken(.r_paren)) |_| {
2248 break :res try p.addNode(.{
2249 .tag = .call_one,
2250 .main_token = lparen,
2251 .data = .{
2252 .lhs = res,
2253 .rhs = 0,
2254 },
2255 });
2256 }
2257 const param_one = try p.expectExpr();
2258 const comma_one = p.eatToken(.comma);
2259 if (p.eatToken(.r_paren)) |_| {
2260 break :res try p.addNode(.{
2261 .tag = if (comma_one == null) .call_one else .call_one_comma,
2262 .main_token = lparen,
2263 .data = .{
2264 .lhs = res,
2265 .rhs = param_one,
2266 },
2267 });
2268 }
2269 if (comma_one == null) {
2270 try p.warnExpected(.comma);
2271 }
2272
2273 const scratch_top = p.scratch.items.len;
2274 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2275
2276 try p.scratch.append(p.gpa, param_one);
2277
2278 while (true) {
2279 const next = try p.expectExpr();
2280 try p.scratch.append(p.gpa, next);
2281 switch (p.token_tags[p.nextToken()]) {
2282 .comma => {
2283 if (p.eatToken(.r_paren)) |_| {
2284 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2285 break :res try p.addNode(.{
2286 .tag = .call_comma,
2287 .main_token = lparen,
2288 .data = .{
2289 .lhs = res,
2290 .rhs = try p.addExtra(Node.SubRange{
2291 .start = span.start,
2292 .end = span.end,
2293 }),
2294 },
2295 });
2296 } else {
2297 continue;
2298 }
2299 },
2300 .r_paren => {
2301 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2302 break :res try p.addNode(.{
2303 .tag = .call,
2304 .main_token = lparen,
2305 .data = .{
2306 .lhs = res,
2307 .rhs = try p.addExtra(Node.SubRange{
2308 .start = span.start,
2309 .end = span.end,
2310 }),
2311 },
2312 });
2313 },
2314 .colon, .r_brace, .r_bracket => {
2315 p.tok_i -= 1;
2316 return p.failExpected(.r_paren);
2317 },
2318 else => {
2319 p.tok_i -= 1;
2320 try p.warnExpected(.comma);
2321 },
2322 }
2168 const lparen = p.eatToken(.l_paren) orelse return res;
2169 const scratch_top = p.scratch.items.len;
2170 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2171 while (true) {
2172 if (p.eatToken(.r_paren)) |_| break;
2173 const param = try p.expectExpr();
2174 try p.scratch.append(p.gpa, param);
2175 switch (p.token_tags[p.tok_i]) {
2176 .comma => p.tok_i += 1,
2177 .r_paren => { p.tok_i += 1; break; },
2178 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
2179 // Likely just a missing comma; give error but continue parsing.
2180 else => try p.warnExpected(.comma),
23232181 }
2182 }
2183 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2184 const params = p.scratch.items[scratch_top..];
2185 res = switch(params.len) {
2186 0 => try p.addNode(.{
2187 .tag = if (comma) .call_one_comma else .call_one,
2188 .main_token = lparen,
2189 .data = .{
2190 .lhs = res,
2191 .rhs = 0,
2192 },
2193 }),
2194 1 => try p.addNode(.{
2195 .tag = if (comma) .call_one_comma else .call_one,
2196 .main_token = lparen,
2197 .data = .{
2198 .lhs = res,
2199 .rhs = params[0],
2200 },
2201 }),
2202 else => try p.addNode(.{
2203 .tag = if (comma) .call_comma else .call,
2204 .main_token = lparen,
2205 .data = .{
2206 .lhs = res,
2207 .rhs = try p.addExtra(try p.listToSpan(params)),
2208 },
2209 }),
23242210 };
23252211 }
23262212 }
......@@ -2554,148 +2440,108 @@ const Parser = struct {
25542440 // If there are 0, 1, or 2 items, we can use ArrayInitDotTwo/StructInitDotTwo;
25552441 // otherwise we use the full ArrayInitDot/StructInitDot.
25562442
2557 if (p.eatToken(.r_brace)) |_| {
2558 return p.addNode(.{
2559 .tag = .struct_init_dot_two,
2560 .main_token = lbrace,
2561 .data = .{
2562 .lhs = 0,
2563 .rhs = 0,
2564 },
2565 });
2566 }
2567 const field_init_one = try p.parseFieldInit();
2568 if (field_init_one != 0) {
2569 const comma_one = p.eatToken(.comma);
2570 if (p.eatToken(.r_brace)) |_| {
2571 return p.addNode(.{
2572 .tag = if (comma_one != null) .struct_init_dot_two_comma else .struct_init_dot_two,
2443 const scratch_top = p.scratch.items.len;
2444 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2445 const field_init = try p.parseFieldInit();
2446 if (field_init != 0) {
2447 try p.scratch.append(p.gpa, field_init);
2448 while (true) {
2449 switch (p.token_tags[p.tok_i]) {
2450 .comma => p.tok_i += 1,
2451 .r_brace => { p.tok_i += 1; break; },
2452 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
2453 // Likely just a missing comma; give error but continue parsing.
2454 else => try p.warnExpected(.comma),
2455 }
2456 if (p.eatToken(.r_brace)) |_| break;
2457 const next = try p.expectFieldInit();
2458 try p.scratch.append(p.gpa, next);
2459 }
2460 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2461 const inits = p.scratch.items[scratch_top..];
2462 switch (inits.len) {
2463 0 => unreachable,
2464 1 => return p.addNode(.{
2465 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
25732466 .main_token = lbrace,
25742467 .data = .{
2575 .lhs = field_init_one,
2468 .lhs = inits[0],
25762469 .rhs = 0,
25772470 },
2578 });
2579 }
2580 if (comma_one == null) {
2581 try p.warnExpected(.comma);
2582 }
2583 const field_init_two = try p.expectFieldInit();
2584 const comma_two = p.eatToken(.comma);
2585 if (p.eatToken(.r_brace)) |_| {
2586 return p.addNode(.{
2587 .tag = if (comma_two != null) .struct_init_dot_two_comma else .struct_init_dot_two,
2471 }),
2472 2 => return p.addNode(.{
2473 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
25882474 .main_token = lbrace,
25892475 .data = .{
2590 .lhs = field_init_one,
2591 .rhs = field_init_two,
2476 .lhs = inits[0],
2477 .rhs = inits[1],
25922478 },
2593 });
2594 }
2595 if (comma_two == null) {
2596 try p.warnExpected(.comma);
2479 }),
2480 else => {
2481 const span = try p.listToSpan(inits);
2482 return p.addNode(.{
2483 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
2484 .main_token = lbrace,
2485 .data = .{
2486 .lhs = span.start,
2487 .rhs = span.end,
2488 },
2489 });
2490 },
25972491 }
2598 const scratch_top = p.scratch.items.len;
2599 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2600
2601 try p.scratch.appendSlice(p.gpa, &.{ field_init_one, field_init_two });
2492 }
26022493
2603 while (true) {
2604 const next = try p.expectFieldInit();
2605 assert(next != 0);
2606 try p.scratch.append(p.gpa, next);
2607 switch (p.token_tags[p.nextToken()]) {
2608 .comma => {
2609 if (p.eatToken(.r_brace)) |_| break;
2610 continue;
2611 },
2612 .r_brace => break,
2613 .colon, .r_paren, .r_bracket => {
2614 p.tok_i -= 1;
2615 return p.failExpected(.r_brace);
2616 },
2617 else => {
2618 p.tok_i -= 1;
2619 try p.warnExpected(.comma);
2620 },
2621 }
2494 while (true) {
2495 if (p.eatToken(.r_brace)) |_| break;
2496 const elem_init = try p.expectExpr();
2497 try p.scratch.append(p.gpa, elem_init);
2498 switch (p.token_tags[p.tok_i]) {
2499 .comma => p.tok_i += 1,
2500 .r_brace => { p.tok_i += 1; break; },
2501 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
2502 // Likely just a missing comma; give error but continue parsing.
2503 else => try p.warnExpected(.comma),
26222504 }
2623 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2624 const trailing_comma = p.token_tags[p.tok_i - 2] == .comma;
2625 return p.addNode(.{
2626 .tag = if (trailing_comma) .struct_init_dot_comma else .struct_init_dot,
2505 }
2506 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2507 const inits = p.scratch.items[scratch_top..];
2508 switch (inits.len) {
2509 0 => return p.addNode(.{
2510 .tag = .struct_init_dot_two,
26272511 .main_token = lbrace,
26282512 .data = .{
2629 .lhs = span.start,
2630 .rhs = span.end,
2513 .lhs = 0,
2514 .rhs = 0,
26312515 },
2632 });
2633 }
2634
2635 const elem_init_one = try p.expectExpr();
2636 const comma_one = p.eatToken(.comma);
2637 if (p.eatToken(.r_brace)) |_| {
2638 return p.addNode(.{
2639 .tag = if (comma_one != null) .array_init_dot_two_comma else .array_init_dot_two,
2516 }),
2517 1 => return p.addNode(.{
2518 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,
26402519 .main_token = lbrace,
26412520 .data = .{
2642 .lhs = elem_init_one,
2521 .lhs = inits[0],
26432522 .rhs = 0,
26442523 },
2645 });
2646 }
2647 if (comma_one == null) {
2648 try p.warnExpected(.comma);
2649 }
2650 const elem_init_two = try p.expectExpr();
2651 const comma_two = p.eatToken(.comma);
2652 if (p.eatToken(.r_brace)) |_| {
2653 return p.addNode(.{
2654 .tag = if (comma_two != null) .array_init_dot_two_comma else .array_init_dot_two,
2524 }),
2525 2 => return p.addNode(.{
2526 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,
26552527 .main_token = lbrace,
26562528 .data = .{
2657 .lhs = elem_init_one,
2658 .rhs = elem_init_two,
2659 },
2660 });
2661 }
2662 if (comma_two == null) {
2663 try p.warnExpected(.comma);
2664 }
2665 const scratch_top = p.scratch.items.len;
2666 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2667
2668 try p.scratch.appendSlice(p.gpa, &.{ elem_init_one, elem_init_two });
2669
2670 while (true) {
2671 const next = try p.expectExpr();
2672 if (next == 0) break;
2673 try p.scratch.append(p.gpa, next);
2674 switch (p.token_tags[p.nextToken()]) {
2675 .comma => {
2676 if (p.eatToken(.r_brace)) |_| break;
2677 continue;
2678 },
2679 .r_brace => break,
2680 .colon, .r_paren, .r_bracket => {
2681 p.tok_i -= 1;
2682 return p.failExpected(.r_brace);
2529 .lhs = inits[0],
2530 .rhs = inits[1],
26832531 },
2684 else => {
2685 p.tok_i -= 1;
2686 try p.warnExpected(.comma);
2687 },
2688 }
2689 }
2690 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
2691 return p.addNode(.{
2692 .tag = if (p.token_tags[p.tok_i - 2] == .comma) .array_init_dot_comma else .array_init_dot,
2693 .main_token = lbrace,
2694 .data = .{
2695 .lhs = span.start,
2696 .rhs = span.end,
2532 }),
2533 else => {
2534 const span = try p.listToSpan(inits);
2535 return p.addNode(.{
2536 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
2537 .main_token = lbrace,
2538 .data = .{
2539 .lhs = span.start,
2540 .rhs = span.end,
2541 },
2542 });
26972543 },
2698 });
2544 }
26992545 },
27002546 else => return null_node,
27012547 },
......@@ -2703,37 +2549,16 @@ const Parser = struct {
27032549 .l_brace => {
27042550 const error_token = p.tok_i;
27052551 p.tok_i += 2;
2706
2707 if (p.eatToken(.r_brace)) |rbrace| {
2708 return p.addNode(.{
2709 .tag = .error_set_decl,
2710 .main_token = error_token,
2711 .data = .{
2712 .lhs = undefined,
2713 .rhs = rbrace,
2714 },
2715 });
2716 }
2717
27182552 while (true) {
2553 if (p.eatToken(.r_brace)) |_| break;
27192554 const doc_comment = try p.eatDocComments();
27202555 const identifier = try p.expectToken(.identifier);
2721 switch (p.token_tags[p.nextToken()]) {
2722 .comma => {
2723 if (p.eatToken(.r_brace)) |_| break;
2724 continue;
2725 },
2726 .r_brace => break,
2727 .colon, .r_paren, .r_bracket => {
2728 p.tok_i -= 1;
2729 return p.failExpected(.r_brace);
2730 },
2731 else => {
2732 // This is likely just a missing comma;
2733 // give an error but continue parsing this list.
2734 p.tok_i -= 1;
2735 try p.warnExpected(.comma);
2736 },
2556 switch (p.token_tags[p.tok_i]) {
2557 .comma => p.tok_i += 1,
2558 .r_brace => { p.tok_i += 1; break; },
2559 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
2560 // Likely just a missing comma; give error but continue parsing.
2561 else => try p.warnExpected(.comma),
27372562 }
27382563 }
27392564 return p.addNode(.{
......@@ -2791,7 +2616,7 @@ const Parser = struct {
27912616 const found_payload = try p.parsePtrIndexPayload();
27922617 if (found_payload == 0) try p.warn(.expected_loop_payload);
27932618
2794 const then_expr = try p.expectExpr();
2619 const then_expr = try p.expectTypeExpr();
27952620 const else_token = p.eatToken(.keyword_else) orelse {
27962621 return p.addNode(.{
27972622 .tag = .for_simple,
......@@ -2926,12 +2751,10 @@ const Parser = struct {
29262751 try p.scratch.append(p.gpa, output_item);
29272752 switch (p.token_tags[p.tok_i]) {
29282753 .comma => p.tok_i += 1,
2929 .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters.
2930 else => {
2931 // This is likely just a missing comma;
2932 // give an error but continue parsing this list.
2933 try p.warnExpected(.comma);
2934 },
2754 // All possible delimiters.
2755 .colon, .r_paren, .r_brace, .r_bracket => break,
2756 // Likely just a missing comma; give error but continue parsing.
2757 else => try p.warnExpected(.comma),
29352758 }
29362759 }
29372760 if (p.eatToken(.colon)) |_| {
......@@ -2941,12 +2764,10 @@ const Parser = struct {
29412764 try p.scratch.append(p.gpa, input_item);
29422765 switch (p.token_tags[p.tok_i]) {
29432766 .comma => p.tok_i += 1,
2944 .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters.
2945 else => {
2946 // This is likely just a missing comma;
2947 // give an error but continue parsing this list.
2948 try p.warnExpected(.comma);
2949 },
2767 // All possible delimiters.
2768 .colon, .r_paren, .r_brace, .r_bracket => break,
2769 // Likely just a missing comma; give error but continue parsing.
2770 else => try p.warnExpected(.comma),
29502771 }
29512772 }
29522773 if (p.eatToken(.colon)) |_| {
......@@ -2954,11 +2775,8 @@ const Parser = struct {
29542775 switch (p.token_tags[p.tok_i]) {
29552776 .comma => p.tok_i += 1,
29562777 .colon, .r_paren, .r_brace, .r_bracket => break,
2957 else => {
2958 // This is likely just a missing comma;
2959 // give an error but continue parsing this list.
2960 try p.warnExpected(.comma);
2961 },
2778 // Likely just a missing comma; give error but continue parsing.
2779 else => try p.warnExpected(.comma),
29622780 }
29632781 }
29642782 }
......@@ -3158,56 +2976,48 @@ const Parser = struct {
31582976 /// <- SwitchItem (COMMA SwitchItem)* COMMA?
31592977 /// / KEYWORD_else
31602978 fn parseSwitchProng(p: *Parser) !Node.Index {
3161 if (p.eatToken(.keyword_else)) |_| {
3162 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
3163 _ = try p.parsePtrPayload();
3164 return p.addNode(.{
2979 const scratch_top = p.scratch.items.len;
2980 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2981
2982 if (p.eatToken(.keyword_else) == null) {
2983 while (true) {
2984 const item = try p.parseSwitchItem();
2985 if (item == 0) break;
2986 try p.scratch.append(p.gpa, item);
2987 if (p.eatToken(.comma) == null) break;
2988 }
2989 if (scratch_top == p.scratch.items.len) return null_node;
2990 }
2991 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
2992 _ = try p.parsePtrPayload();
2993
2994 const items = p.scratch.items[scratch_top..];
2995 switch(items.len) {
2996 0 => return p.addNode(.{
31652997 .tag = .switch_case_one,
31662998 .main_token = arrow_token,
31672999 .data = .{
31683000 .lhs = 0,
31693001 .rhs = try p.expectAssignExpr(),
3170 },
3171 });
3172 }
3173 const first_item = try p.parseSwitchItem();
3174 if (first_item == 0) return null_node;
3175
3176 if (p.eatToken(.equal_angle_bracket_right)) |arrow_token| {
3177 _ = try p.parsePtrPayload();
3178 return p.addNode(.{
3002 }
3003 }),
3004 1 => return p.addNode(.{
31793005 .tag = .switch_case_one,
31803006 .main_token = arrow_token,
31813007 .data = .{
3182 .lhs = first_item,
3008 .lhs = items[0],
3009 .rhs = try p.expectAssignExpr(),
3010 }
3011 }),
3012 else => return p.addNode(.{
3013 .tag = .switch_case,
3014 .main_token = arrow_token,
3015 .data = .{
3016 .lhs = try p.addExtra(try p.listToSpan(items)),
31833017 .rhs = try p.expectAssignExpr(),
31843018 },
3185 });
3186 }
3187
3188 const scratch_top = p.scratch.items.len;
3189 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3190
3191 try p.scratch.append(p.gpa, first_item);
3192 while (p.eatToken(.comma)) |_| {
3193 const next_item = try p.parseSwitchItem();
3194 if (next_item == 0) break;
3195 try p.scratch.append(p.gpa, next_item);
3019 }),
31963020 }
3197 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
3198 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
3199 _ = try p.parsePtrPayload();
3200 return p.addNode(.{
3201 .tag = .switch_case,
3202 .main_token = arrow_token,
3203 .data = .{
3204 .lhs = try p.addExtra(Node.SubRange{
3205 .start = span.start,
3206 .end = span.end,
3207 }),
3208 .rhs = try p.expectAssignExpr(),
3209 },
3210 });
32113021 }
32123022
32133023 /// SwitchItem <- Expr (DOT3 Expr)?
......@@ -3563,19 +3373,12 @@ const Parser = struct {
35633373 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
35643374 if (varargs == .none) varargs = .seen;
35653375 }
3566 switch (p.token_tags[p.nextToken()]) {
3567 .comma => {},
3568 .r_paren => break,
3569 .colon, .r_brace, .r_bracket => {
3570 p.tok_i -= 1;
3571 return p.failExpected(.r_paren);
3572 },
3573 else => {
3574 // This is likely just a missing comma;
3575 // give an error but continue parsing this list.
3576 p.tok_i -= 1;
3577 try p.warnExpected(.comma);
3578 },
3376 switch (p.token_tags[p.tok_i]) {
3377 .comma => p.tok_i += 1,
3378 .r_paren => { p.tok_i += 1; break; },
3379 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
3380 // Likely just a missing comma; give error but continue parsing.
3381 else => try p.warnExpected(.comma),
35793382 }
35803383 }
35813384 if (varargs == .nonfinal) {
......@@ -3605,13 +3408,10 @@ const Parser = struct {
36053408
36063409 switch (p.token_tags[p.tok_i]) {
36073410 .comma => p.tok_i += 1,
3608 // all possible delimiters
3411 // All possible delimiters.
36093412 .colon, .r_paren, .r_brace, .r_bracket => break,
3610 else => {
3611 // This is likely just a missing comma;
3612 // give an error but continue parsing this list.
3613 try p.warnExpected(.comma);
3614 },
3413 // Likely just a missing comma; give error but continue parsing.
3414 else => try p.warnExpected(.comma),
36153415 }
36163416 }
36173417 return p.listToSpan(p.scratch.items[scratch_top..]);
......@@ -3636,117 +3436,58 @@ const Parser = struct {
36363436 },
36373437 });
36383438 }
3639 if (p.eatToken(.r_paren)) |_| {
3640 return p.addNode(.{
3439 const scratch_top = p.scratch.items.len;
3440 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3441 while (true) {
3442 if (p.eatToken(.r_paren)) |_| break;
3443 const param = try p.expectExpr();
3444 try p.scratch.append(p.gpa, param);
3445 switch (p.token_tags[p.tok_i]) {
3446 .comma => p.tok_i += 1,
3447 .r_paren => { p.tok_i += 1; break; },
3448 // Likely just a missing comma; give error but continue parsing.
3449 else => try p.warnExpected(.comma),
3450 }
3451 }
3452 const comma = (p.token_tags[p.tok_i - 2] == .comma);
3453 const params = p.scratch.items[scratch_top..];
3454 switch (params.len) {
3455 0 => return p.addNode(.{
36413456 .tag = .builtin_call_two,
36423457 .main_token = builtin_token,
36433458 .data = .{
36443459 .lhs = 0,
36453460 .rhs = 0,
36463461 },
3647 });
3648 }
3649 const param_one = try p.expectExpr();
3650 switch (p.token_tags[p.nextToken()]) {
3651 .comma => {
3652 if (p.eatToken(.r_paren)) |_| {
3653 return p.addNode(.{
3654 .tag = .builtin_call_two_comma,
3655 .main_token = builtin_token,
3656 .data = .{
3657 .lhs = param_one,
3658 .rhs = 0,
3659 },
3660 });
3661 }
3662 },
3663 .r_paren => return p.addNode(.{
3664 .tag = .builtin_call_two,
3462 }),
3463 1 => return p.addNode(.{
3464 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
36653465 .main_token = builtin_token,
36663466 .data = .{
3667 .lhs = param_one,
3467 .lhs = params[0],
36683468 .rhs = 0,
36693469 },
36703470 }),
3671 else => {
3672 // This is likely just a missing comma;
3673 // give an error but continue parsing this list.
3674 p.tok_i -= 1;
3675 try p.warnExpected(.comma);
3676 },
3677 }
3678 const param_two = try p.expectExpr();
3679 switch (p.token_tags[p.nextToken()]) {
3680 .comma => {
3681 if (p.eatToken(.r_paren)) |_| {
3682 return p.addNode(.{
3683 .tag = .builtin_call_two_comma,
3684 .main_token = builtin_token,
3685 .data = .{
3686 .lhs = param_one,
3687 .rhs = param_two,
3688 },
3689 });
3690 }
3691 },
3692 .r_paren => return p.addNode(.{
3693 .tag = .builtin_call_two,
3471 2 => return p.addNode(.{
3472 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
36943473 .main_token = builtin_token,
36953474 .data = .{
3696 .lhs = param_one,
3697 .rhs = param_two,
3475 .lhs = params[0],
3476 .rhs = params[1],
36983477 },
36993478 }),
37003479 else => {
3701 // This is likely just a missing comma;
3702 // give an error but continue parsing this list.
3703 p.tok_i -= 1;
3704 try p.warnExpected(.comma);
3480 const span = try p.listToSpan(params);
3481 return p.addNode(.{
3482 .tag = if (comma) .builtin_call_comma else .builtin_call,
3483 .main_token = builtin_token,
3484 .data = .{
3485 .lhs = span.start,
3486 .rhs = span.end,
3487 },
3488 });
37053489 },
37063490 }
3707
3708 const scratch_top = p.scratch.items.len;
3709 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3710
3711 try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two });
3712
3713 while (true) {
3714 const param = try p.expectExpr();
3715 try p.scratch.append(p.gpa, param);
3716 switch (p.token_tags[p.nextToken()]) {
3717 .comma => {
3718 if (p.eatToken(.r_paren)) |_| {
3719 const params = try p.listToSpan(p.scratch.items[scratch_top..]);
3720 return p.addNode(.{
3721 .tag = .builtin_call_comma,
3722 .main_token = builtin_token,
3723 .data = .{
3724 .lhs = params.start,
3725 .rhs = params.end,
3726 },
3727 });
3728 }
3729 continue;
3730 },
3731 .r_paren => {
3732 const params = try p.listToSpan(p.scratch.items[scratch_top..]);
3733 return p.addNode(.{
3734 .tag = .builtin_call,
3735 .main_token = builtin_token,
3736 .data = .{
3737 .lhs = params.start,
3738 .rhs = params.end,
3739 },
3740 });
3741 },
3742 else => {
3743 // This is likely just a missing comma;
3744 // give an error but continue parsing this list.
3745 p.tok_i -= 1;
3746 try p.warnExpected(.comma);
3747 },
3748 }
3749 }
37503491 }
37513492
37523493 // string literal or multiline string literal
lib/std/zig/parser_test.zig+1-1
......@@ -5154,7 +5154,7 @@ test "recovery: missing for payload" {
51545154 try testError(
51555155 \\comptime {
51565156 \\ const a = for(a) {};
5157 \\ const a: for(a) {};
5157 \\ const a: for(a) blk: {};
51585158 \\ for(a) {}
51595159 \\}
51605160 , &[_]Error{