mirror of
https://github.com/ziglang/zig.git
synced 2025-12-29 17:43:17 +00:00
parse.zig: use shared scratch buffer to avoid allocating and freeing many small lists
This commit is contained in:
parent
f750618846
commit
9ddd12ea14
@ -43,11 +43,13 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!Tree {
|
||||
.errors = .{},
|
||||
.nodes = .{},
|
||||
.extra_data = .{},
|
||||
.scratch = .{},
|
||||
.tok_i = 0,
|
||||
};
|
||||
defer parser.errors.deinit(gpa);
|
||||
defer parser.nodes.deinit(gpa);
|
||||
defer parser.extra_data.deinit(gpa);
|
||||
defer parser.scratch.deinit(gpa);
|
||||
|
||||
// Empirically, Zig source code has a 2:1 ratio of tokens to AST nodes.
|
||||
// Make sure at least 1 so we can use appendAssumeCapacity on the root node below.
|
||||
@ -93,18 +95,7 @@ const Parser = struct {
|
||||
errors: std.ArrayListUnmanaged(AstError),
|
||||
nodes: ast.NodeList,
|
||||
extra_data: std.ArrayListUnmanaged(Node.Index),
|
||||
|
||||
const SmallSpan = union(enum) {
|
||||
zero_or_one: Node.Index,
|
||||
multi: []Node.Index,
|
||||
|
||||
fn deinit(self: SmallSpan, gpa: *Allocator) void {
|
||||
switch (self) {
|
||||
.zero_or_one => {},
|
||||
.multi => |list| gpa.free(list),
|
||||
}
|
||||
}
|
||||
};
|
||||
scratch: std.ArrayListUnmanaged(Node.Index),
|
||||
|
||||
const Members = struct {
|
||||
len: usize,
|
||||
@ -204,8 +195,8 @@ const Parser = struct {
|
||||
/// /
|
||||
/// TopLevelComptime <- KEYWORD_comptime BlockExpr
|
||||
fn parseContainerMembers(p: *Parser) !Members {
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
var field_state: union(enum) {
|
||||
/// No fields have been seen.
|
||||
@ -233,7 +224,7 @@ const Parser = struct {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = test_decl_node };
|
||||
}
|
||||
try list.append(test_decl_node);
|
||||
try p.scratch.append(p.gpa, test_decl_node);
|
||||
}
|
||||
trailing = false;
|
||||
},
|
||||
@ -254,7 +245,7 @@ const Parser = struct {
|
||||
field_state = .err;
|
||||
},
|
||||
}
|
||||
try list.append(container_field);
|
||||
try p.scratch.append(p.gpa, container_field);
|
||||
switch (p.token_tags[p.tok_i]) {
|
||||
.comma => {
|
||||
p.tok_i += 1;
|
||||
@ -294,7 +285,7 @@ const Parser = struct {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = comptime_node };
|
||||
}
|
||||
try list.append(comptime_node);
|
||||
try p.scratch.append(p.gpa, comptime_node);
|
||||
}
|
||||
trailing = false;
|
||||
},
|
||||
@ -310,7 +301,7 @@ const Parser = struct {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = top_level_decl };
|
||||
}
|
||||
try list.append(top_level_decl);
|
||||
try p.scratch.append(p.gpa, top_level_decl);
|
||||
}
|
||||
trailing = p.token_tags[p.tok_i - 1] == .semicolon;
|
||||
},
|
||||
@ -320,7 +311,7 @@ const Parser = struct {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = node };
|
||||
}
|
||||
try list.append(node);
|
||||
try p.scratch.append(p.gpa, node);
|
||||
}
|
||||
trailing = p.token_tags[p.tok_i - 1] == .semicolon;
|
||||
},
|
||||
@ -338,7 +329,7 @@ const Parser = struct {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = top_level_decl };
|
||||
}
|
||||
try list.append(top_level_decl);
|
||||
try p.scratch.append(p.gpa, top_level_decl);
|
||||
}
|
||||
trailing = p.token_tags[p.tok_i - 1] == .semicolon;
|
||||
},
|
||||
@ -357,7 +348,7 @@ const Parser = struct {
|
||||
field_state = .err;
|
||||
},
|
||||
}
|
||||
try list.append(container_field);
|
||||
try p.scratch.append(p.gpa, container_field);
|
||||
switch (p.token_tags[p.tok_i]) {
|
||||
.comma => {
|
||||
p.tok_i += 1;
|
||||
@ -393,7 +384,8 @@ const Parser = struct {
|
||||
}
|
||||
}
|
||||
|
||||
switch (list.items.len) {
|
||||
const items = p.scratch.items[scratch_top..];
|
||||
switch (items.len) {
|
||||
0 => return Members{
|
||||
.len = 0,
|
||||
.lhs = 0,
|
||||
@ -402,20 +394,20 @@ const Parser = struct {
|
||||
},
|
||||
1 => return Members{
|
||||
.len = 1,
|
||||
.lhs = list.items[0],
|
||||
.lhs = items[0],
|
||||
.rhs = 0,
|
||||
.trailing = trailing,
|
||||
},
|
||||
2 => return Members{
|
||||
.len = 2,
|
||||
.lhs = list.items[0],
|
||||
.rhs = list.items[1],
|
||||
.lhs = items[0],
|
||||
.rhs = items[1],
|
||||
.trailing = trailing,
|
||||
},
|
||||
else => {
|
||||
const span = try p.listToSpan(list.items);
|
||||
const span = try p.listToSpan(items);
|
||||
return Members{
|
||||
.len = list.items.len,
|
||||
.len = items.len,
|
||||
.lhs = span.start,
|
||||
.rhs = span.end,
|
||||
.trailing = trailing,
|
||||
@ -647,8 +639,10 @@ const Parser = struct {
|
||||
const fn_proto_index = try p.reserveNode();
|
||||
|
||||
_ = p.eatToken(.identifier);
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
// parseParamDeclList does not shrink scratch buffer, but we will
|
||||
const params = try p.parseParamDeclList();
|
||||
defer params.deinit(p.gpa);
|
||||
const align_expr = try p.parseByteAlign();
|
||||
const section_expr = try p.parseLinkSection();
|
||||
const callconv_expr = try p.parseCallconv();
|
||||
@ -662,17 +656,17 @@ const Parser = struct {
|
||||
}
|
||||
|
||||
if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
|
||||
switch (params) {
|
||||
.zero_or_one => |param| return p.setNode(fn_proto_index, .{
|
||||
switch (params.len) {
|
||||
0, 1 => return p.setNode(fn_proto_index, .{
|
||||
.tag = .fn_proto_simple,
|
||||
.main_token = fn_token,
|
||||
.data = .{
|
||||
.lhs = param,
|
||||
.lhs = if (params.len > 0) params[0] else 0,
|
||||
.rhs = return_type_expr,
|
||||
},
|
||||
}),
|
||||
.multi => |list| {
|
||||
const span = try p.listToSpan(list);
|
||||
else => {
|
||||
const span = try p.listToSpan(params);
|
||||
return p.setNode(fn_proto_index, .{
|
||||
.tag = .fn_proto_multi,
|
||||
.main_token = fn_token,
|
||||
@ -687,13 +681,13 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
switch (params) {
|
||||
.zero_or_one => |param| return p.setNode(fn_proto_index, .{
|
||||
switch (params.len) {
|
||||
0, 1 => return p.setNode(fn_proto_index, .{
|
||||
.tag = .fn_proto_one,
|
||||
.main_token = fn_token,
|
||||
.data = .{
|
||||
.lhs = try p.addExtra(Node.FnProtoOne{
|
||||
.param = param,
|
||||
.param = if (params.len > 0) params[0] else 0,
|
||||
.align_expr = align_expr,
|
||||
.section_expr = section_expr,
|
||||
.callconv_expr = callconv_expr,
|
||||
@ -701,8 +695,8 @@ const Parser = struct {
|
||||
.rhs = return_type_expr,
|
||||
},
|
||||
}),
|
||||
.multi => |list| {
|
||||
const span = try p.listToSpan(list);
|
||||
else => {
|
||||
const span = try p.listToSpan(params);
|
||||
return p.setNode(fn_proto_index, .{
|
||||
.tag = .fn_proto,
|
||||
.main_token = fn_token,
|
||||
@ -1894,20 +1888,20 @@ const Parser = struct {
|
||||
});
|
||||
}
|
||||
|
||||
var statements = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer statements.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try statements.appendSlice(&.{ stmt_one, stmt_two });
|
||||
try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two });
|
||||
|
||||
while (true) {
|
||||
const statement = try p.expectStatementRecoverable();
|
||||
if (statement == 0) break;
|
||||
try statements.append(statement);
|
||||
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(statements.items);
|
||||
const statements_span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = if (semicolon) .block_semicolon else .block,
|
||||
.main_token = lbrace,
|
||||
@ -2041,14 +2035,14 @@ const Parser = struct {
|
||||
});
|
||||
}
|
||||
|
||||
var init_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer init_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try init_list.append(field_init);
|
||||
try p.scratch.append(p.gpa, field_init);
|
||||
|
||||
while (true) {
|
||||
const next = try p.expectFieldInit();
|
||||
try init_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
@ -2068,7 +2062,7 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
const span = try p.listToSpan(init_list.items);
|
||||
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,
|
||||
.main_token = lbrace,
|
||||
@ -2098,22 +2092,22 @@ const Parser = struct {
|
||||
try p.warnExpected(.comma);
|
||||
}
|
||||
|
||||
var init_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer init_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try init_list.append(elem_init);
|
||||
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 init_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
if (p.eatToken(.comma) == null) {
|
||||
trailing_comma = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ = try p.expectToken(.r_brace);
|
||||
const span = try p.listToSpan(init_list.items);
|
||||
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,
|
||||
@ -2188,18 +2182,18 @@ const Parser = struct {
|
||||
try p.warnExpected(.comma);
|
||||
}
|
||||
|
||||
var param_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer param_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try param_list.append(param_one);
|
||||
try p.scratch.append(p.gpa, param_one);
|
||||
|
||||
while (true) {
|
||||
const next = try p.expectExpr();
|
||||
try param_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
const span = try p.listToSpan(param_list.items);
|
||||
const span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = .async_call_comma,
|
||||
.main_token = lparen,
|
||||
@ -2216,7 +2210,7 @@ const Parser = struct {
|
||||
}
|
||||
},
|
||||
.r_paren => {
|
||||
const span = try p.listToSpan(param_list.items);
|
||||
const span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = .async_call,
|
||||
.main_token = lparen,
|
||||
@ -2277,18 +2271,18 @@ const Parser = struct {
|
||||
try p.warnExpected(.comma);
|
||||
}
|
||||
|
||||
var param_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer param_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try param_list.append(param_one);
|
||||
try p.scratch.append(p.gpa, param_one);
|
||||
|
||||
while (true) {
|
||||
const next = try p.expectExpr();
|
||||
try param_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
const span = try p.listToSpan(param_list.items);
|
||||
const span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
break :res try p.addNode(.{
|
||||
.tag = .call_comma,
|
||||
.main_token = lparen,
|
||||
@ -2305,7 +2299,7 @@ const Parser = struct {
|
||||
}
|
||||
},
|
||||
.r_paren => {
|
||||
const span = try p.listToSpan(param_list.items);
|
||||
const span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
break :res try p.addNode(.{
|
||||
.tag = .call,
|
||||
.main_token = lparen,
|
||||
@ -2602,15 +2596,15 @@ const Parser = struct {
|
||||
if (comma_two == null) {
|
||||
try p.warnExpected(.comma);
|
||||
}
|
||||
var init_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer init_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try init_list.appendSlice(&.{ field_init_one, field_init_two });
|
||||
try p.scratch.appendSlice(p.gpa, &.{ field_init_one, field_init_two });
|
||||
|
||||
while (true) {
|
||||
const next = try p.expectFieldInit();
|
||||
assert(next != 0);
|
||||
try init_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_brace)) |_| break;
|
||||
@ -2627,7 +2621,7 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
const span = try p.listToSpan(init_list.items);
|
||||
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,
|
||||
@ -2669,15 +2663,15 @@ const Parser = struct {
|
||||
if (comma_two == null) {
|
||||
try p.warnExpected(.comma);
|
||||
}
|
||||
var init_list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer init_list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try init_list.appendSlice(&.{ elem_init_one, elem_init_two });
|
||||
try p.scratch.appendSlice(p.gpa, &.{ elem_init_one, elem_init_two });
|
||||
|
||||
while (true) {
|
||||
const next = try p.expectExpr();
|
||||
if (next == 0) break;
|
||||
try init_list.append(next);
|
||||
try p.scratch.append(p.gpa, next);
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_brace)) |_| break;
|
||||
@ -2694,7 +2688,7 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
const span = try p.listToSpan(init_list.items);
|
||||
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,
|
||||
@ -2924,13 +2918,13 @@ const Parser = struct {
|
||||
|
||||
_ = try p.expectToken(.colon);
|
||||
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
while (true) {
|
||||
const output_item = try p.parseAsmOutputItem();
|
||||
if (output_item == 0) break;
|
||||
try list.append(output_item);
|
||||
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.
|
||||
@ -2945,7 +2939,7 @@ const Parser = struct {
|
||||
while (true) {
|
||||
const input_item = try p.parseAsmInputItem();
|
||||
if (input_item == 0) break;
|
||||
try list.append(input_item);
|
||||
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.
|
||||
@ -2971,7 +2965,7 @@ const Parser = struct {
|
||||
}
|
||||
}
|
||||
const rparen = try p.expectToken(.r_paren);
|
||||
const span = try p.listToSpan(list.items);
|
||||
const span = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = .@"asm",
|
||||
.main_token = asm_token,
|
||||
@ -3192,16 +3186,16 @@ const Parser = struct {
|
||||
});
|
||||
}
|
||||
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try list.append(first_item);
|
||||
try p.scratch.append(p.gpa, first_item);
|
||||
while (p.eatToken(.comma)) |_| {
|
||||
const next_item = try p.parseSwitchItem();
|
||||
if (next_item == 0) break;
|
||||
try list.append(next_item);
|
||||
try p.scratch.append(p.gpa, next_item);
|
||||
}
|
||||
const span = try p.listToSpan(list.items);
|
||||
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(.{
|
||||
@ -3556,10 +3550,13 @@ const Parser = struct {
|
||||
}
|
||||
|
||||
/// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
|
||||
fn parseParamDeclList(p: *Parser) !SmallSpan {
|
||||
fn parseParamDeclList(p: *Parser) ![]Node.Index {
|
||||
const scratch_top = p.scratch.items.len;
|
||||
// don't defer p.scratch.shrinkRetainingCapacity because caller will do it
|
||||
|
||||
_ = try p.expectToken(.l_paren);
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
return SmallSpan{ .zero_or_one = 0 };
|
||||
return p.scratch.items[scratch_top..];
|
||||
}
|
||||
const param_one = while (true) {
|
||||
const param = try p.expectParamDecl();
|
||||
@ -3567,10 +3564,10 @@ const Parser = struct {
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
return SmallSpan{ .zero_or_one = 0 };
|
||||
return p.scratch.items[scratch_top..];
|
||||
}
|
||||
},
|
||||
.r_paren => return SmallSpan{ .zero_or_one = 0 },
|
||||
.r_paren => return p.scratch.items[scratch_top..],
|
||||
else => {
|
||||
// This is likely just a missing comma;
|
||||
// give an error but continue parsing this list.
|
||||
@ -3579,11 +3576,12 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
} else unreachable;
|
||||
try p.scratch.append(p.gpa, param_one);
|
||||
|
||||
const param_two = while (true) {
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {},
|
||||
.r_paren => return SmallSpan{ .zero_or_one = param_one },
|
||||
.r_paren => return p.scratch.items[scratch_top..],
|
||||
.colon, .r_brace, .r_bracket => {
|
||||
p.tok_i -= 1;
|
||||
return p.failExpected(.r_paren);
|
||||
@ -3596,21 +3594,17 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
return SmallSpan{ .zero_or_one = param_one };
|
||||
return p.scratch.items[scratch_top..];
|
||||
}
|
||||
const param = try p.expectParamDecl();
|
||||
if (param != 0) break param;
|
||||
} else unreachable;
|
||||
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
|
||||
try list.appendSlice(&.{ param_one, param_two });
|
||||
try p.scratch.append(p.gpa, param_two);
|
||||
|
||||
while (true) {
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {},
|
||||
.r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },
|
||||
.r_paren => return p.scratch.items[scratch_top..],
|
||||
.colon, .r_brace, .r_bracket => {
|
||||
p.tok_i -= 1;
|
||||
return p.failExpected(.r_paren);
|
||||
@ -3623,10 +3617,10 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
return SmallSpan{ .multi = list.toOwnedSlice() };
|
||||
return p.scratch.items[scratch_top..];
|
||||
}
|
||||
const param = try p.expectParamDecl();
|
||||
if (param != 0) try list.append(param);
|
||||
if (param != 0) try p.scratch.append(p.gpa, param);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3635,14 +3629,14 @@ const Parser = struct {
|
||||
fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) {
|
||||
return struct {
|
||||
pub fn parse(p: *Parser) Error!Node.SubRange {
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
while (true) {
|
||||
const item = try nodeParseFn(p);
|
||||
if (item == 0) break;
|
||||
|
||||
try list.append(item);
|
||||
try p.scratch.append(p.gpa, item);
|
||||
|
||||
switch (p.token_tags[p.tok_i]) {
|
||||
.comma => p.tok_i += 1,
|
||||
@ -3655,7 +3649,7 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
return p.listToSpan(list.items);
|
||||
return p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
}
|
||||
}.parse;
|
||||
}
|
||||
@ -3746,18 +3740,18 @@ const Parser = struct {
|
||||
},
|
||||
}
|
||||
|
||||
var list = std.ArrayList(Node.Index).init(p.gpa);
|
||||
defer list.deinit();
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
|
||||
try list.appendSlice(&.{ param_one, param_two });
|
||||
try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two });
|
||||
|
||||
while (true) {
|
||||
const param = try p.expectExpr();
|
||||
try list.append(param);
|
||||
try p.scratch.append(p.gpa, param);
|
||||
switch (p.token_tags[p.nextToken()]) {
|
||||
.comma => {
|
||||
if (p.eatToken(.r_paren)) |_| {
|
||||
const params = try p.listToSpan(list.items);
|
||||
const params = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = .builtin_call_comma,
|
||||
.main_token = builtin_token,
|
||||
@ -3770,7 +3764,7 @@ const Parser = struct {
|
||||
continue;
|
||||
},
|
||||
.r_paren => {
|
||||
const params = try p.listToSpan(list.items);
|
||||
const params = try p.listToSpan(p.scratch.items[scratch_top..]);
|
||||
return p.addNode(.{
|
||||
.tag = .builtin_call,
|
||||
.main_token = builtin_token,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user