| author | |
| committer | |
| log | 3c46da14db296beec186c3df4fe3669f6c99b715 |
| tree | 8c34fd2046c87da2592b39454e833e0160900af0 |
| parent | bf4e2ab8d16e74374c4769f90e1f4042c0f968a1 |
| parent | 9296ec14e9efe901b397cf8560f75cacf867f170 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/365966 files changed, 162 insertions(+), 94 deletions(-)
doc/langref.html.in+17-36| ... | @@ -7274,46 +7274,27 @@ fn readU32Be() u32 {} | ... | @@ -7274,46 +7274,27 @@ fn readU32Be() u32 {} |
| 7274 | </ul> | 7274 | </ul> |
| 7275 | {#header_close#} | 7275 | {#header_close#} |
| 7276 | {#header_close#} | 7276 | {#header_close#} |
| 7277 | |||
| 7277 | {#header_open|Source Encoding#} | 7278 | {#header_open|Source Encoding#} |
| 7278 | <p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p> | 7279 | <p>Zig source code is UTF-8 encoded. Invalid UTF-8 byte sequences are not allowed anywhere.</p> |
| 7279 | <p>Throughout all zig source code (including in comments), some code points are never allowed:</p> | 7280 | <p>Some code points are never allowed, even in {#link|Comments#}:</p> |
| 7280 | <ul> | 7281 | <ul> |
| 7281 | <li>Ascii control characters, except for U+000a (LF), U+000d (CR), and U+0009 (HT): U+0000 - U+0008, U+000b - U+000c, U+000e - U+0001f, U+007f.</li> | 7282 | <li>ASCII control characters, except for U+000a (LF): U+0000...U+0009, U+000b...U+0001f, U+007f.</li> |
| 7282 | <li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li> | 7283 | <li>Non-ASCII Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li> |
| 7284 | <li>Byte order marks: U+FEFF (BOM).</li> | ||
| 7283 | </ul> | 7285 | </ul> |
| 7284 | <p> | 7286 | <p> |
| 7285 | LF (byte value 0x0a, code point U+000a, {#syntax#}'\n'{#endsyntax#}) is the line terminator in Zig source code. | 7287 | LF (byte value 0x0a, code point U+000a, {#syntax#}'\n'{#endsyntax#}) is |
| 7286 | This byte value terminates every line of zig source code except the last line of the file. | 7288 | the line terminator in Zig source code. This byte value terminates every |
| 7287 | It is recommended that non-empty source files end with an empty line, which means the last byte would be 0x0a (LF). | 7289 | line of Zig source code, including last line of the file. |
| 7288 | </p> | 7290 | </p> |
| 7289 | <p> | 7291 | <p>These conservative rules mean that third party tools reading |
| 7290 | Each LF may be immediately preceded by a single CR (byte value 0x0d, code point U+000d, {#syntax#}'\r'{#endsyntax#}) | 7292 | already-validated Zig source code may make simplifying assumptions, such |
| 7291 | to form a Windows style line ending, but this is discouraged. Note that in multiline strings, CRLF sequences will | 7293 | as naively separating lines based on {#syntax#}'\n'{#endsyntax#}. |
| 7292 | be encoded as LF when compiled into a zig program. | 7294 | However, tooling such as <kbd>zig fmt</kbd> provides convenience |
| 7293 | A CR in any other context is not allowed. | 7295 | functionality to convert invalid source encodings to valid source |
| 7294 | </p> | 7296 | encodings, for instance by stripping byte order marks and carriage |
| 7295 | <p> | 7297 | returns.</p> |
| 7296 | HT hard tabs (byte value 0x09, code point U+0009, {#syntax#}'\t'{#endsyntax#}) are interchangeable with | ||
| 7297 | SP spaces (byte value 0x20, code point U+0020, {#syntax#}' '{#endsyntax#}) as a token separator, | ||
| 7298 | but use of hard tabs is discouraged. See {#link|Grammar#}. | ||
| 7299 | </p> | ||
| 7300 | <p> | ||
| 7301 | For compatibility with other tools, the compiler ignores a UTF-8-encoded byte order mark (U+FEFF) | ||
| 7302 | if it is the first Unicode code point in the source text. A byte order mark is not allowed anywhere else in the source. | ||
| 7303 | </p> | ||
| 7304 | <p> | ||
| 7305 | Note that running <kbd>zig fmt</kbd> on a source file will implement all recommendations mentioned here. | ||
| 7306 | </p> | ||
| 7307 | <p> | ||
| 7308 | Note that a tool reading Zig source code can make assumptions if the source code is assumed to be correct Zig code. | ||
| 7309 | For example, when identifying the ends of lines, a tool can use a naive search such as <code>/\n/</code>, | ||
| 7310 | or an <a href="https://msdn.microsoft.com/en-us/library/dd409797.aspx">advanced</a> | ||
| 7311 | search such as <code>/\r\n?|[\n\u0085\u2028\u2029]/</code>, and in either case line endings will be correctly identified. | ||
| 7312 | For another example, when identifying the whitespace before the first token on a line, | ||
| 7313 | a tool can either use a naive search such as <code>/[ \t]/</code>, | ||
| 7314 | or an <a href="https://tc39.es/ecma262/#sec-characterclassescape">advanced</a> search such as <code>/\s/</code>, | ||
| 7315 | and in either case whitespace will be correctly identified. | ||
| 7316 | </p> | ||
| 7317 | {#header_close#} | 7298 | {#header_close#} |
| 7318 | 7299 | ||
| 7319 | {#header_open|Keyword Reference#} | 7300 | {#header_open|Keyword Reference#} |
lib/compiler/Maker.zig+26-20| ... | @@ -292,9 +292,7 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -292,9 +292,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 292 | try cached_passthru_configure.append(arena, @intCast(configure_argv.items.len)); | 292 | try cached_passthru_configure.append(arena, @intCast(configure_argv.items.len)); |
| 293 | configure_argv.appendAssumeCapacity(arg); | 293 | configure_argv.appendAssumeCapacity(arg); |
| 294 | } else if (mem.eql(u8, arg, "--color")) { | 294 | } else if (mem.eql(u8, arg, "--color")) { |
| 295 | const next_arg = nextArgOrFatal(args, &arg_i); | 295 | color = nextEnumArg(args, &arg_i, Color); |
| 296 | color = stringToEnum(Color, next_arg) orelse | ||
| 297 | fatalWithHint("expected [auto|on|off] found {q}", .{next_arg}); | ||
| 298 | 296 | ||
| 299 | try cached_passthru_configure.append(arena, @intCast(configure_argv.items.len)); | 297 | try cached_passthru_configure.append(arena, @intCast(configure_argv.items.len)); |
| 300 | configure_argv.appendAssumeCapacity(try arena.print("--color={t}", .{color})); | 298 | configure_argv.appendAssumeCapacity(try arena.print("--color={t}", .{color})); |
| ... | @@ -401,25 +399,11 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -401,25 +399,11 @@ pub fn main(init: process.Init.Minimal) !void { |
| 401 | } else if (mem.eql(u8, arg, "--libc")) { | 399 | } else if (mem.eql(u8, arg, "--libc")) { |
| 402 | graph.libc_file = nextArgOrFatal(args, &arg_i); | 400 | graph.libc_file = nextArgOrFatal(args, &arg_i); |
| 403 | } else if (mem.eql(u8, arg, "--error-style")) { | 401 | } else if (mem.eql(u8, arg, "--error-style")) { |
| 404 | const next_arg = nextArg(args, &arg_i) orelse | 402 | error_style = nextEnumArg(args, &arg_i, ErrorStyle); |
| 405 | fatalWithHint("expected style after {q}", .{arg}); | ||
| 406 | error_style = stringToEnum(ErrorStyle, next_arg) orelse { | ||
| 407 | fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg }); | ||
| 408 | }; | ||
| 409 | } else if (mem.eql(u8, arg, "--multiline-errors")) { | 403 | } else if (mem.eql(u8, arg, "--multiline-errors")) { |
| 410 | const next_arg = nextArg(args, &arg_i) orelse | 404 | multiline_errors = nextEnumArg(args, &arg_i, MultilineErrors); |
| 411 | fatalWithHint("expected style after {q}", .{arg}); | ||
| 412 | multiline_errors = stringToEnum(MultilineErrors, next_arg) orelse { | ||
| 413 | fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg }); | ||
| 414 | }; | ||
| 415 | } else if (mem.eql(u8, arg, "--summary")) { | 405 | } else if (mem.eql(u8, arg, "--summary")) { |
| 416 | const next_arg = nextArg(args, &arg_i) orelse | 406 | summary = nextEnumArg(args, &arg_i, Summary); |
| 417 | fatalWithHint("expected [all|new|failures|line|none] after {q}", .{arg}); | ||
| 418 | summary = stringToEnum(Summary, next_arg) orelse { | ||
| 419 | fatalWithHint("expected [all|new|failures|line|none] after {q}, found {q}", .{ | ||
| 420 | arg, next_arg, | ||
| 421 | }); | ||
| 422 | }; | ||
| 423 | } else if (mem.cutPrefix(u8, arg, "--seed=")) |rest| { | 407 | } else if (mem.cutPrefix(u8, arg, "--seed=")) |rest| { |
| 424 | graph.random_seed = parseRandomSeed(rest); | 408 | graph.random_seed = parseRandomSeed(rest); |
| 425 | } else if (mem.eql(u8, arg, "--build-id")) { | 409 | } else if (mem.eql(u8, arg, "--build-id")) { |
| ... | @@ -4053,3 +4037,25 @@ fn confPathDepToCachePath( | ... | @@ -4053,3 +4037,25 @@ fn confPathDepToCachePath( |
| 4053 | .install_include => @panic("TODO"), | 4037 | .install_include => @panic("TODO"), |
| 4054 | }; | 4038 | }; |
| 4055 | } | 4039 | } |
| 4040 | |||
| 4041 | fn fatalEnumHint(comptime E: type, arg: []const u8, param: ?[]const u8) noreturn { | ||
| 4042 | var buf: [100]u8 = undefined; | ||
| 4043 | var w: Io.Writer = .fixed(&buf); | ||
| 4044 | for (@typeInfo(E).@"enum".field_names) |field_name| { | ||
| 4045 | w.writeAll(field_name) catch unreachable; | ||
| 4046 | w.writeByte('|') catch unreachable; | ||
| 4047 | } | ||
| 4048 | const buffered = w.buffered(); | ||
| 4049 | const enum_options_text = buffered[0 .. buffered.len - 1]; | ||
| 4050 | if (param) |p| { | ||
| 4051 | fatalWithHint("expected [{s}] after {q}; found {q}", .{ enum_options_text, arg, p }); | ||
| 4052 | } else { | ||
| 4053 | fatalWithHint("expected [{s}] after {q}", .{ enum_options_text, arg }); | ||
| 4054 | } | ||
| 4055 | } | ||
| 4056 | |||
| 4057 | fn nextEnumArg(args: []const []const u8, i: *usize, comptime E: type) E { | ||
| 4058 | const arg = args[i.* - 1]; | ||
| 4059 | const next_arg = nextArg(args, i) orelse fatalEnumHint(E, arg, null); | ||
| 4060 | return stringToEnum(E, next_arg) orelse fatalEnumHint(E, arg, next_arg); | ||
| 4061 | } |
lib/std/Io/Writer.zig+42-20| ... | @@ -584,36 +584,41 @@ pub fn writeAll(w: *Writer, bytes: []const u8) Error!void { | ... | @@ -584,36 +584,41 @@ pub fn writeAll(w: *Writer, bytes: []const u8) Error!void { |
| 584 | /// required, otherwise the digit following ':' is interpreted as **width**. | 584 | /// required, otherwise the digit following ':' is interpreted as **width**. |
| 585 | /// | 585 | /// |
| 586 | /// **specifier** supports: | 586 | /// **specifier** supports: |
| 587 | /// - `x` and `X`: numeric value in hexadecimal notation, or string in hexadecimal bytes | 587 | /// - "x" and "X": numeric value in hexadecimal notation, or string in hexadecimal bytes |
| 588 | /// - `s`: | 588 | /// - "s": |
| 589 | /// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination | 589 | /// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination |
| 590 | /// - for slices of u8, print the entire slice as a string without zero-termination | 590 | /// - for slices of u8, print the entire slice as a string without zero-termination |
| 591 | /// - `t`: | 591 | /// - "t": |
| 592 | /// - for enums and tagged unions: prints the tag name | 592 | /// - for enums and tagged unions: prints the tag name |
| 593 | /// - for error sets: prints the error name | 593 | /// - for error sets: prints the error name |
| 594 | /// - `b64`: string as standard base64 | 594 | /// - "b64": string as standard base64 |
| 595 | /// - `e`: floating point value in scientific notation | 595 | /// - "e": floating point value in scientific notation |
| 596 | /// - `d`: numeric value in decimal notation | 596 | /// - "d": numeric value in decimal notation |
| 597 | /// - `b`: integer value in binary notation | 597 | /// - "b": integer value in binary notation |
| 598 | /// - `o`: integer value in octal notation | 598 | /// - "o": integer value in octal notation |
| 599 | /// - `c`: integer as an ASCII character. Integer type must have 8 bits at max. | 599 | /// - "c": integer as an ASCII character. Integer type must have 8 bits at max. |
| 600 | /// - `u`: integer as an UTF-8 sequence. Integer type must have 21 bits at max. | 600 | /// - "u": integer as an UTF-8 sequence. Integer type must have 21 bits at max. |
| 601 | /// - `B`: bytes in SI units (decimal) | 601 | /// - "B": bytes in SI units (decimal) |
| 602 | /// - `Bi`: bytes in IEC units (binary) | 602 | /// - "Bi": bytes in IEC units (binary) |
| 603 | /// - `?`: optional value as either the unwrapped value, or `null`; may be | 603 | /// - "?": optional value as either the unwrapped value, or `null`; may be |
| 604 | /// followed by a format specifier for the underlying value. | 604 | /// followed by a format specifier for the underlying value. |
| 605 | /// - `!`: error union value as either the unwrapped value, or the formatted | 605 | /// - "!": error union value as either the unwrapped value, or the formatted |
| 606 | /// error value; may be followed by a format specifier for the underlying | 606 | /// error value; may be followed by a format specifier for the underlying |
| 607 | /// value. | 607 | /// value. |
| 608 | /// - `*`: the address of the value instead of the value itself. | 608 | /// - "*": the address of the value instead of the value itself. |
| 609 | /// - `any`: a value of any type using its default format. | 609 | /// - "any": a value of any type using its default format. |
| 610 | /// - `f`: delegates to the `format` method of the type, passing `*Writer` and | 610 | /// - "f": delegates to the `format` method of the type, passing `*Writer` and |
| 611 | /// expecting `Error!void` returned. | 611 | /// expecting `Error!void` returned. |
| 612 | /// | 612 | /// - "q": prints as a double-quote escaped string. Inside the double-quoted |
| 613 | /// A user type may be a struct, vector, union or enum type. | 613 | /// string, everything is passed through unmodified, except for the following |
| 614 | /// transformations: | ||
| 615 | /// - escaped: '\n', '\r', '\t', '\\', '"' | ||
| 616 | /// - hex-encoded: ASCII control characters | ||
| 617 | /// - "qf": delegates to the `format` method of the type, while double-quote | ||
| 618 | /// escaping. | ||
| 614 | /// | 619 | /// |
| 615 | /// Literal curly braces can be escaped in the format string via doubling, e.g. | 620 | /// Literal curly braces can be escaped in the format string via doubling, e.g. |
| 616 | /// `{{` or `}}`. | 621 | /// "{{" or "}}". |
| 617 | pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void { | 622 | pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void { |
| 618 | const ArgsType = @TypeOf(args); | 623 | const ArgsType = @TypeOf(args); |
| 619 | const args_type_info = @typeInfo(ArgsType); | 624 | const args_type_info = @typeInfo(ArgsType); |
| ... | @@ -1231,6 +1236,18 @@ pub fn printValue( | ... | @@ -1231,6 +1236,18 @@ pub fn printValue( |
| 1231 | }, | 1236 | }, |
| 1232 | else => {}, | 1237 | else => {}, |
| 1233 | }, | 1238 | }, |
| 1239 | 'q' => switch (fmt[1]) { | ||
| 1240 | 'f' => { | ||
| 1241 | try w.writeByte('"'); | ||
| 1242 | var buffer: [64]u8 = undefined; | ||
| 1243 | var escaping_writer: std.zig.StringEscapeWriter = .init(w, &buffer); | ||
| 1244 | try value.format(&escaping_writer.writer); | ||
| 1245 | try escaping_writer.writer.flush(); | ||
| 1246 | try w.writeByte('"'); | ||
| 1247 | return; | ||
| 1248 | }, | ||
| 1249 | else => {}, | ||
| 1250 | }, | ||
| 1234 | else => {}, | 1251 | else => {}, |
| 1235 | }, | 1252 | }, |
| 1236 | 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') switch (@typeInfo(T)) { | 1253 | 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') switch (@typeInfo(T)) { |
| ... | @@ -2143,6 +2160,11 @@ test "{q} format string" { | ... | @@ -2143,6 +2160,11 @@ test "{q} format string" { |
| 2143 | try testing.expectFmt("hello \"i\\tlike\\\"cheese\\x00\\x05cheese\" world", "hello {q} world", .{data}); | 2160 | try testing.expectFmt("hello \"i\\tlike\\\"cheese\\x00\\x05cheese\" world", "hello {q} world", .{data}); |
| 2144 | } | 2161 | } |
| 2145 | 2162 | ||
| 2163 | test "{qf} format string" { | ||
| 2164 | const data: []const u8 = "😎"; | ||
| 2165 | try testing.expectFmt("hello \"@\\\"😎\\\"\" world", "hello {qf} world", .{std.zig.fmtId(data)}); | ||
| 2166 | } | ||
| 2167 | |||
| 2146 | fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void { | 2168 | fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void { |
| 2147 | var buffer: [100]u8 = undefined; | 2169 | var buffer: [100]u8 = undefined; |
| 2148 | var w: Writer = .fixed(&buffer); | 2170 | var w: Writer = .fixed(&buffer); |
lib/std/zig.zig+69-7| ... | @@ -538,21 +538,83 @@ test fmtChar { | ... | @@ -538,21 +538,83 @@ test fmtChar { |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | /// Print the string as escaped contents of a double quoted string. | 540 | /// Print the string as escaped contents of a double quoted string. |
| 541 | /// | ||
| 542 | /// The following transformations are made: | ||
| 543 | /// * escaped: '\n', '\r', '\t', '\\', '"' | ||
| 544 | /// * hex-encoded: ascii control characters | ||
| 545 | /// | ||
| 546 | /// Everything else is passed through unmodified. | ||
| 541 | pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void { | 547 | pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void { |
| 548 | _ = try stringEscapeCounting(bytes, w); | ||
| 549 | } | ||
| 550 | |||
| 551 | pub fn stringEscapeCounting(bytes: []const u8, w: *Writer) Writer.Error!usize { | ||
| 552 | var n: usize = 0; | ||
| 542 | for (bytes) |byte| switch (byte) { | 553 | for (bytes) |byte| switch (byte) { |
| 543 | '\n' => try w.writeAll("\\n"), | 554 | '\t' => { |
| 544 | '\r' => try w.writeAll("\\r"), | 555 | try w.writeAll("\\t"); |
| 545 | '\t' => try w.writeAll("\\t"), | 556 | n += 2; |
| 546 | '\\' => try w.writeAll("\\\\"), | 557 | }, |
| 547 | '"' => try w.writeAll("\\\""), | 558 | '\n' => { |
| 548 | ' ', '!', '#'...'[', ']'...'~' => try w.writeByte(byte), | 559 | try w.writeAll("\\n"); |
| 549 | else => { | 560 | n += 2; |
| 561 | }, | ||
| 562 | '\r' => { | ||
| 563 | try w.writeAll("\\r"); | ||
| 564 | n += 2; | ||
| 565 | }, | ||
| 566 | '\\' => { | ||
| 567 | try w.writeAll("\\\\"); | ||
| 568 | n += 2; | ||
| 569 | }, | ||
| 570 | '"' => { | ||
| 571 | try w.writeAll("\\\""); | ||
| 572 | n += 2; | ||
| 573 | }, | ||
| 574 | 0...8, 11, 12, 14...0x1f, 0x7f => { | ||
| 550 | try w.writeAll("\\x"); | 575 | try w.writeAll("\\x"); |
| 551 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); | 576 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); |
| 577 | n += 4; | ||
| 578 | }, | ||
| 579 | else => { | ||
| 580 | try w.writeByte(byte); | ||
| 581 | n += 1; | ||
| 552 | }, | 582 | }, |
| 553 | }; | 583 | }; |
| 584 | return n; | ||
| 554 | } | 585 | } |
| 555 | 586 | ||
| 587 | pub const StringEscapeWriter = struct { | ||
| 588 | out: *Writer, | ||
| 589 | writer: Writer, | ||
| 590 | |||
| 591 | pub fn init(out: *Writer, buffer: []u8) @This() { | ||
| 592 | return .{ | ||
| 593 | .out = out, | ||
| 594 | .writer = .{ | ||
| 595 | .vtable = &.{ .drain = @This().drain }, | ||
| 596 | .buffer = buffer, | ||
| 597 | }, | ||
| 598 | }; | ||
| 599 | } | ||
| 600 | |||
| 601 | fn drain(w: *Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { | ||
| 602 | const sew: *StringEscapeWriter = @alignCast(@fieldParentPtr("writer", w)); | ||
| 603 | const out = sew.out; | ||
| 604 | _ = try stringEscapeCounting(w.buffered(), out); | ||
| 605 | w.end = 0; | ||
| 606 | var n: usize = 0; | ||
| 607 | for (data[0 .. data.len - 1]) |bytes| { | ||
| 608 | n += try stringEscapeCounting(bytes, out); | ||
| 609 | } | ||
| 610 | const pattern = data[data.len - 1]; | ||
| 611 | for (0..splat) |_| { | ||
| 612 | n += try stringEscapeCounting(pattern, out); | ||
| 613 | } | ||
| 614 | return n; | ||
| 615 | } | ||
| 616 | }; | ||
| 617 | |||
| 556 | /// Print as escaped contents of a single-quoted string. | 618 | /// Print as escaped contents of a single-quoted string. |
| 557 | pub fn charEscape(codepoint: u21, w: *Writer) Writer.Error!void { | 619 | pub fn charEscape(codepoint: u21, w: *Writer) Writer.Error!void { |
| 558 | switch (codepoint) { | 620 | switch (codepoint) { |
lib/std/zig/parser_generated_oracle.zig+5-5| ... | @@ -3073,7 +3073,7 @@ const Parser = struct { | ... | @@ -3073,7 +3073,7 @@ const Parser = struct { |
| 3073 | return blk_0: { | 3073 | return blk_0: { |
| 3074 | const pos_0 = p.i; | 3074 | const pos_0 = p.i; |
| 3075 | if (blk_1: { | 3075 | if (blk_1: { |
| 3076 | if (std.mem.startsWith(u8, p.source[p.i..], "\xef\xbb\xbf")) { | 3076 | if (std.mem.startsWith(u8, p.source[p.i..], "")) { |
| 3077 | p.i += 3; | 3077 | p.i += 3; |
| 3078 | break :blk_1 true; | 3078 | break :blk_1 true; |
| 3079 | } | 3079 | } |
| ... | @@ -3145,7 +3145,7 @@ const Parser = struct { | ... | @@ -3145,7 +3145,7 @@ const Parser = struct { |
| 3145 | return blk_0: { | 3145 | return blk_0: { |
| 3146 | const pos_0 = p.i; | 3146 | const pos_0 = p.i; |
| 3147 | if (blk_1: { | 3147 | if (blk_1: { |
| 3148 | if (std.mem.startsWith(u8, p.source[p.i..], "\xf4")) { | 3148 | if (std.mem.startsWith(u8, p.source[p.i..], "�")) { |
| 3149 | p.i += 1; | 3149 | p.i += 1; |
| 3150 | break :blk_1 true; | 3150 | break :blk_1 true; |
| 3151 | } | 3151 | } |
| ... | @@ -3201,7 +3201,7 @@ const Parser = struct { | ... | @@ -3201,7 +3201,7 @@ const Parser = struct { |
| 3201 | return blk_0: { | 3201 | return blk_0: { |
| 3202 | const pos_0 = p.i; | 3202 | const pos_0 = p.i; |
| 3203 | if (blk_1: { | 3203 | if (blk_1: { |
| 3204 | if (std.mem.startsWith(u8, p.source[p.i..], "\xf0")) { | 3204 | if (std.mem.startsWith(u8, p.source[p.i..], "�")) { |
| 3205 | p.i += 1; | 3205 | p.i += 1; |
| 3206 | break :blk_1 true; | 3206 | break :blk_1 true; |
| 3207 | } | 3207 | } |
| ... | @@ -3257,7 +3257,7 @@ const Parser = struct { | ... | @@ -3257,7 +3257,7 @@ const Parser = struct { |
| 3257 | return blk_0: { | 3257 | return blk_0: { |
| 3258 | const pos_0 = p.i; | 3258 | const pos_0 = p.i; |
| 3259 | if (blk_1: { | 3259 | if (blk_1: { |
| 3260 | if (std.mem.startsWith(u8, p.source[p.i..], "\xed")) { | 3260 | if (std.mem.startsWith(u8, p.source[p.i..], "�")) { |
| 3261 | p.i += 1; | 3261 | p.i += 1; |
| 3262 | break :blk_1 true; | 3262 | break :blk_1 true; |
| 3263 | } | 3263 | } |
| ... | @@ -3313,7 +3313,7 @@ const Parser = struct { | ... | @@ -3313,7 +3313,7 @@ const Parser = struct { |
| 3313 | return blk_0: { | 3313 | return blk_0: { |
| 3314 | const pos_0 = p.i; | 3314 | const pos_0 = p.i; |
| 3315 | if (blk_1: { | 3315 | if (blk_1: { |
| 3316 | if (std.mem.startsWith(u8, p.source[p.i..], "\xe0")) { | 3316 | if (std.mem.startsWith(u8, p.source[p.i..], "�")) { |
| 3317 | p.i += 1; | 3317 | p.i += 1; |
| 3318 | break :blk_1 true; | 3318 | break :blk_1 true; |
| 3319 | } | 3319 | } |
tools/gen_parser_oracle.zig+3-6| ... | @@ -267,17 +267,14 @@ const Generator = struct { | ... | @@ -267,17 +267,14 @@ const Generator = struct { |
| 267 | const bytes = g.p.strings.items[literal.off..][0..literal.len]; | 267 | const bytes = g.p.strings.items[literal.off..][0..literal.len]; |
| 268 | try g.w.print( | 268 | try g.w.print( |
| 269 | \\blk_{d}: {{ | 269 | \\blk_{d}: {{ |
| 270 | \\if (std.mem.startsWith(u8, p.source[p.i..], " | 270 | \\if (std.mem.startsWith(u8, p.source[p.i..], {q})) {{ |
| 271 | , .{suffix}); | 271 | \\ |
| 272 | try std.zig.stringEscape(bytes, g.w); | ||
| 273 | try g.w.print( | ||
| 274 | \\")) {{ | ||
| 275 | \\p.i += {d}; | 272 | \\p.i += {d}; |
| 276 | \\ break :blk_{d} true; | 273 | \\ break :blk_{d} true; |
| 277 | \\}} | 274 | \\}} |
| 278 | \\break :blk_{d} false; | 275 | \\break :blk_{d} false; |
| 279 | \\}} | 276 | \\}} |
| 280 | , .{ bytes.len, suffix, suffix }); | 277 | , .{ suffix, bytes, bytes.len, suffix, suffix }); |
| 281 | }, | 278 | }, |
| 282 | .class => |ranges| { | 279 | .class => |ranges| { |
| 283 | try g.w.writeAll("(p.i < p.source.len and switch (p.source[p.i]) {"); | 280 | try g.w.writeAll("(p.i < p.source.len and switch (p.source[p.i]) {"); |