| ... | @@ -13,78 +13,38 @@ pub const WriteStream = @import("json/write_stream.zig").WriteStream; | ... | @@ -13,78 +13,38 @@ pub const WriteStream = @import("json/write_stream.zig").WriteStream; |
| 13 | /// A single token slice into the parent string. | 13 | /// A single token slice into the parent string. |
| 14 | /// | 14 | /// |
| 15 | /// Use `token.slice()` on the input at the current position to get the current slice. | 15 | /// Use `token.slice()` on the input at the current position to get the current slice. |
| 16 | pub const Token = struct { | 16 | pub const Token = union(enum) { |
| 17 | id: Id, | 17 | ObjectBegin, |
| 18 | | 18 | ObjectEnd, |
| 19 | /// How many bytes do we skip before counting | 19 | ArrayBegin, |
| 20 | offset: u1, | 20 | ArrayEnd, |
| 21 | | 21 | String: struct { |
| 22 | /// Whether string contains an escape sequence and cannot be zero-copied | 22 | /// How many bytes the token is. |
| 23 | string_has_escape: bool, | 23 | count: usize, |
| 24 | | 24 | |
| 25 | /// Whether number is simple and can be represented by an integer (i.e. no `.` or `e`) | 25 | /// Whether string contains an escape sequence and cannot be zero-copied |
| 26 | number_is_integer: bool, | 26 | has_escape: bool, |
| 27 | | 27 | |
| 28 | /// How many bytes from the current position behind the start of this token is. | 28 | /// Slice into the underlying input string. |
| 29 | count: usize, | 29 | pub fn slice(self: @This(), input: []const u8, i: usize) []const u8 { |
| 30 | | 30 | return input[i - self.count .. i]; |
| 31 | pub const Id = enum { | 31 | } |
| 32 | ObjectBegin, | 32 | }, |
| 33 | ObjectEnd, | 33 | Number: struct { |
| 34 | ArrayBegin, | 34 | /// How many bytes the token is. |
| 35 | ArrayEnd, | 35 | count: usize, |
| 36 | String, | | |
| 37 | Number, | | |
| 38 | True, | | |
| 39 | False, | | |
| 40 | Null, | | |
| 41 | }; | | |
| 42 | | | |
| 43 | pub fn init(id: Id, count: usize, offset: u1) Token { | | |
| 44 | return Token{ | | |
| 45 | .id = id, | | |
| 46 | .offset = offset, | | |
| 47 | .string_has_escape = false, | | |
| 48 | .number_is_integer = true, | | |
| 49 | .count = count, | | |
| 50 | }; | | |
| 51 | } | | |
| 52 | | 36 | |
| 53 | pub fn initString(count: usize, has_unicode_escape: bool) Token { | 37 | /// Whether number is simple and can be represented by an integer (i.e. no `.` or `e`) |
| 54 | return Token{ | 38 | is_integer: bool, |
| 55 | .id = Id.String, | | |
| 56 | .offset = 0, | | |
| 57 | .string_has_escape = has_unicode_escape, | | |
| 58 | .number_is_integer = true, | | |
| 59 | .count = count, | | |
| 60 | }; | | |
| 61 | } | | |
| 62 | | 39 | |
| 63 | pub fn initNumber(count: usize, number_is_integer: bool) Token { | 40 | /// Slice into the underlying input string. |
| 64 | return Token{ | 41 | pub fn slice(self: @This(), input: []const u8, i: usize) []const u8 { |
| 65 | .id = Id.Number, | 42 | return input[i - self.count .. i]; |
| 66 | .offset = 0, | 43 | } |
| 67 | .string_has_escape = false, | 44 | }, |
| 68 | .number_is_integer = number_is_integer, | 45 | True, |
| 69 | .count = count, | 46 | False, |
| 70 | }; | 47 | Null, |
| 71 | } | | |
| 72 | | | |
| 73 | /// A marker token is a zero-length | | |
| 74 | pub fn initMarker(id: Id) Token { | | |
| 75 | return Token{ | | |
| 76 | .id = id, | | |
| 77 | .offset = 0, | | |
| 78 | .string_has_escape = false, | | |
| 79 | .number_is_integer = true, | | |
| 80 | .count = 0, | | |
| 81 | }; | | |
| 82 | } | | |
| 83 | | | |
| 84 | /// Slice into the underlying input string. | | |
| 85 | pub fn slice(self: Token, input: []const u8, i: usize) []const u8 { | | |
| 86 | return input[i + self.offset - self.count .. i + self.offset]; | | |
| 87 | } | | |
| 88 | }; | 48 | }; |
| 89 | | 49 | |
| 90 | /// A small streaming JSON parser. This accepts input one byte at a time and returns tokens as | 50 | /// A small streaming JSON parser. This accepts input one byte at a time and returns tokens as |
| ... | @@ -236,7 +196,7 @@ pub const StreamingParser = struct { | ... | @@ -236,7 +196,7 @@ pub const StreamingParser = struct { |
| 236 | p.state = State.ValueBegin; | 196 | p.state = State.ValueBegin; |
| 237 | p.after_string_state = State.ObjectSeparator; | 197 | p.after_string_state = State.ObjectSeparator; |
| 238 | | 198 | |
| 239 | token.* = Token.initMarker(Token.Id.ObjectBegin); | 199 | token.* = Token.ObjectBegin; |
| 240 | }, | 200 | }, |
| 241 | '[' => { | 201 | '[' => { |
| 242 | p.stack <<= 1; | 202 | p.stack <<= 1; |
| ... | @@ -246,7 +206,7 @@ pub const StreamingParser = struct { | ... | @@ -246,7 +206,7 @@ pub const StreamingParser = struct { |
| 246 | p.state = State.ValueBegin; | 206 | p.state = State.ValueBegin; |
| 247 | p.after_string_state = State.ValueEnd; | 207 | p.after_string_state = State.ValueEnd; |
| 248 | | 208 | |
| 249 | token.* = Token.initMarker(Token.Id.ArrayBegin); | 209 | token.* = Token.ArrayBegin; |
| 250 | }, | 210 | }, |
| 251 | '-' => { | 211 | '-' => { |
| 252 | p.number_is_integer = true; | 212 | p.number_is_integer = true; |
| ... | @@ -334,7 +294,7 @@ pub const StreamingParser = struct { | ... | @@ -334,7 +294,7 @@ pub const StreamingParser = struct { |
| 334 | }, | 294 | }, |
| 335 | } | 295 | } |
| 336 | | 296 | |
| 337 | token.* = Token.initMarker(Token.Id.ObjectEnd); | 297 | token.* = Token.ObjectEnd; |
| 338 | }, | 298 | }, |
| 339 | ']' => { | 299 | ']' => { |
| 340 | if (p.stack & 1 != array_bit) { | 300 | if (p.stack & 1 != array_bit) { |
| ... | @@ -360,7 +320,7 @@ pub const StreamingParser = struct { | ... | @@ -360,7 +320,7 @@ pub const StreamingParser = struct { |
| 360 | }, | 320 | }, |
| 361 | } | 321 | } |
| 362 | | 322 | |
| 363 | token.* = Token.initMarker(Token.Id.ArrayEnd); | 323 | token.* = Token.ArrayEnd; |
| 364 | }, | 324 | }, |
| 365 | '{' => { | 325 | '{' => { |
| 366 | if (p.stack_used == max_stack_size) { | 326 | if (p.stack_used == max_stack_size) { |
| ... | @@ -374,7 +334,7 @@ pub const StreamingParser = struct { | ... | @@ -374,7 +334,7 @@ pub const StreamingParser = struct { |
| 374 | p.state = State.ValueBegin; | 334 | p.state = State.ValueBegin; |
| 375 | p.after_string_state = State.ObjectSeparator; | 335 | p.after_string_state = State.ObjectSeparator; |
| 376 | | 336 | |
| 377 | token.* = Token.initMarker(Token.Id.ObjectBegin); | 337 | token.* = Token.ObjectBegin; |
| 378 | }, | 338 | }, |
| 379 | '[' => { | 339 | '[' => { |
| 380 | if (p.stack_used == max_stack_size) { | 340 | if (p.stack_used == max_stack_size) { |
| ... | @@ -388,7 +348,7 @@ pub const StreamingParser = struct { | ... | @@ -388,7 +348,7 @@ pub const StreamingParser = struct { |
| 388 | p.state = State.ValueBegin; | 348 | p.state = State.ValueBegin; |
| 389 | p.after_string_state = State.ValueEnd; | 349 | p.after_string_state = State.ValueEnd; |
| 390 | | 350 | |
| 391 | token.* = Token.initMarker(Token.Id.ArrayBegin); | 351 | token.* = Token.ArrayBegin; |
| 392 | }, | 352 | }, |
| 393 | '-' => { | 353 | '-' => { |
| 394 | p.number_is_integer = true; | 354 | p.number_is_integer = true; |
| ... | @@ -443,7 +403,7 @@ pub const StreamingParser = struct { | ... | @@ -443,7 +403,7 @@ pub const StreamingParser = struct { |
| 443 | p.state = State.ValueBegin; | 403 | p.state = State.ValueBegin; |
| 444 | p.after_string_state = State.ObjectSeparator; | 404 | p.after_string_state = State.ObjectSeparator; |
| 445 | | 405 | |
| 446 | token.* = Token.initMarker(Token.Id.ObjectBegin); | 406 | token.* = Token.ObjectBegin; |
| 447 | }, | 407 | }, |
| 448 | '[' => { | 408 | '[' => { |
| 449 | if (p.stack_used == max_stack_size) { | 409 | if (p.stack_used == max_stack_size) { |
| ... | @@ -457,7 +417,7 @@ pub const StreamingParser = struct { | ... | @@ -457,7 +417,7 @@ pub const StreamingParser = struct { |
| 457 | p.state = State.ValueBegin; | 417 | p.state = State.ValueBegin; |
| 458 | p.after_string_state = State.ValueEnd; | 418 | p.after_string_state = State.ValueEnd; |
| 459 | | 419 | |
| 460 | token.* = Token.initMarker(Token.Id.ArrayBegin); | 420 | token.* = Token.ArrayBegin; |
| 461 | }, | 421 | }, |
| 462 | '-' => { | 422 | '-' => { |
| 463 | p.number_is_integer = true; | 423 | p.number_is_integer = true; |
| ... | @@ -519,7 +479,7 @@ pub const StreamingParser = struct { | ... | @@ -519,7 +479,7 @@ pub const StreamingParser = struct { |
| 519 | p.state = State.TopLevelEnd; | 479 | p.state = State.TopLevelEnd; |
| 520 | } | 480 | } |
| 521 | | 481 | |
| 522 | token.* = Token.initMarker(Token.Id.ArrayEnd); | 482 | token.* = Token.ArrayEnd; |
| 523 | }, | 483 | }, |
| 524 | '}' => { | 484 | '}' => { |
| 525 | if (p.stack_used == 0) { | 485 | if (p.stack_used == 0) { |
| ... | @@ -537,7 +497,7 @@ pub const StreamingParser = struct { | ... | @@ -537,7 +497,7 @@ pub const StreamingParser = struct { |
| 537 | p.state = State.TopLevelEnd; | 497 | p.state = State.TopLevelEnd; |
| 538 | } | 498 | } |
| 539 | | 499 | |
| 540 | token.* = Token.initMarker(Token.Id.ObjectEnd); | 500 | token.* = Token.ObjectEnd; |
| 541 | }, | 501 | }, |
| 542 | 0x09, 0x0A, 0x0D, 0x20 => { | 502 | 0x09, 0x0A, 0x0D, 0x20 => { |
| 543 | // whitespace | 503 | // whitespace |
| ... | @@ -571,7 +531,12 @@ pub const StreamingParser = struct { | ... | @@ -571,7 +531,12 @@ pub const StreamingParser = struct { |
| 571 | p.complete = true; | 531 | p.complete = true; |
| 572 | } | 532 | } |
| 573 | | 533 | |
| 574 | token.* = Token.initString(p.count - 1, p.string_has_escape); | 534 | token.* = .{ |
| | 535 | .String = .{ |
| | 536 | .count = p.count - 1, |
| | 537 | .has_escape = p.string_has_escape, |
| | 538 | }, |
| | 539 | }; |
| 575 | }, | 540 | }, |
| 576 | '\\' => { | 541 | '\\' => { |
| 577 | p.state = State.StringEscapeCharacter; | 542 | p.state = State.StringEscapeCharacter; |
| ... | @@ -686,7 +651,12 @@ pub const StreamingParser = struct { | ... | @@ -686,7 +651,12 @@ pub const StreamingParser = struct { |
| 686 | }, | 651 | }, |
| 687 | else => { | 652 | else => { |
| 688 | p.state = p.after_value_state; | 653 | p.state = p.after_value_state; |
| 689 | token.* = Token.initNumber(p.count, p.number_is_integer); | 654 | token.* = .{ |
| | 655 | .Number = .{ |
| | 656 | .count = p.count, |
| | 657 | .is_integer = p.number_is_integer, |
| | 658 | }, |
| | 659 | }; |
| 690 | return true; | 660 | return true; |
| 691 | }, | 661 | }, |
| 692 | } | 662 | } |
| ... | @@ -708,7 +678,12 @@ pub const StreamingParser = struct { | ... | @@ -708,7 +678,12 @@ pub const StreamingParser = struct { |
| 708 | }, | 678 | }, |
| 709 | else => { | 679 | else => { |
| 710 | p.state = p.after_value_state; | 680 | p.state = p.after_value_state; |
| 711 | token.* = Token.initNumber(p.count, p.number_is_integer); | 681 | token.* = .{ |
| | 682 | .Number = .{ |
| | 683 | .count = p.count, |
| | 684 | .is_integer = p.number_is_integer, |
| | 685 | }, |
| | 686 | }; |
| 712 | return true; | 687 | return true; |
| 713 | }, | 688 | }, |
| 714 | } | 689 | } |
| ... | @@ -738,7 +713,12 @@ pub const StreamingParser = struct { | ... | @@ -738,7 +713,12 @@ pub const StreamingParser = struct { |
| 738 | }, | 713 | }, |
| 739 | else => { | 714 | else => { |
| 740 | p.state = p.after_value_state; | 715 | p.state = p.after_value_state; |
| 741 | token.* = Token.initNumber(p.count, p.number_is_integer); | 716 | token.* = .{ |
| | 717 | .Number = .{ |
| | 718 | .count = p.count, |
| | 719 | .is_integer = p.number_is_integer, |
| | 720 | }, |
| | 721 | }; |
| 742 | return true; | 722 | return true; |
| 743 | }, | 723 | }, |
| 744 | } | 724 | } |
| ... | @@ -753,7 +733,12 @@ pub const StreamingParser = struct { | ... | @@ -753,7 +733,12 @@ pub const StreamingParser = struct { |
| 753 | }, | 733 | }, |
| 754 | else => { | 734 | else => { |
| 755 | p.state = p.after_value_state; | 735 | p.state = p.after_value_state; |
| 756 | token.* = Token.initNumber(p.count, p.number_is_integer); | 736 | token.* = .{ |
| | 737 | .Number = .{ |
| | 738 | .count = p.count, |
| | 739 | .is_integer = p.number_is_integer, |
| | 740 | }, |
| | 741 | }; |
| 757 | return true; | 742 | return true; |
| 758 | }, | 743 | }, |
| 759 | } | 744 | } |
| ... | @@ -791,7 +776,12 @@ pub const StreamingParser = struct { | ... | @@ -791,7 +776,12 @@ pub const StreamingParser = struct { |
| 791 | }, | 776 | }, |
| 792 | else => { | 777 | else => { |
| 793 | p.state = p.after_value_state; | 778 | p.state = p.after_value_state; |
| 794 | token.* = Token.initNumber(p.count, p.number_is_integer); | 779 | token.* = .{ |
| | 780 | .Number = .{ |
| | 781 | .count = p.count, |
| | 782 | .is_integer = p.number_is_integer, |
| | 783 | }, |
| | 784 | }; |
| 795 | return true; | 785 | return true; |
| 796 | }, | 786 | }, |
| 797 | } | 787 | } |
| ... | @@ -811,7 +801,7 @@ pub const StreamingParser = struct { | ... | @@ -811,7 +801,7 @@ pub const StreamingParser = struct { |
| 811 | 'e' => { | 801 | 'e' => { |
| 812 | p.state = p.after_value_state; | 802 | p.state = p.after_value_state; |
| 813 | p.complete = p.state == State.TopLevelEnd; | 803 | p.complete = p.state == State.TopLevelEnd; |
| 814 | token.* = Token.init(Token.Id.True, p.count + 1, 1); | 804 | token.* = Token.True; |
| 815 | }, | 805 | }, |
| 816 | else => { | 806 | else => { |
| 817 | return error.InvalidLiteral; | 807 | return error.InvalidLiteral; |
| ... | @@ -837,7 +827,7 @@ pub const StreamingParser = struct { | ... | @@ -837,7 +827,7 @@ pub const StreamingParser = struct { |
| 837 | 'e' => { | 827 | 'e' => { |
| 838 | p.state = p.after_value_state; | 828 | p.state = p.after_value_state; |
| 839 | p.complete = p.state == State.TopLevelEnd; | 829 | p.complete = p.state == State.TopLevelEnd; |
| 840 | token.* = Token.init(Token.Id.False, p.count + 1, 1); | 830 | token.* = Token.False; |
| 841 | }, | 831 | }, |
| 842 | else => { | 832 | else => { |
| 843 | return error.InvalidLiteral; | 833 | return error.InvalidLiteral; |
| ... | @@ -858,7 +848,7 @@ pub const StreamingParser = struct { | ... | @@ -858,7 +848,7 @@ pub const StreamingParser = struct { |
| 858 | 'l' => { | 848 | 'l' => { |
| 859 | p.state = p.after_value_state; | 849 | p.state = p.after_value_state; |
| 860 | p.complete = p.state == State.TopLevelEnd; | 850 | p.complete = p.state == State.TopLevelEnd; |
| 861 | token.* = Token.init(Token.Id.Null, p.count + 1, 1); | 851 | token.* = Token.Null; |
| 862 | }, | 852 | }, |
| 863 | else => { | 853 | else => { |
| 864 | return error.InvalidLiteral; | 854 | return error.InvalidLiteral; |
| ... | @@ -923,9 +913,9 @@ pub const TokenStream = struct { | ... | @@ -923,9 +913,9 @@ pub const TokenStream = struct { |
| 923 | } | 913 | } |
| 924 | }; | 914 | }; |
| 925 | | 915 | |
| 926 | fn checkNext(p: *TokenStream, id: Token.Id) void { | 916 | fn checkNext(p: *TokenStream, id: std.meta.TagType(Token)) void { |
| 927 | const token = (p.next() catch unreachable).?; | 917 | const token = (p.next() catch unreachable).?; |
| 928 | debug.assert(token.id == id); | 918 | debug.assert(std.meta.activeTag(token) == id); |
| 929 | } | 919 | } |
| 930 | | 920 | |
| 931 | test "json.token" { | 921 | test "json.token" { |
| ... | @@ -948,35 +938,35 @@ test "json.token" { | ... | @@ -948,35 +938,35 @@ test "json.token" { |
| 948 | | 938 | |
| 949 | var p = TokenStream.init(s); | 939 | var p = TokenStream.init(s); |
| 950 | | 940 | |
| 951 | checkNext(&p, Token.Id.ObjectBegin); | 941 | checkNext(&p, .ObjectBegin); |
| 952 | checkNext(&p, Token.Id.String); // Image | 942 | checkNext(&p, .String); // Image |
| 953 | checkNext(&p, Token.Id.ObjectBegin); | 943 | checkNext(&p, .ObjectBegin); |
| 954 | checkNext(&p, Token.Id.String); // Width | 944 | checkNext(&p, .String); // Width |
| 955 | checkNext(&p, Token.Id.Number); | 945 | checkNext(&p, .Number); |
| 956 | checkNext(&p, Token.Id.String); // Height | 946 | checkNext(&p, .String); // Height |
| 957 | checkNext(&p, Token.Id.Number); | 947 | checkNext(&p, .Number); |
| 958 | checkNext(&p, Token.Id.String); // Title | 948 | checkNext(&p, .String); // Title |
| 959 | checkNext(&p, Token.Id.String); | 949 | checkNext(&p, .String); |
| 960 | checkNext(&p, Token.Id.String); // Thumbnail | 950 | checkNext(&p, .String); // Thumbnail |
| 961 | checkNext(&p, Token.Id.ObjectBegin); | 951 | checkNext(&p, .ObjectBegin); |
| 962 | checkNext(&p, Token.Id.String); // Url | 952 | checkNext(&p, .String); // Url |
| 963 | checkNext(&p, Token.Id.String); | 953 | checkNext(&p, .String); |
| 964 | checkNext(&p, Token.Id.String); // Height | 954 | checkNext(&p, .String); // Height |
| 965 | checkNext(&p, Token.Id.Number); | 955 | checkNext(&p, .Number); |
| 966 | checkNext(&p, Token.Id.String); // Width | 956 | checkNext(&p, .String); // Width |
| 967 | checkNext(&p, Token.Id.Number); | 957 | checkNext(&p, .Number); |
| 968 | checkNext(&p, Token.Id.ObjectEnd); | 958 | checkNext(&p, .ObjectEnd); |
| 969 | checkNext(&p, Token.Id.String); // Animated | 959 | checkNext(&p, .String); // Animated |
| 970 | checkNext(&p, Token.Id.False); | 960 | checkNext(&p, .False); |
| 971 | checkNext(&p, Token.Id.String); // IDs | 961 | checkNext(&p, .String); // IDs |
| 972 | checkNext(&p, Token.Id.ArrayBegin); | 962 | checkNext(&p, .ArrayBegin); |
| 973 | checkNext(&p, Token.Id.Number); | 963 | checkNext(&p, .Number); |
| 974 | checkNext(&p, Token.Id.Number); | 964 | checkNext(&p, .Number); |
| 975 | checkNext(&p, Token.Id.Number); | 965 | checkNext(&p, .Number); |
| 976 | checkNext(&p, Token.Id.Number); | 966 | checkNext(&p, .Number); |
| 977 | checkNext(&p, Token.Id.ArrayEnd); | 967 | checkNext(&p, .ArrayEnd); |
| 978 | checkNext(&p, Token.Id.ObjectEnd); | 968 | checkNext(&p, .ObjectEnd); |
| 979 | checkNext(&p, Token.Id.ObjectEnd); | 969 | checkNext(&p, .ObjectEnd); |
| 980 | | 970 | |
| 981 | testing.expect((try p.next()) == null); | 971 | testing.expect((try p.next()) == null); |
| 982 | } | 972 | } |
| ... | @@ -1122,8 +1112,8 @@ pub const Parser = struct { | ... | @@ -1122,8 +1112,8 @@ pub const Parser = struct { |
| 1122 | // can be cleaned up on error correctly during a `parse` on call. | 1112 | // can be cleaned up on error correctly during a `parse` on call. |
| 1123 | fn transition(p: *Parser, allocator: *Allocator, input: []const u8, i: usize, token: Token) !void { | 1113 | fn transition(p: *Parser, allocator: *Allocator, input: []const u8, i: usize, token: Token) !void { |
| 1124 | switch (p.state) { | 1114 | switch (p.state) { |
| 1125 | State.ObjectKey => switch (token.id) { | 1115 | State.ObjectKey => switch (token) { |
| 1126 | Token.Id.ObjectEnd => { | 1116 | .ObjectEnd => { |
| 1127 | if (p.stack.len == 1) { | 1117 | if (p.stack.len == 1) { |
| 1128 | return; | 1118 | return; |
| 1129 | } | 1119 | } |
| ... | @@ -1131,8 +1121,8 @@ pub const Parser = struct { | ... | @@ -1131,8 +1121,8 @@ pub const Parser = struct { |
| 1131 | var value = p.stack.pop(); | 1121 | var value = p.stack.pop(); |
| 1132 | try p.pushToParent(&value); | 1122 | try p.pushToParent(&value); |
| 1133 | }, | 1123 | }, |
| 1134 | Token.Id.String => { | 1124 | .String => |s| { |
| 1135 | try p.stack.append(try p.parseString(allocator, token, input, i)); | 1125 | try p.stack.append(try p.parseString(allocator, s, input, i)); |
| 1136 | p.state = State.ObjectValue; | 1126 | p.state = State.ObjectValue; |
| 1137 | }, | 1127 | }, |
| 1138 | else => { | 1128 | else => { |
| ... | @@ -1146,41 +1136,41 @@ pub const Parser = struct { | ... | @@ -1146,41 +1136,41 @@ pub const Parser = struct { |
| 1146 | var object = &p.stack.items[p.stack.len - 2].Object; | 1136 | var object = &p.stack.items[p.stack.len - 2].Object; |
| 1147 | var key = p.stack.items[p.stack.len - 1].String; | 1137 | var key = p.stack.items[p.stack.len - 1].String; |
| 1148 | | 1138 | |
| 1149 | switch (token.id) { | 1139 | switch (token) { |
| 1150 | Token.Id.ObjectBegin => { | 1140 | .ObjectBegin => { |
| 1151 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | 1141 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1152 | p.state = State.ObjectKey; | 1142 | p.state = State.ObjectKey; |
| 1153 | }, | 1143 | }, |
| 1154 | Token.Id.ArrayBegin => { | 1144 | .ArrayBegin => { |
| 1155 | try p.stack.append(Value{ .Array = Array.init(allocator) }); | 1145 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1156 | p.state = State.ArrayValue; | 1146 | p.state = State.ArrayValue; |
| 1157 | }, | 1147 | }, |
| 1158 | Token.Id.String => { | 1148 | .String => |s| { |
| 1159 | _ = try object.put(key, try p.parseString(allocator, token, input, i)); | 1149 | _ = try object.put(key, try p.parseString(allocator, s, input, i)); |
| 1160 | _ = p.stack.pop(); | 1150 | _ = p.stack.pop(); |
| 1161 | p.state = State.ObjectKey; | 1151 | p.state = State.ObjectKey; |
| 1162 | }, | 1152 | }, |
| 1163 | Token.Id.Number => { | 1153 | .Number => |n| { |
| 1164 | _ = try object.put(key, try p.parseNumber(token, input, i)); | 1154 | _ = try object.put(key, try p.parseNumber(n, input, i)); |
| 1165 | _ = p.stack.pop(); | 1155 | _ = p.stack.pop(); |
| 1166 | p.state = State.ObjectKey; | 1156 | p.state = State.ObjectKey; |
| 1167 | }, | 1157 | }, |
| 1168 | Token.Id.True => { | 1158 | .True => { |
| 1169 | _ = try object.put(key, Value{ .Bool = true }); | 1159 | _ = try object.put(key, Value{ .Bool = true }); |
| 1170 | _ = p.stack.pop(); | 1160 | _ = p.stack.pop(); |
| 1171 | p.state = State.ObjectKey; | 1161 | p.state = State.ObjectKey; |
| 1172 | }, | 1162 | }, |
| 1173 | Token.Id.False => { | 1163 | .False => { |
| 1174 | _ = try object.put(key, Value{ .Bool = false }); | 1164 | _ = try object.put(key, Value{ .Bool = false }); |
| 1175 | _ = p.stack.pop(); | 1165 | _ = p.stack.pop(); |
| 1176 | p.state = State.ObjectKey; | 1166 | p.state = State.ObjectKey; |
| 1177 | }, | 1167 | }, |
| 1178 | Token.Id.Null => { | 1168 | .Null => { |
| 1179 | _ = try object.put(key, Value.Null); | 1169 | _ = try object.put(key, Value.Null); |
| 1180 | _ = p.stack.pop(); | 1170 | _ = p.stack.pop(); |
| 1181 | p.state = State.ObjectKey; | 1171 | p.state = State.ObjectKey; |
| 1182 | }, | 1172 | }, |
| 1183 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { | 1173 | .ObjectEnd, .ArrayEnd => { |
| 1184 | unreachable; | 1174 | unreachable; |
| 1185 | }, | 1175 | }, |
| 1186 | } | 1176 | } |
| ... | @@ -1188,8 +1178,8 @@ pub const Parser = struct { | ... | @@ -1188,8 +1178,8 @@ pub const Parser = struct { |
| 1188 | State.ArrayValue => { | 1178 | State.ArrayValue => { |
| 1189 | var array = &p.stack.items[p.stack.len - 1].Array; | 1179 | var array = &p.stack.items[p.stack.len - 1].Array; |
| 1190 | | 1180 | |
| 1191 | switch (token.id) { | 1181 | switch (token) { |
| 1192 | Token.Id.ArrayEnd => { | 1182 | .ArrayEnd => { |
| 1193 | if (p.stack.len == 1) { | 1183 | if (p.stack.len == 1) { |
| 1194 | return; | 1184 | return; |
| 1195 | } | 1185 | } |
| ... | @@ -1197,59 +1187,59 @@ pub const Parser = struct { | ... | @@ -1197,59 +1187,59 @@ pub const Parser = struct { |
| 1197 | var value = p.stack.pop(); | 1187 | var value = p.stack.pop(); |
| 1198 | try p.pushToParent(&value); | 1188 | try p.pushToParent(&value); |
| 1199 | }, | 1189 | }, |
| 1200 | Token.Id.ObjectBegin => { | 1190 | .ObjectBegin => { |
| 1201 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | 1191 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1202 | p.state = State.ObjectKey; | 1192 | p.state = State.ObjectKey; |
| 1203 | }, | 1193 | }, |
| 1204 | Token.Id.ArrayBegin => { | 1194 | .ArrayBegin => { |
| 1205 | try p.stack.append(Value{ .Array = Array.init(allocator) }); | 1195 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1206 | p.state = State.ArrayValue; | 1196 | p.state = State.ArrayValue; |
| 1207 | }, | 1197 | }, |
| 1208 | Token.Id.String => { | 1198 | .String => |s| { |
| 1209 | try array.append(try p.parseString(allocator, token, input, i)); | 1199 | try array.append(try p.parseString(allocator, s, input, i)); |
| 1210 | }, | 1200 | }, |
| 1211 | Token.Id.Number => { | 1201 | .Number => |n| { |
| 1212 | try array.append(try p.parseNumber(token, input, i)); | 1202 | try array.append(try p.parseNumber(n, input, i)); |
| 1213 | }, | 1203 | }, |
| 1214 | Token.Id.True => { | 1204 | .True => { |
| 1215 | try array.append(Value{ .Bool = true }); | 1205 | try array.append(Value{ .Bool = true }); |
| 1216 | }, | 1206 | }, |
| 1217 | Token.Id.False => { | 1207 | .False => { |
| 1218 | try array.append(Value{ .Bool = false }); | 1208 | try array.append(Value{ .Bool = false }); |
| 1219 | }, | 1209 | }, |
| 1220 | Token.Id.Null => { | 1210 | .Null => { |
| 1221 | try array.append(Value.Null); | 1211 | try array.append(Value.Null); |
| 1222 | }, | 1212 | }, |
| 1223 | Token.Id.ObjectEnd => { | 1213 | .ObjectEnd => { |
| 1224 | unreachable; | 1214 | unreachable; |
| 1225 | }, | 1215 | }, |
| 1226 | } | 1216 | } |
| 1227 | }, | 1217 | }, |
| 1228 | State.Simple => switch (token.id) { | 1218 | State.Simple => switch (token) { |
| 1229 | Token.Id.ObjectBegin => { | 1219 | .ObjectBegin => { |
| 1230 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | 1220 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1231 | p.state = State.ObjectKey; | 1221 | p.state = State.ObjectKey; |
| 1232 | }, | 1222 | }, |
| 1233 | Token.Id.ArrayBegin => { | 1223 | .ArrayBegin => { |
| 1234 | try p.stack.append(Value{ .Array = Array.init(allocator) }); | 1224 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1235 | p.state = State.ArrayValue; | 1225 | p.state = State.ArrayValue; |
| 1236 | }, | 1226 | }, |
| 1237 | Token.Id.String => { | 1227 | .String => |s| { |
| 1238 | try p.stack.append(try p.parseString(allocator, token, input, i)); | 1228 | try p.stack.append(try p.parseString(allocator, s, input, i)); |
| 1239 | }, | 1229 | }, |
| 1240 | Token.Id.Number => { | 1230 | .Number => |n| { |
| 1241 | try p.stack.append(try p.parseNumber(token, input, i)); | 1231 | try p.stack.append(try p.parseNumber(n, input, i)); |
| 1242 | }, | 1232 | }, |
| 1243 | Token.Id.True => { | 1233 | .True => { |
| 1244 | try p.stack.append(Value{ .Bool = true }); | 1234 | try p.stack.append(Value{ .Bool = true }); |
| 1245 | }, | 1235 | }, |
| 1246 | Token.Id.False => { | 1236 | .False => { |
| 1247 | try p.stack.append(Value{ .Bool = false }); | 1237 | try p.stack.append(Value{ .Bool = false }); |
| 1248 | }, | 1238 | }, |
| 1249 | Token.Id.Null => { | 1239 | .Null => { |
| 1250 | try p.stack.append(Value.Null); | 1240 | try p.stack.append(Value.Null); |
| 1251 | }, | 1241 | }, |
| 1252 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { | 1242 | .ObjectEnd, .ArrayEnd => { |
| 1253 | unreachable; | 1243 | unreachable; |
| 1254 | }, | 1244 | }, |
| 1255 | }, | 1245 | }, |
| ... | @@ -1277,18 +1267,18 @@ pub const Parser = struct { | ... | @@ -1277,18 +1267,18 @@ pub const Parser = struct { |
| 1277 | } | 1267 | } |
| 1278 | } | 1268 | } |
| 1279 | | 1269 | |
| 1280 | fn parseString(p: *Parser, allocator: *Allocator, token: Token, input: []const u8, i: usize) !Value { | 1270 | fn parseString(p: *Parser, allocator: *Allocator, s: std.meta.TagPayloadType(Token, Token.String), input: []const u8, i: usize) !Value { |
| 1281 | // TODO: We don't strictly have to copy values which do not contain any escape | 1271 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1282 | // characters if flagged with the option. | 1272 | // characters if flagged with the option. |
| 1283 | const slice = token.slice(input, i); | 1273 | const slice = s.slice(input, i); |
| 1284 | return Value{ .String = try unescapeStringAlloc(allocator, slice) }; | 1274 | return Value{ .String = try unescapeStringAlloc(allocator, slice) }; |
| 1285 | } | 1275 | } |
| 1286 | | 1276 | |
| 1287 | fn parseNumber(p: *Parser, token: Token, input: []const u8, i: usize) !Value { | 1277 | fn parseNumber(p: *Parser, n: std.meta.TagPayloadType(Token, Token.Number), input: []const u8, i: usize) !Value { |
| 1288 | return if (token.number_is_integer) | 1278 | return if (n.is_integer) |
| 1289 | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } | 1279 | Value{ .Integer = try std.fmt.parseInt(i64, n.slice(input, i), 10) } |
| 1290 | else | 1280 | else |
| 1291 | Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) }; | 1281 | Value{ .Float = try std.fmt.parseFloat(f64, n.slice(input, i)) }; |
| 1292 | } | 1282 | } |
| 1293 | }; | 1283 | }; |
| 1294 | | 1284 | |