feature. See also
. The project being documented here (as the example) is the Zig library itself.
Parse.parsePrimaryTypeExpr
fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index
File
Code
fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index {
switch (p.tokenTag(p.tok_i)) {
.char_literal => return try p.addNode(.{
.tag = .char_literal,
.main_token = p.nextToken(),
.data = undefined,
}),
.number_literal => return try p.addNode(.{
.tag = .number_literal,
.main_token = p.nextToken(),
.data = undefined,
}),
.keyword_unreachable => return try p.addNode(.{
.tag = .unreachable_literal,
.main_token = p.nextToken(),
.data = undefined,
}),
.keyword_anyframe => return try p.addNode(.{
.tag = .anyframe_literal,
.main_token = p.nextToken(),
.data = undefined,
}),
.string_literal => {
const main_token = p.nextToken();
return try p.addNode(.{
.tag = .string_literal,
.main_token = main_token,
.data = undefined,
});
},
.builtin => return try p.expectBuiltinCall(),
.keyword_fn => return (try p.parseFnProto()).?,
.keyword_if => return try p.expectIf(expectTypeExpr),
.keyword_switch => return try p.expectSwitchExpr(false),
.keyword_extern,
.keyword_packed,
=> {
p.tok_i += 1;
return try p.expectContainerDeclAuto();
},
.keyword_struct,
.keyword_opaque,
.keyword_enum,
.keyword_union,
=> return try p.expectContainerDeclAuto(),
.keyword_comptime => return try p.addNode(.{
.tag = .@"comptime",
.main_token = p.nextToken(),
.data = .{ .node = try p.expectTypeExpr() },
}),
.multiline_string_literal_line => {
const first_line = p.nextToken();
while (p.tokenTag(p.tok_i) == .multiline_string_literal_line) {
p.tok_i += 1;
}
return try p.addNode(.{
.tag = .multiline_string_literal,
.main_token = first_line,
.data = .{ .token_and_token = .{
first_line,
p.tok_i - 1,
} },
});
},
.identifier => switch (p.tokenTag(p.tok_i + 1)) {
.colon => switch (p.tokenTag(p.tok_i + 2)) {
.keyword_inline => {
p.tok_i += 3;
switch (p.tokenTag(p.tok_i)) {
.keyword_for => return try p.expectFor(expectTypeExpr),
.keyword_while => return try p.expectWhileTypeExpr(),
else => return p.fail(.expected_inlinable),
}
},
.keyword_for => {
p.tok_i += 2;
return try p.expectFor(expectTypeExpr);
},
.keyword_while => {
p.tok_i += 2;
return try p.expectWhileTypeExpr();
},
.keyword_switch => {
p.tok_i += 2;
return try p.expectSwitchExpr(true);
},
.l_brace => {
p.tok_i += 2;
return (try p.parseBlock()).?;
},
else => return try p.addNode(.{
.tag = .identifier,
.main_token = p.nextToken(),
.data = undefined,
}),
},
else => return try p.addNode(.{
.tag = .identifier,
.main_token = p.nextToken(),
.data = undefined,
}),
},
.keyword_inline => {
p.tok_i += 1;
switch (p.tokenTag(p.tok_i)) {
.keyword_for => return try p.expectFor(expectTypeExpr),
.keyword_while => return try p.expectWhileTypeExpr(),
else => return p.fail(.expected_inlinable),
}
},
.keyword_for => return try p.expectFor(expectTypeExpr),
.keyword_while => return try p.expectWhileTypeExpr(),
.period => switch (p.tokenTag(p.tok_i + 1)) {
.identifier => {
p.tok_i += 1;
return try p.addNode(.{
.tag = .enum_literal,
.main_token = p.nextToken(),
.data = undefined,
});
},
.l_brace => {
const lbrace = p.tok_i + 1;
p.tok_i = lbrace + 1;
// otherwise we use the full ArrayInitDot/StructInitDot.
const scratch_top = p.scratch.items.len;
defer p.scratch.shrinkRetainingCapacity(scratch_top);
const opt_field_init = try p.parseFieldInit();
if (opt_field_init) |field_init| {
try p.scratch.append(p.gpa, field_init);
while (true) {
switch (p.tokenTag(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),
else => try p.warn(.expected_comma_after_initializer),
}
if (p.eatToken(.r_brace)) |_| break;
const next = try p.expectFieldInit();
try p.scratch.append(p.gpa, next);
}
const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
const inits = p.scratch.items[scratch_top..];
std.debug.assert(inits.len != 0);
if (inits.len <= 2) {
return try p.addNode(.{
.tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
.main_token = lbrace,
.data = .{ .opt_node_and_opt_node = .{
if (inits.len >= 1) .fromOptional(inits[0]) else .none,
if (inits.len >= 2) .fromOptional(inits[1]) else .none,
} },
});
} else {
return try p.addNode(.{
.tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
.main_token = lbrace,
.data = .{ .extra_range = try p.listToSpan(inits) },
});
}
}
while (true) {
if (p.eatToken(.r_brace)) |_| break;
const elem_init = try p.expectExpr();
try p.scratch.append(p.gpa, elem_init);
switch (p.tokenTag(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),
else => try p.warn(.expected_comma_after_initializer),
}
}
const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
const inits = p.scratch.items[scratch_top..];
if (inits.len <= 2) {
return try p.addNode(.{
.tag = if (inits.len == 0)
.struct_init_dot_two
else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
.main_token = lbrace,
.data = .{ .opt_node_and_opt_node = .{
if (inits.len >= 1) inits[0].toOptional() else .none,
if (inits.len >= 2) inits[1].toOptional() else .none,
} },
});
} else {
return try p.addNode(.{
.tag = if (comma) .array_init_dot_comma else .array_init_dot,
.main_token = lbrace,
.data = .{ .extra_range = try p.listToSpan(inits) },
});
}
},
else => return null,
},
.keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
.l_brace => {
const error_token = p.tok_i;
p.tok_i += 2;
while (true) {
if (p.eatToken(.r_brace)) |_| break;
_ = try p.eatDocComments();
_ = try p.expectToken(.identifier);
switch (p.tokenTag(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),
else => try p.warn(.expected_comma_after_field),
}
}
return try p.addNode(.{
.tag = .error_set_decl,
.main_token = error_token,
.data = .{
.token_and_token = .{
error_token + 1,
p.tok_i - 1,
},
},
});
},
else => {
const main_token = p.nextToken();
_ = try p.expectToken(.period);
_ = try p.expectToken(.identifier);
return try p.addNode(.{
.tag = .error_value,
.main_token = main_token,
.data = undefined,
});
},
},
.l_paren => return try p.addNode(.{
.tag = .grouped_expression,
.main_token = p.nextToken(),
.data = .{ .node_and_token = .{
try p.expectExpr(),
try p.expectToken(.r_paren),
} },
}),
else => return null,
}
}