@@ -13981,6 +13981,39 @@ fn lowerAstErrors(astgen: *AstGen) !void {
13981
13981
var notes: std.ArrayListUnmanaged(u32) = .empty;
13982
13982
defer notes.deinit(gpa);
13983
13983
13984
+ const token_starts = tree.tokens.items(.start);
13985
+ const token_tags = tree.tokens.items(.tag);
13986
+ const parse_err = tree.errors[0];
13987
+ const tok = parse_err.token + @intFromBool(parse_err.token_is_prev);
13988
+ const tok_start = token_starts[tok];
13989
+ const start_char = tree.source[tok_start];
13990
+
13991
+ if (token_tags[tok] == .invalid and
13992
+ (start_char == '\"' or start_char == '\'' or start_char == '/' or mem.startsWith(u8, tree.source[tok_start..], "\\\\")))
13993
+ {
13994
+ const tok_len: u32 = @intCast(tree.tokenSlice(tok).len);
13995
+ const tok_end = tok_start + tok_len;
13996
+ const bad_off = blk: {
13997
+ var idx = tok_start;
13998
+ while (idx < tok_end) : (idx += 1) {
13999
+ switch (tree.source[idx]) {
14000
+ 0x00...0x09, 0x0b...0x1f, 0x7f => break,
14001
+ else => {},
14002
+ }
14003
+ }
14004
+ break :blk idx - tok_start;
14005
+ };
14006
+
14007
+ const err: Ast.Error = .{
14008
+ .tag = Ast.Error.Tag.invalid_byte,
14009
+ .token = tok,
14010
+ .extra = .{ .offset = bad_off },
14011
+ };
14012
+ msg.clearRetainingCapacity();
14013
+ try tree.renderError(err, msg.writer(gpa));
14014
+ return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.items}, notes.items);
14015
+ }
14016
+
13984
14017
var cur_err = tree.errors[0];
13985
14018
for (tree.errors[1..]) |err| {
13986
14019
if (err.is_note) {
0 commit comments