feature. See also
. The project being documented here (as the example) is the Zig library itself.
Render.renderIdentifier
fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void
File
Code
fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
const tree = r.tree;
assert(tree.tokenTag(token_index) == .identifier);
const lexeme = tokenSliceForRender(tree, token_index);
if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
try r.ais.writeAll(mangled);
try renderSpace(r, token_index, lexeme.len, space);
return;
}
if (lexeme[0] != '@') {
return renderToken(r, token_index, space);
}
assert(lexeme.len >= 3);
assert(lexeme[0] == '@');
assert(lexeme[1] == '\"');
assert(lexeme[lexeme.len - 1] == '\"');
const contents = lexeme[2 .. lexeme.len - 1];
// Empty name can't be unquoted.
if (contents.len == 0) {
return renderQuotedIdentifier(r, token_index, space, false);
}
if (std.zig.isUnderscore(contents)) switch (quote) {
.eagerly_unquote => return renderQuotedIdentifier(r, token_index, space, true),
.eagerly_unquote_except_underscore,
.preserve_when_shadowing,
=> return renderQuotedIdentifier(r, token_index, space, false),
};
// i.e. contents don't match: [A-Za-z_][A-Za-z0-9_]*
var contents_i: usize = 0;
while (contents_i < contents.len) {
switch (contents[contents_i]) {
'0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(r, token_index, space, false),
'A'...'Z', 'a'...'z', '_' => {},
'\\' => {
var esc_offset = contents_i;
const res = std.zig.string_literal.parseEscapeSequence(contents, &esc_offset);
switch (res) {
.success => |char| switch (char) {
'0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(r, token_index, space, false),
'A'...'Z', 'a'...'z', '_' => {},
else => return renderQuotedIdentifier(r, token_index, space, false),
},
.failure => return renderQuotedIdentifier(r, token_index, space, false),
}
contents_i = esc_offset;
continue;
},
else => return renderQuotedIdentifier(r, token_index, space, false),
}
contents_i += 1;
}
// If it's too long to fit in this buffer, we know it's neither and quoting is unnecessary.
// If we read the whole thing, we have to do further checks.
const longest_keyword_or_primitive_len = comptime blk: {
var longest = 0;
for (primitives.names.keys()) |key| {
if (key.len > longest) longest = key.len;
}
for (std.zig.Token.keywords.keys()) |key| {
if (key.len > longest) longest = key.len;
}
break :blk longest;
};
var buf: [longest_keyword_or_primitive_len]u8 = undefined;
contents_i = 0;
var buf_i: usize = 0;
while (contents_i < contents.len and buf_i < longest_keyword_or_primitive_len) {
if (contents[contents_i] == '\\') {
const res = std.zig.string_literal.parseEscapeSequence(contents, &contents_i).success;
buf[buf_i] = @as(u8, @intCast(res));
buf_i += 1;
} else {
buf[buf_i] = contents[contents_i];
contents_i += 1;
buf_i += 1;
}
}
if (contents_i == contents.len) {
if (!std.zig.isValidId(buf[0..buf_i])) {
return renderQuotedIdentifier(r, token_index, space, false);
}
if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) {
.eagerly_unquote,
.eagerly_unquote_except_underscore,
=> return renderQuotedIdentifier(r, token_index, space, true),
.preserve_when_shadowing => return renderQuotedIdentifier(r, token_index, space, false),
};
}
try renderQuotedIdentifier(r, token_index, space, true);
}