feature. See also
. The project being documented here (as the example) is the Zig library itself.
Parse.parseSuffixOp
fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index
File
Code
fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
switch (p.tokenTag(p.tok_i)) {
.l_bracket => {
const lbracket = p.nextToken();
const index_expr = try p.expectExpr();
if (p.eatToken(.ellipsis2)) |_| {
const opt_end_expr = try p.parseExpr();
if (p.eatToken(.colon)) |_| {
const sentinel = try p.expectExpr();
_ = try p.expectToken(.r_bracket);
return try p.addNode(.{
.tag = .slice_sentinel,
.main_token = lbracket,
.data = .{ .node_and_extra = .{
lhs,
try p.addExtra(Node.SliceSentinel{
.start = index_expr,
.end = .fromOptional(opt_end_expr),
.sentinel = sentinel,
}),
} },
});
}
_ = try p.expectToken(.r_bracket);
const end_expr = opt_end_expr orelse {
return try p.addNode(.{
.tag = .slice_open,
.main_token = lbracket,
.data = .{ .node_and_node = .{
lhs,
index_expr,
} },
});
};
return try p.addNode(.{
.tag = .slice,
.main_token = lbracket,
.data = .{ .node_and_extra = .{
lhs,
try p.addExtra(Node.Slice{
.start = index_expr,
.end = end_expr,
}),
} },
});
}
_ = try p.expectToken(.r_bracket);
return try p.addNode(.{
.tag = .array_access,
.main_token = lbracket,
.data = .{ .node_and_node = .{
lhs,
index_expr,
} },
});
},
.period_asterisk => return try p.addNode(.{
.tag = .deref,
.main_token = p.nextToken(),
.data = .{ .node = lhs },
}),
.period => switch (p.tokenTag(p.tok_i + 1)) {
.identifier => return try p.addNode(.{
.tag = .field_access,
.main_token = p.nextToken(),
.data = .{ .node_and_token = .{
lhs,
p.nextToken(),
} },
}),
.question_mark => return try p.addNode(.{
.tag = .unwrap_optional,
.main_token = p.nextToken(),
.data = .{ .node_and_token = .{
lhs,
p.nextToken(),
} },
}),
.l_brace => {
return null;
},
else => {
p.tok_i += 1;
try p.warn(.expected_suffix_op);
return null;
},
},
.l_paren => {
const lparen = p.nextToken();
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.tokenTag(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),
else => try p.warn(.expected_comma_after_arg),
}
}
const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
const params = p.scratch.items[scratch_top..];
switch (params.len) {
0, 1 => return try p.addNode(.{
.tag = if (comma) .call_one_comma else .call_one,
.main_token = lparen,
.data = .{ .node_and_opt_node = .{
lhs,
if (params.len >= 1) .fromOptional(params[0]) else .none,
} },
}),
else => return try p.addNode(.{
.tag = if (comma) .call_comma else .call,
.main_token = lparen,
.data = .{ .node_and_extra = .{
lhs,
try p.addExtra(try p.listToSpan(params)),
} },
}),
}
},
else => return null,
}
}