feature. See also
. The project being documented here (as the example) is the Zig library itself.
Parse.parseTypeExpr
fn parseTypeExpr(p: *Parse) Error!?Node.Index
File
Code
fn parseTypeExpr(p: *Parse) Error!?Node.Index {
switch (p.tokenTag(p.tok_i)) {
.question_mark => return try p.addNode(.{
.tag = .optional_type,
.main_token = p.nextToken(),
.data = .{ .node = try p.expectTypeExpr() },
}),
.keyword_anyframe => switch (p.tokenTag(p.tok_i + 1)) {
.arrow => return try p.addNode(.{
.tag = .anyframe_type,
.main_token = p.nextToken(),
.data = .{ .token_and_node = .{
p.nextToken(),
try p.expectTypeExpr(),
} },
}),
else => return try p.parseErrorUnionExpr(),
},
.asterisk => {
const asterisk = p.nextToken();
const mods = try p.parsePtrModifiers(.bit_align);
const elem_type = try p.expectTypeExpr();
if (mods.bit_range_start != .none) {
return try p.addNode(.{
.tag = .ptr_type_bit_range,
.main_token = asterisk,
.data = .{ .extra_and_node = .{
try p.addExtra(Node.PtrTypeBitRange{
.sentinel = .none,
.align_node = mods.align_node.unwrap().?,
.addrspace_node = mods.addrspace_node,
.bit_range_start = mods.bit_range_start.unwrap().?,
.bit_range_end = mods.bit_range_end.unwrap().?,
}),
elem_type,
} },
});
} else if (mods.addrspace_node != .none) {
return try p.addNode(.{
.tag = .ptr_type,
.main_token = asterisk,
.data = .{ .extra_and_node = .{
try p.addExtra(Node.PtrType{
.sentinel = .none,
.align_node = mods.align_node,
.addrspace_node = mods.addrspace_node,
}),
elem_type,
} },
});
} else {
return try p.addNode(.{
.tag = .ptr_type_aligned,
.main_token = asterisk,
.data = .{ .opt_node_and_node = .{
mods.align_node,
elem_type,
} },
});
}
},
.l_bracket => switch (p.tokenTag(p.tok_i + 1)) {
.asterisk => {
const l_bracket = p.nextToken();
_ = p.nextToken();
var sentinel: ?Node.Index = null;
if (p.eatToken(.identifier)) |ident| {
const ident_slice = p.source[p.tokenStart(ident)..p.tokenStart(ident + 1)];
if (!std.mem.eql(u8, std.mem.trimEnd(u8, ident_slice, &std.ascii.whitespace), "c")) {
p.tok_i -= 1;
}
} else if (p.eatToken(.colon)) |_| {
sentinel = try p.expectExpr();
}
_ = try p.expectToken(.r_bracket);
const mods = try p.parsePtrModifiers(.byte_align);
const elem_type = try p.expectTypeExpr();
if (sentinel == null and mods.addrspace_node == .none) {
return try p.addNode(.{
.tag = .ptr_type_aligned,
.main_token = l_bracket,
.data = .{ .opt_node_and_node = .{
mods.align_node,
elem_type,
} },
});
} else if (mods.align_node == .none and mods.addrspace_node == .none) {
return try p.addNode(.{
.tag = .ptr_type_sentinel,
.main_token = l_bracket,
.data = .{ .opt_node_and_node = .{
.fromOptional(sentinel),
elem_type,
} },
});
} else {
return try p.addNode(.{
.tag = .ptr_type,
.main_token = l_bracket,
.data = .{ .extra_and_node = .{
try p.addExtra(Node.PtrType{
.sentinel = .fromOptional(sentinel),
.align_node = mods.align_node,
.addrspace_node = mods.addrspace_node,
}),
elem_type,
} },
});
}
},
else => {
const lbracket = p.nextToken();
const len_expr = try p.parseExpr();
const sentinel: ?Node.Index = if (p.eatToken(.colon)) |_|
try p.expectExpr()
else
null;
_ = try p.expectToken(.r_bracket);
if (len_expr == null) {
const mods = try p.parsePtrModifiers(.byte_align);
const elem_type = try p.expectTypeExpr();
if (sentinel == null and mods.addrspace_node == .none) {
return try p.addNode(.{
.tag = .ptr_type_aligned,
.main_token = lbracket,
.data = .{ .opt_node_and_node = .{
mods.align_node,
elem_type,
} },
});
} else if (mods.align_node == .none and mods.addrspace_node == .none) {
return try p.addNode(.{
.tag = .ptr_type_sentinel,
.main_token = lbracket,
.data = .{ .opt_node_and_node = .{
.fromOptional(sentinel),
elem_type,
} },
});
} else {
return try p.addNode(.{
.tag = .ptr_type,
.main_token = lbracket,
.data = .{ .extra_and_node = .{
try p.addExtra(Node.PtrType{
.sentinel = .fromOptional(sentinel),
.align_node = mods.align_node,
.addrspace_node = mods.addrspace_node,
}),
elem_type,
} },
});
}
} else {
switch (p.tokenTag(p.tok_i)) {
.keyword_align,
.keyword_const,
.keyword_volatile,
.keyword_allowzero,
.keyword_addrspace,
=> return p.fail(.ptr_mod_on_array_child_type),
else => {},
}
const elem_type = try p.expectTypeExpr();
if (sentinel == null) {
return try p.addNode(.{
.tag = .array_type,
.main_token = lbracket,
.data = .{ .node_and_node = .{
len_expr.?,
elem_type,
} },
});
} else {
return try p.addNode(.{
.tag = .array_type_sentinel,
.main_token = lbracket,
.data = .{ .node_and_extra = .{
len_expr.?,
try p.addExtra(Node.ArrayTypeSentinel{
.sentinel = sentinel.?,
.elem_type = elem_type,
}),
} },
});
}
}
},
},
else => return p.parseErrorUnionExpr(),
}
}