union Token [src]

Fields

target: []const u8
target_must_resolve: []const u8
prereq: []const u8
prereq_must_resolve: []const u8
incomplete_quoted_prerequisite: IndexAndBytes
incomplete_target: IndexAndBytes
invalid_target: IndexAndChar
bad_target_escape: IndexAndChar
expected_dollar_sign: IndexAndChar
continuation_eol: IndexAndChar
incomplete_escape: IndexAndChar
expected_colon: IndexAndChar

Members

Source

pub const Token = union(enum) { target: []const u8, target_must_resolve: []const u8, prereq: []const u8, prereq_must_resolve: []const u8, incomplete_quoted_prerequisite: IndexAndBytes, incomplete_target: IndexAndBytes, invalid_target: IndexAndChar, bad_target_escape: IndexAndChar, expected_dollar_sign: IndexAndChar, continuation_eol: IndexAndChar, incomplete_escape: IndexAndChar, expected_colon: IndexAndChar, pub const IndexAndChar = struct { index: usize, char: u8, }; pub const IndexAndBytes = struct { index: usize, bytes: []const u8, }; /// Resolve escapes in target or prereq. Only valid with .target_must_resolve or .prereq_must_resolve. pub fn resolve(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void { switch (self) { .target_must_resolve => |bytes| { var state: enum { start, escape, dollar } = .start; for (bytes) |c| { switch (state) { .start => { switch (c) { '\\' => state = .escape, '$' => state = .dollar, else => try list.append(gpa, c), } }, .escape => { switch (c) { ' ', '#', '\\' => {}, '$' => { try list.append(gpa, '\\'); state = .dollar; continue; }, else => try list.append(gpa, '\\'), } try list.append(gpa, c); state = .start; }, .dollar => { try list.append(gpa, '$'); switch (c) { '$' => {}, else => try list.append(gpa, c), } state = .start; }, } } }, .prereq_must_resolve => |bytes| { var state: enum { start, escape } = .start; for (bytes) |c| { switch (state) { .start => { switch (c) { '\\' => state = .escape, else => try list.append(gpa, c), } }, .escape => { switch (c) { ' ' => {}, '\\' => { try list.append(gpa, c); continue; }, else => try list.append(gpa, '\\'), } try list.append(gpa, c); state = .start; }, } } }, else => unreachable, } } pub fn printError(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void { switch (self) { .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error .incomplete_quoted_prerequisite, .incomplete_target, => |index_and_bytes| { try list.print(gpa, "{s} '", .{self.errStr()}); if (self == .incomplete_target) { const tmp = Token{ .target_must_resolve = index_and_bytes.bytes }; try tmp.resolve(gpa, list); } else { try printCharValues(gpa, list, index_and_bytes.bytes); } try list.print(gpa, "' at position {d}", .{index_and_bytes.index}); }, .invalid_target, .bad_target_escape, .expected_dollar_sign, .continuation_eol, .incomplete_escape, .expected_colon, => |index_and_char| { try list.appendSlice(gpa, "illegal char "); try printUnderstandableChar(gpa, list, index_and_char.char); try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() }); }, } } fn errStr(self: Token) []const u8 { return switch (self) { .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error .incomplete_quoted_prerequisite => "incomplete quoted prerequisite", .incomplete_target => "incomplete target", .invalid_target => "invalid target", .bad_target_escape => "bad target escape", .expected_dollar_sign => "expecting '$'", .continuation_eol => "continuation expecting end-of-line", .incomplete_escape => "incomplete escape", .expected_colon => "expecting ':'", }; } }