aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-06-13 19:49:41 +0300
committerGitHub <noreply@github.com>2021-06-13 19:49:41 +0300
commitf58fbb1004e26982ad83c61b3fecf5e575fb9210 (patch)
tree328036fa9c7eb125307437e0fdf0244d782c9736
parent46b9e061e07700ad1372ed2e9d2af9a29f24d76c (diff)
parent483933d88d4fbf00467a48df100075a40344766b (diff)
downloadzig-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.zig941
-rw-r--r--lib/std/zig/parser_test.zig2
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{