diff options
| author | Veikka Tuominen <git@vexu.eu> | 2021-06-13 19:49:41 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-13 19:49:41 +0300 |
| commit | f58fbb1004e26982ad83c61b3fecf5e575fb9210 (patch) | |
| tree | 328036fa9c7eb125307437e0fdf0244d782c9736 | |
| parent | 46b9e061e07700ad1372ed2e9d2af9a29f24d76c (diff) | |
| parent | 483933d88d4fbf00467a48df100075a40344766b (diff) | |
| download | zig-f58fbb1004e26982ad83c61b3fecf5e575fb9210.tar.gz zig-f58fbb1004e26982ad83c61b3fecf5e575fb9210.zip | |
Merge pull request #9074 from mattbork/parse-always-scratch
parse.zig: simplify parsing functions that build lists by always using scratch buffer
| -rw-r--r-- | lib/std/zig/parse.zig | 941 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 2 |
2 files changed, 342 insertions, 601 deletions
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 78ef8e78cb..4d5cadb37b 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1850,65 +1850,54 @@ const Parser = struct { /// Block <- LBRACE Statement* RBRACE fn parseBlock(p: *Parser) !Node.Index { const lbrace = p.eatToken(.l_brace) orelse return null_node; - - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + while (true) { + if (p.token_tags[p.tok_i] == .r_brace) break; + const statement = try p.expectStatementRecoverable(); + if (statement == 0) break; + try p.scratch.append(p.gpa, statement); + } + _ = try p.expectToken(.r_brace); + const semicolon = (p.token_tags[p.tok_i - 2] == .semicolon); + const statements = p.scratch.items[scratch_top..]; + switch (statements.len) { + 0 => return p.addNode(.{ .tag = .block_two, .main_token = lbrace, .data = .{ .lhs = 0, .rhs = 0, }, - }); - } - - const stmt_one = try p.expectStatementRecoverable(); - if (p.eatToken(.r_brace)) |_| { - const semicolon = p.token_tags[p.tok_i - 2] == .semicolon; - return p.addNode(.{ + }), + 1 => return p.addNode(.{ .tag = if (semicolon) .block_two_semicolon else .block_two, .main_token = lbrace, .data = .{ - .lhs = stmt_one, + .lhs = statements[0], .rhs = 0, }, - }); - } - const stmt_two = try p.expectStatementRecoverable(); - if (p.eatToken(.r_brace)) |_| { - const semicolon = p.token_tags[p.tok_i - 2] == .semicolon; - return p.addNode(.{ + }), + 2 => return p.addNode(.{ .tag = if (semicolon) .block_two_semicolon else .block_two, .main_token = lbrace, .data = .{ - .lhs = stmt_one, - .rhs = stmt_two, + .lhs = statements[0], + .rhs = statements[1], }, - }); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two }); - - while (true) { - const statement = try p.expectStatementRecoverable(); - if (statement == 0) break; - try p.scratch.append(p.gpa, statement); - if (p.token_tags[p.tok_i] == .r_brace) break; - } - _ = try p.expectToken(.r_brace); - const semicolon = p.token_tags[p.tok_i - 2] == .semicolon; - const statements_span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = if (semicolon) .block_semicolon else .block, - .main_token = lbrace, - .data = .{ - .lhs = statements_span.start, - .rhs = statements_span.end, + }), + else => { + const span = try p.listToSpan(statements); + return p.addNode(.{ + .tag = if (semicolon) .block_semicolon else .block, + .main_token = lbrace, + .data = .{ + .lhs = span.start, + .rhs = span.end, + }, + }); }, - }); + } } /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload @@ -2010,114 +1999,86 @@ const Parser = struct { // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne; // otherwise we use the full ArrayInit/StructInit. - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = .struct_init_one, - .main_token = lbrace, - .data = .{ - .lhs = lhs, - .rhs = 0, - }, - }); - } + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); const field_init = try p.parseFieldInit(); if (field_init != 0) { - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_one != null) .struct_init_one_comma else .struct_init_one, - .main_token = lbrace, - .data = .{ - .lhs = lhs, - .rhs = field_init, - }, - }); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - try p.scratch.append(p.gpa, field_init); - while (true) { + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_brace => { p.tok_i += 1; break; }, + .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), + } + if (p.eatToken(.r_brace)) |_| break; const next = try p.expectFieldInit(); try p.scratch.append(p.gpa, next); - - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_brace)) |_| break; - continue; - }, - .r_brace => break, - .colon, .r_paren, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_brace); + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const inits = p.scratch.items[scratch_top..]; + switch (inits.len) { + 0 => unreachable, + 1 => return p.addNode(.{ + .tag = if (comma) .struct_init_one_comma else .struct_init_one, + .main_token = lbrace, + .data = .{ + .lhs = lhs, + .rhs = inits[0], }, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); + }), + else => return p.addNode(.{ + .tag = if (comma) .struct_init_comma else .struct_init, + .main_token = lbrace, + .data = .{ + .lhs = lhs, + .rhs = try p.addExtra(try p.listToSpan(inits)), }, - } + }), } - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = if (p.token_tags[p.tok_i - 2] == .comma) .struct_init_comma else .struct_init, + } + + while (true) { + if (p.eatToken(.r_brace)) |_| break; + const elem_init = try p.expectExpr(); + try p.scratch.append(p.gpa, elem_init); + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_brace => { p.tok_i += 1; break; }, + .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), + } + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const inits = p.scratch.items[scratch_top..]; + switch (inits.len) { + 0 => return p.addNode(.{ + .tag = .struct_init_one, .main_token = lbrace, .data = .{ .lhs = lhs, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), + .rhs = 0, }, - }); - } - - const elem_init = try p.expectExpr(); - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_one != null) .array_init_one_comma else .array_init_one, + }), + 1 => return p.addNode(.{ + .tag = if (comma) .array_init_one_comma else .array_init_one, .main_token = lbrace, .data = .{ .lhs = lhs, - .rhs = elem_init, + .rhs = inits[0], }, - }); - } - if (comma_one == null) { - try p.warnExpected(.comma); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.append(p.gpa, elem_init); - - var trailing_comma = true; - var next = try p.parseExpr(); - while (next != 0) : (next = try p.parseExpr()) { - try p.scratch.append(p.gpa, next); - if (p.eatToken(.comma) == null) { - trailing_comma = false; - break; - } + }), + else => return p.addNode(.{ + .tag = if (comma) .array_init_comma else .array_init, + .main_token = lbrace, + .data = .{ + .lhs = lhs, + .rhs = try p.addExtra(try p.listToSpan(inits)), + }, + }), } - _ = try p.expectToken(.r_brace); - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = if (trailing_comma) .array_init_comma else .array_init, - .main_token = lbrace, - .data = .{ - .lhs = lhs, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - }, - }); } /// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? @@ -2143,184 +2104,109 @@ const Parser = struct { fn parseSuffixExpr(p: *Parser) !Node.Index { if (p.eatToken(.keyword_async)) |async_token| { var res = try p.expectPrimaryTypeExpr(); - while (true) { const node = try p.parseSuffixOp(res); if (node == 0) break; res = node; } - const lparen = p.nextToken(); - if (p.token_tags[lparen] != .l_paren) { - p.tok_i -= 1; + const lparen = p.eatToken(.l_paren) orelse { try p.warn(.expected_param_list); return res; + }; + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + while (true) { + if (p.eatToken(.r_paren)) |_| break; + const param = try p.expectExpr(); + try p.scratch.append(p.gpa, param); + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_paren => { p.tok_i += 1; break; }, + .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), + } } - if (p.eatToken(.r_paren)) |_| { - return p.addNode(.{ - .tag = .async_call_one, + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const params = p.scratch.items[scratch_top..]; + switch(params.len) { + 0 => return p.addNode(.{ + .tag = if (comma) .async_call_one_comma else .async_call_one, .main_token = lparen, .data = .{ .lhs = res, .rhs = 0, }, - }); - } - const param_one = try p.expectExpr(); - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_paren)) |_| { - return p.addNode(.{ - .tag = if (comma_one == null) .async_call_one else .async_call_one_comma, + }), + 1 => return p.addNode(.{ + .tag = if (comma) .async_call_one_comma else .async_call_one, .main_token = lparen, .data = .{ .lhs = res, - .rhs = param_one, - }, - }); - } - if (comma_one == null) { - try p.warnExpected(.comma); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.append(p.gpa, param_one); - - while (true) { - const next = try p.expectExpr(); - try p.scratch.append(p.gpa, next); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_paren)) |_| { - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .async_call_comma, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - }, - }); - } else { - continue; - } - }, - .r_paren => { - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .async_call, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - }, - }); + .rhs = params[0], }, - .colon, .r_brace, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_paren); - }, - else => { - p.tok_i -= 1; - try p.warnExpected(.comma); + }), + else => return p.addNode(.{ + .tag = if (comma) .async_call_comma else .async_call, + .main_token = lparen, + .data = .{ + .lhs = res, + .rhs = try p.addExtra(try p.listToSpan(params)), }, - } + }), } } + var res = try p.parsePrimaryTypeExpr(); if (res == 0) return res; - while (true) { const suffix_op = try p.parseSuffixOp(res); if (suffix_op != 0) { res = suffix_op; continue; } - res = res: { - const lparen = p.eatToken(.l_paren) orelse return res; - if (p.eatToken(.r_paren)) |_| { - break :res try p.addNode(.{ - .tag = .call_one, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = 0, - }, - }); - } - const param_one = try p.expectExpr(); - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_paren)) |_| { - break :res try p.addNode(.{ - .tag = if (comma_one == null) .call_one else .call_one_comma, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = param_one, - }, - }); - } - if (comma_one == null) { - try p.warnExpected(.comma); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.append(p.gpa, param_one); - - while (true) { - const next = try p.expectExpr(); - try p.scratch.append(p.gpa, next); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_paren)) |_| { - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - break :res try p.addNode(.{ - .tag = .call_comma, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - }, - }); - } else { - continue; - } - }, - .r_paren => { - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - break :res try p.addNode(.{ - .tag = .call, - .main_token = lparen, - .data = .{ - .lhs = res, - .rhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - }, - }); - }, - .colon, .r_brace, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_paren); - }, - else => { - p.tok_i -= 1; - try p.warnExpected(.comma); - }, - } + const lparen = p.eatToken(.l_paren) orelse return res; + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + while (true) { + if (p.eatToken(.r_paren)) |_| break; + const param = try p.expectExpr(); + try p.scratch.append(p.gpa, param); + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_paren => { p.tok_i += 1; break; }, + .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const params = p.scratch.items[scratch_top..]; + res = switch(params.len) { + 0 => try p.addNode(.{ + .tag = if (comma) .call_one_comma else .call_one, + .main_token = lparen, + .data = .{ + .lhs = res, + .rhs = 0, + }, + }), + 1 => try p.addNode(.{ + .tag = if (comma) .call_one_comma else .call_one, + .main_token = lparen, + .data = .{ + .lhs = res, + .rhs = params[0], + }, + }), + else => try p.addNode(.{ + .tag = if (comma) .call_comma else .call, + .main_token = lparen, + .data = .{ + .lhs = res, + .rhs = try p.addExtra(try p.listToSpan(params)), + }, + }), }; } } @@ -2554,148 +2440,108 @@ const Parser = struct { // If there are 0, 1, or 2 items, we can use ArrayInitDotTwo/StructInitDotTwo; // otherwise we use the full ArrayInitDot/StructInitDot. - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = .struct_init_dot_two, - .main_token = lbrace, - .data = .{ - .lhs = 0, - .rhs = 0, - }, - }); - } - const field_init_one = try p.parseFieldInit(); - if (field_init_one != 0) { - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_one != null) .struct_init_dot_two_comma else .struct_init_dot_two, + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + const field_init = try p.parseFieldInit(); + if (field_init != 0) { + try p.scratch.append(p.gpa, field_init); + while (true) { + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_brace => { p.tok_i += 1; break; }, + .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), + } + if (p.eatToken(.r_brace)) |_| break; + const next = try p.expectFieldInit(); + try p.scratch.append(p.gpa, next); + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const inits = p.scratch.items[scratch_top..]; + switch (inits.len) { + 0 => unreachable, + 1 => return p.addNode(.{ + .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, .main_token = lbrace, .data = .{ - .lhs = field_init_one, + .lhs = inits[0], .rhs = 0, }, - }); - } - if (comma_one == null) { - try p.warnExpected(.comma); - } - const field_init_two = try p.expectFieldInit(); - const comma_two = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_two != null) .struct_init_dot_two_comma else .struct_init_dot_two, + }), + 2 => return p.addNode(.{ + .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, .main_token = lbrace, .data = .{ - .lhs = field_init_one, - .rhs = field_init_two, + .lhs = inits[0], + .rhs = inits[1], }, - }); - } - if (comma_two == null) { - try p.warnExpected(.comma); + }), + else => { + const span = try p.listToSpan(inits); + return p.addNode(.{ + .tag = if (comma) .struct_init_dot_comma else .struct_init_dot, + .main_token = lbrace, + .data = .{ + .lhs = span.start, + .rhs = span.end, + }, + }); + }, } - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.appendSlice(p.gpa, &.{ field_init_one, field_init_two }); + } - while (true) { - const next = try p.expectFieldInit(); - assert(next != 0); - try p.scratch.append(p.gpa, next); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_brace)) |_| break; - continue; - }, - .r_brace => break, - .colon, .r_paren, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_brace); - }, - else => { - p.tok_i -= 1; - try p.warnExpected(.comma); - }, - } + while (true) { + if (p.eatToken(.r_brace)) |_| break; + const elem_init = try p.expectExpr(); + try p.scratch.append(p.gpa, elem_init); + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_brace => { p.tok_i += 1; break; }, + .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - const trailing_comma = p.token_tags[p.tok_i - 2] == .comma; - return p.addNode(.{ - .tag = if (trailing_comma) .struct_init_dot_comma else .struct_init_dot, + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const inits = p.scratch.items[scratch_top..]; + switch (inits.len) { + 0 => return p.addNode(.{ + .tag = .struct_init_dot_two, .main_token = lbrace, .data = .{ - .lhs = span.start, - .rhs = span.end, + .lhs = 0, + .rhs = 0, }, - }); - } - - const elem_init_one = try p.expectExpr(); - const comma_one = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_one != null) .array_init_dot_two_comma else .array_init_dot_two, + }), + 1 => return p.addNode(.{ + .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, .main_token = lbrace, .data = .{ - .lhs = elem_init_one, + .lhs = inits[0], .rhs = 0, }, - }); - } - if (comma_one == null) { - try p.warnExpected(.comma); - } - const elem_init_two = try p.expectExpr(); - const comma_two = p.eatToken(.comma); - if (p.eatToken(.r_brace)) |_| { - return p.addNode(.{ - .tag = if (comma_two != null) .array_init_dot_two_comma else .array_init_dot_two, + }), + 2 => return p.addNode(.{ + .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, .main_token = lbrace, .data = .{ - .lhs = elem_init_one, - .rhs = elem_init_two, - }, - }); - } - if (comma_two == null) { - try p.warnExpected(.comma); - } - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.appendSlice(p.gpa, &.{ elem_init_one, elem_init_two }); - - while (true) { - const next = try p.expectExpr(); - if (next == 0) break; - try p.scratch.append(p.gpa, next); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_brace)) |_| break; - continue; - }, - .r_brace => break, - .colon, .r_paren, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_brace); + .lhs = inits[0], + .rhs = inits[1], }, - else => { - p.tok_i -= 1; - try p.warnExpected(.comma); - }, - } - } - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = if (p.token_tags[p.tok_i - 2] == .comma) .array_init_dot_comma else .array_init_dot, - .main_token = lbrace, - .data = .{ - .lhs = span.start, - .rhs = span.end, + }), + else => { + const span = try p.listToSpan(inits); + return p.addNode(.{ + .tag = if (comma) .array_init_dot_comma else .array_init_dot, + .main_token = lbrace, + .data = .{ + .lhs = span.start, + .rhs = span.end, + }, + }); }, - }); + } }, else => return null_node, }, @@ -2703,37 +2549,16 @@ const Parser = struct { .l_brace => { const error_token = p.tok_i; p.tok_i += 2; - - if (p.eatToken(.r_brace)) |rbrace| { - return p.addNode(.{ - .tag = .error_set_decl, - .main_token = error_token, - .data = .{ - .lhs = undefined, - .rhs = rbrace, - }, - }); - } - while (true) { + if (p.eatToken(.r_brace)) |_| break; const doc_comment = try p.eatDocComments(); const identifier = try p.expectToken(.identifier); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_brace)) |_| break; - continue; - }, - .r_brace => break, - .colon, .r_paren, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_brace); - }, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); - }, + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_brace => { p.tok_i += 1; break; }, + .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } return p.addNode(.{ @@ -2791,7 +2616,7 @@ const Parser = struct { const found_payload = try p.parsePtrIndexPayload(); if (found_payload == 0) try p.warn(.expected_loop_payload); - const then_expr = try p.expectExpr(); + const then_expr = try p.expectTypeExpr(); const else_token = p.eatToken(.keyword_else) orelse { return p.addNode(.{ .tag = .for_simple, @@ -2926,12 +2751,10 @@ const Parser = struct { try p.scratch.append(p.gpa, output_item); switch (p.token_tags[p.tok_i]) { .comma => p.tok_i += 1, - .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - try p.warnExpected(.comma); - }, + // All possible delimiters. + .colon, .r_paren, .r_brace, .r_bracket => break, + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } if (p.eatToken(.colon)) |_| { @@ -2941,12 +2764,10 @@ const Parser = struct { try p.scratch.append(p.gpa, input_item); switch (p.token_tags[p.tok_i]) { .comma => p.tok_i += 1, - .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - try p.warnExpected(.comma); - }, + // All possible delimiters. + .colon, .r_paren, .r_brace, .r_bracket => break, + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } if (p.eatToken(.colon)) |_| { @@ -2954,11 +2775,8 @@ const Parser = struct { switch (p.token_tags[p.tok_i]) { .comma => p.tok_i += 1, .colon, .r_paren, .r_brace, .r_bracket => break, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - try p.warnExpected(.comma); - }, + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } } @@ -3158,56 +2976,48 @@ const Parser = struct { /// <- SwitchItem (COMMA SwitchItem)* COMMA? /// / KEYWORD_else fn parseSwitchProng(p: *Parser) !Node.Index { - if (p.eatToken(.keyword_else)) |_| { - const arrow_token = try p.expectToken(.equal_angle_bracket_right); - _ = try p.parsePtrPayload(); - return p.addNode(.{ + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + + if (p.eatToken(.keyword_else) == null) { + while (true) { + const item = try p.parseSwitchItem(); + if (item == 0) break; + try p.scratch.append(p.gpa, item); + if (p.eatToken(.comma) == null) break; + } + if (scratch_top == p.scratch.items.len) return null_node; + } + const arrow_token = try p.expectToken(.equal_angle_bracket_right); + _ = try p.parsePtrPayload(); + + const items = p.scratch.items[scratch_top..]; + switch(items.len) { + 0 => return p.addNode(.{ .tag = .switch_case_one, .main_token = arrow_token, .data = .{ .lhs = 0, .rhs = try p.expectAssignExpr(), - }, - }); - } - const first_item = try p.parseSwitchItem(); - if (first_item == 0) return null_node; - - if (p.eatToken(.equal_angle_bracket_right)) |arrow_token| { - _ = try p.parsePtrPayload(); - return p.addNode(.{ + } + }), + 1 => return p.addNode(.{ .tag = .switch_case_one, .main_token = arrow_token, .data = .{ - .lhs = first_item, + .lhs = items[0], + .rhs = try p.expectAssignExpr(), + } + }), + else => return p.addNode(.{ + .tag = .switch_case, + .main_token = arrow_token, + .data = .{ + .lhs = try p.addExtra(try p.listToSpan(items)), .rhs = try p.expectAssignExpr(), }, - }); - } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.append(p.gpa, first_item); - while (p.eatToken(.comma)) |_| { - const next_item = try p.parseSwitchItem(); - if (next_item == 0) break; - try p.scratch.append(p.gpa, next_item); + }), } - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - const arrow_token = try p.expectToken(.equal_angle_bracket_right); - _ = try p.parsePtrPayload(); - return p.addNode(.{ - .tag = .switch_case, - .main_token = arrow_token, - .data = .{ - .lhs = try p.addExtra(Node.SubRange{ - .start = span.start, - .end = span.end, - }), - .rhs = try p.expectAssignExpr(), - }, - }); } /// SwitchItem <- Expr (DOT3 Expr)? @@ -3563,19 +3373,12 @@ const Parser = struct { } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) { if (varargs == .none) varargs = .seen; } - switch (p.token_tags[p.nextToken()]) { - .comma => {}, - .r_paren => break, - .colon, .r_brace, .r_bracket => { - p.tok_i -= 1; - return p.failExpected(.r_paren); - }, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); - }, + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_paren => { p.tok_i += 1; break; }, + .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } if (varargs == .nonfinal) { @@ -3605,13 +3408,10 @@ const Parser = struct { switch (p.token_tags[p.tok_i]) { .comma => p.tok_i += 1, - // all possible delimiters + // All possible delimiters. .colon, .r_paren, .r_brace, .r_bracket => break, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - try p.warnExpected(.comma); - }, + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), } } return p.listToSpan(p.scratch.items[scratch_top..]); @@ -3636,117 +3436,58 @@ const Parser = struct { }, }); } - if (p.eatToken(.r_paren)) |_| { - return p.addNode(.{ + const scratch_top = p.scratch.items.len; + defer p.scratch.shrinkRetainingCapacity(scratch_top); + while (true) { + if (p.eatToken(.r_paren)) |_| break; + const param = try p.expectExpr(); + try p.scratch.append(p.gpa, param); + switch (p.token_tags[p.tok_i]) { + .comma => p.tok_i += 1, + .r_paren => { p.tok_i += 1; break; }, + // Likely just a missing comma; give error but continue parsing. + else => try p.warnExpected(.comma), + } + } + const comma = (p.token_tags[p.tok_i - 2] == .comma); + const params = p.scratch.items[scratch_top..]; + switch (params.len) { + 0 => return p.addNode(.{ .tag = .builtin_call_two, .main_token = builtin_token, .data = .{ .lhs = 0, .rhs = 0, }, - }); - } - const param_one = try p.expectExpr(); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_paren)) |_| { - return p.addNode(.{ - .tag = .builtin_call_two_comma, - .main_token = builtin_token, - .data = .{ - .lhs = param_one, - .rhs = 0, - }, - }); - } - }, - .r_paren => return p.addNode(.{ - .tag = .builtin_call_two, + }), + 1 => return p.addNode(.{ + .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, .main_token = builtin_token, .data = .{ - .lhs = param_one, + .lhs = params[0], .rhs = 0, }, }), - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); - }, - } - const param_two = try p.expectExpr(); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_paren)) |_| { - return p.addNode(.{ - .tag = .builtin_call_two_comma, - .main_token = builtin_token, - .data = .{ - .lhs = param_one, - .rhs = param_two, - }, - }); - } - }, - .r_paren => return p.addNode(.{ - .tag = .builtin_call_two, + 2 => return p.addNode(.{ + .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, .main_token = builtin_token, .data = .{ - .lhs = param_one, - .rhs = param_two, + .lhs = params[0], + .rhs = params[1], }, }), else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); + const span = try p.listToSpan(params); + return p.addNode(.{ + .tag = if (comma) .builtin_call_comma else .builtin_call, + .main_token = builtin_token, + .data = .{ + .lhs = span.start, + .rhs = span.end, + }, + }); }, } - - const scratch_top = p.scratch.items.len; - defer p.scratch.shrinkRetainingCapacity(scratch_top); - - try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two }); - - while (true) { - const param = try p.expectExpr(); - try p.scratch.append(p.gpa, param); - switch (p.token_tags[p.nextToken()]) { - .comma => { - if (p.eatToken(.r_paren)) |_| { - const params = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .builtin_call_comma, - .main_token = builtin_token, - .data = .{ - .lhs = params.start, - .rhs = params.end, - }, - }); - } - continue; - }, - .r_paren => { - const params = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .builtin_call, - .main_token = builtin_token, - .data = .{ - .lhs = params.start, - .rhs = params.end, - }, - }); - }, - else => { - // This is likely just a missing comma; - // give an error but continue parsing this list. - p.tok_i -= 1; - try p.warnExpected(.comma); - }, - } - } } // string literal or multiline string literal diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 9359aa2cd2..f6aab4ceca 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -5154,7 +5154,7 @@ test "recovery: missing for payload" { try testError( \\comptime { \\ const a = for(a) {}; - \\ const a: for(a) {}; + \\ const a: for(a) blk: {}; \\ for(a) {} \\} , &[_]Error{ |
