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, writer: anytype) @TypeOf(writer).Error!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 writer.writeByte(c), } }, .escape => { switch (c) { ' ', '#', '\\' => {}, '$' => { try writer.writeByte('\\'); state = .dollar; continue; }, else => try writer.writeByte('\\'), } try writer.writeByte(c); state = .start; }, .dollar => { try writer.writeByte('$'); switch (c) { '$' => {}, else => try writer.writeByte(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 writer.writeByte(c), } }, .escape => { switch (c) { ' ' => {}, '\\' => { try writer.writeByte(c); continue; }, else => try writer.writeByte('\\'), } try writer.writeByte(c); state = .start; }, } } }, else => unreachable, } } pub fn printError(self: Token, writer: anytype) @TypeOf(writer).Error!void { switch (self) { .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error .incomplete_quoted_prerequisite, .incomplete_target, => |index_and_bytes| { try writer.print("{s} '", .{self.errStr()}); if (self == .incomplete_target) { const tmp = Token{ .target_must_resolve = index_and_bytes.bytes }; try tmp.resolve(writer); } else { try printCharValues(writer, index_and_bytes.bytes); } try writer.print("' 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 writer.writeAll("illegal char "); try printUnderstandableChar(writer, index_and_char.char); try writer.print(" 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 ':'", }; } }