| ... | ... | @@ -13,78 +13,38 @@ pub const WriteStream = @import("json/write_stream.zig").WriteStream; |
| 13 | 13 | /// A single token slice into the parent string. |
| 14 | 14 | /// |
| 15 | 15 | /// Use `token.slice()` on the input at the current position to get the current slice. |
| 16 | | pub const Token = struct { |
| 17 | | id: Id, |
| 18 | | |
| 19 | | /// How many bytes do we skip before counting |
| 20 | | offset: u1, |
| 21 | | |
| 22 | | /// Whether string contains an escape sequence and cannot be zero-copied |
| 23 | | string_has_escape: bool, |
| 24 | | |
| 25 | | /// Whether number is simple and can be represented by an integer (i.e. no `.` or `e`) |
| 26 | | number_is_integer: bool, |
| 27 | | |
| 28 | | /// How many bytes from the current position behind the start of this token is. |
| 29 | | count: usize, |
| 30 | | |
| 31 | | pub const Id = enum { |
| 32 | | ObjectBegin, |
| 33 | | ObjectEnd, |
| 34 | | ArrayBegin, |
| 35 | | ArrayEnd, |
| 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 | | } |
| 16 | pub const Token = union(enum) { |
| 17 | ObjectBegin, |
| 18 | ObjectEnd, |
| 19 | ArrayBegin, |
| 20 | ArrayEnd, |
| 21 | String: struct { |
| 22 | /// How many bytes the token is. |
| 23 | count: usize, |
| 24 | |
| 25 | /// Whether string contains an escape sequence and cannot be zero-copied |
| 26 | has_escape: bool, |
| 27 | |
| 28 | /// Slice into the underlying input string. |
| 29 | pub fn slice(self: @This(), input: []const u8, i: usize) []const u8 { |
| 30 | return input[i - self.count .. i]; |
| 31 | } |
| 32 | }, |
| 33 | Number: struct { |
| 34 | /// How many bytes the token is. |
| 35 | count: usize, |
| 52 | 36 | |
| 53 | | pub fn initString(count: usize, has_unicode_escape: bool) Token { |
| 54 | | return Token{ |
| 55 | | .id = Id.String, |
| 56 | | .offset = 0, |
| 57 | | .string_has_escape = has_unicode_escape, |
| 58 | | .number_is_integer = true, |
| 59 | | .count = count, |
| 60 | | }; |
| 61 | | } |
| 37 | /// Whether number is simple and can be represented by an integer (i.e. no `.` or `e`) |
| 38 | is_integer: bool, |
| 62 | 39 | |
| 63 | | pub fn initNumber(count: usize, number_is_integer: bool) Token { |
| 64 | | return Token{ |
| 65 | | .id = Id.Number, |
| 66 | | .offset = 0, |
| 67 | | .string_has_escape = false, |
| 68 | | .number_is_integer = number_is_integer, |
| 69 | | .count = count, |
| 70 | | }; |
| 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 | | } |
| 40 | /// Slice into the underlying input string. |
| 41 | pub fn slice(self: @This(), input: []const u8, i: usize) []const u8 { |
| 42 | return input[i - self.count .. i]; |
| 43 | } |
| 44 | }, |
| 45 | True, |
| 46 | False, |
| 47 | Null, |
| 88 | 48 | }; |
| 89 | 49 | |
| 90 | 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 | 196 | p.state = State.ValueBegin; |
| 237 | 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 | 202 | p.stack <<= 1; |
| ... | ... | @@ -246,7 +206,7 @@ pub const StreamingParser = struct { |
| 246 | 206 | p.state = State.ValueBegin; |
| 247 | 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 | 212 | p.number_is_integer = true; |
| ... | ... | @@ -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 | 300 | if (p.stack & 1 != array_bit) { |
| ... | ... | @@ -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 | 326 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -374,7 +334,7 @@ pub const StreamingParser = struct { |
| 374 | 334 | p.state = State.ValueBegin; |
| 375 | 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 | 340 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -388,7 +348,7 @@ pub const StreamingParser = struct { |
| 388 | 348 | p.state = State.ValueBegin; |
| 389 | 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 | 354 | p.number_is_integer = true; |
| ... | ... | @@ -443,7 +403,7 @@ pub const StreamingParser = struct { |
| 443 | 403 | p.state = State.ValueBegin; |
| 444 | 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 | 409 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -457,7 +417,7 @@ pub const StreamingParser = struct { |
| 457 | 417 | p.state = State.ValueBegin; |
| 458 | 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 | 423 | p.number_is_integer = true; |
| ... | ... | @@ -519,7 +479,7 @@ pub const StreamingParser = struct { |
| 519 | 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 | 485 | if (p.stack_used == 0) { |
| ... | ... | @@ -537,7 +497,7 @@ pub const StreamingParser = struct { |
| 537 | 497 | p.state = State.TopLevelEnd; |
| 538 | 498 | } |
| 539 | 499 | |
| 540 | | token.* = Token.initMarker(Token.Id.ObjectEnd); |
| 500 | token.* = Token.ObjectEnd; |
| 541 | 501 | }, |
| 542 | 502 | 0x09, 0x0A, 0x0D, 0x20 => { |
| 543 | 503 | // whitespace |
| ... | ... | @@ -571,7 +531,12 @@ pub const StreamingParser = struct { |
| 571 | 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 | 542 | p.state = State.StringEscapeCharacter; |
| ... | ... | @@ -686,7 +651,12 @@ pub const StreamingParser = struct { |
| 686 | 651 | }, |
| 687 | 652 | else => { |
| 688 | 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 | 660 | return true; |
| 691 | 661 | }, |
| 692 | 662 | } |
| ... | ... | @@ -708,7 +678,12 @@ pub const StreamingParser = struct { |
| 708 | 678 | }, |
| 709 | 679 | else => { |
| 710 | 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 | 687 | return true; |
| 713 | 688 | }, |
| 714 | 689 | } |
| ... | ... | @@ -738,7 +713,12 @@ pub const StreamingParser = struct { |
| 738 | 713 | }, |
| 739 | 714 | else => { |
| 740 | 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 | 722 | return true; |
| 743 | 723 | }, |
| 744 | 724 | } |
| ... | ... | @@ -753,7 +733,12 @@ pub const StreamingParser = struct { |
| 753 | 733 | }, |
| 754 | 734 | else => { |
| 755 | 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 | 742 | return true; |
| 758 | 743 | }, |
| 759 | 744 | } |
| ... | ... | @@ -791,7 +776,12 @@ pub const StreamingParser = struct { |
| 791 | 776 | }, |
| 792 | 777 | else => { |
| 793 | 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 | 785 | return true; |
| 796 | 786 | }, |
| 797 | 787 | } |
| ... | ... | @@ -811,7 +801,7 @@ pub const StreamingParser = struct { |
| 811 | 801 | 'e' => { |
| 812 | 802 | p.state = p.after_value_state; |
| 813 | 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 | 806 | else => { |
| 817 | 807 | return error.InvalidLiteral; |
| ... | ... | @@ -837,7 +827,7 @@ pub const StreamingParser = struct { |
| 837 | 827 | 'e' => { |
| 838 | 828 | p.state = p.after_value_state; |
| 839 | 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 | 832 | else => { |
| 843 | 833 | return error.InvalidLiteral; |
| ... | ... | @@ -858,7 +848,7 @@ pub const StreamingParser = struct { |
| 858 | 848 | 'l' => { |
| 859 | 849 | p.state = p.after_value_state; |
| 860 | 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 | 853 | else => { |
| 864 | 854 | return error.InvalidLiteral; |
| ... | ... | @@ -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 | 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 | 921 | test "json.token" { |
| ... | ... | @@ -948,35 +938,35 @@ test "json.token" { |
| 948 | 938 | |
| 949 | 939 | var p = TokenStream.init(s); |
| 950 | 940 | |
| 951 | | checkNext(&p, Token.Id.ObjectBegin); |
| 952 | | checkNext(&p, Token.Id.String); // Image |
| 953 | | checkNext(&p, Token.Id.ObjectBegin); |
| 954 | | checkNext(&p, Token.Id.String); // Width |
| 955 | | checkNext(&p, Token.Id.Number); |
| 956 | | checkNext(&p, Token.Id.String); // Height |
| 957 | | checkNext(&p, Token.Id.Number); |
| 958 | | checkNext(&p, Token.Id.String); // Title |
| 959 | | checkNext(&p, Token.Id.String); |
| 960 | | checkNext(&p, Token.Id.String); // Thumbnail |
| 961 | | checkNext(&p, Token.Id.ObjectBegin); |
| 962 | | checkNext(&p, Token.Id.String); // Url |
| 963 | | checkNext(&p, Token.Id.String); |
| 964 | | checkNext(&p, Token.Id.String); // Height |
| 965 | | checkNext(&p, Token.Id.Number); |
| 966 | | checkNext(&p, Token.Id.String); // Width |
| 967 | | checkNext(&p, Token.Id.Number); |
| 968 | | checkNext(&p, Token.Id.ObjectEnd); |
| 969 | | checkNext(&p, Token.Id.String); // Animated |
| 970 | | checkNext(&p, Token.Id.False); |
| 971 | | checkNext(&p, Token.Id.String); // IDs |
| 972 | | checkNext(&p, Token.Id.ArrayBegin); |
| 973 | | checkNext(&p, Token.Id.Number); |
| 974 | | checkNext(&p, Token.Id.Number); |
| 975 | | checkNext(&p, Token.Id.Number); |
| 976 | | checkNext(&p, Token.Id.Number); |
| 977 | | checkNext(&p, Token.Id.ArrayEnd); |
| 978 | | checkNext(&p, Token.Id.ObjectEnd); |
| 979 | | checkNext(&p, Token.Id.ObjectEnd); |
| 941 | checkNext(&p, .ObjectBegin); |
| 942 | checkNext(&p, .String); // Image |
| 943 | checkNext(&p, .ObjectBegin); |
| 944 | checkNext(&p, .String); // Width |
| 945 | checkNext(&p, .Number); |
| 946 | checkNext(&p, .String); // Height |
| 947 | checkNext(&p, .Number); |
| 948 | checkNext(&p, .String); // Title |
| 949 | checkNext(&p, .String); |
| 950 | checkNext(&p, .String); // Thumbnail |
| 951 | checkNext(&p, .ObjectBegin); |
| 952 | checkNext(&p, .String); // Url |
| 953 | checkNext(&p, .String); |
| 954 | checkNext(&p, .String); // Height |
| 955 | checkNext(&p, .Number); |
| 956 | checkNext(&p, .String); // Width |
| 957 | checkNext(&p, .Number); |
| 958 | checkNext(&p, .ObjectEnd); |
| 959 | checkNext(&p, .String); // Animated |
| 960 | checkNext(&p, .False); |
| 961 | checkNext(&p, .String); // IDs |
| 962 | checkNext(&p, .ArrayBegin); |
| 963 | checkNext(&p, .Number); |
| 964 | checkNext(&p, .Number); |
| 965 | checkNext(&p, .Number); |
| 966 | checkNext(&p, .Number); |
| 967 | checkNext(&p, .ArrayEnd); |
| 968 | checkNext(&p, .ObjectEnd); |
| 969 | checkNext(&p, .ObjectEnd); |
| 980 | 970 | |
| 981 | 971 | testing.expect((try p.next()) == null); |
| 982 | 972 | } |
| ... | ... | @@ -1122,8 +1112,8 @@ pub const Parser = struct { |
| 1122 | 1112 | // can be cleaned up on error correctly during a `parse` on call. |
| 1123 | 1113 | fn transition(p: *Parser, allocator: *Allocator, input: []const u8, i: usize, token: Token) !void { |
| 1124 | 1114 | switch (p.state) { |
| 1125 | | State.ObjectKey => switch (token.id) { |
| 1126 | | Token.Id.ObjectEnd => { |
| 1115 | State.ObjectKey => switch (token) { |
| 1116 | .ObjectEnd => { |
| 1127 | 1117 | if (p.stack.len == 1) { |
| 1128 | 1118 | return; |
| 1129 | 1119 | } |
| ... | ... | @@ -1131,8 +1121,8 @@ pub const Parser = struct { |
| 1131 | 1121 | var value = p.stack.pop(); |
| 1132 | 1122 | try p.pushToParent(&value); |
| 1133 | 1123 | }, |
| 1134 | | Token.Id.String => { |
| 1135 | | try p.stack.append(try p.parseString(allocator, token, input, i)); |
| 1124 | .String => |s| { |
| 1125 | try p.stack.append(try p.parseString(allocator, s, input, i)); |
| 1136 | 1126 | p.state = State.ObjectValue; |
| 1137 | 1127 | }, |
| 1138 | 1128 | else => { |
| ... | ... | @@ -1146,41 +1136,41 @@ pub const Parser = struct { |
| 1146 | 1136 | var object = &p.stack.items[p.stack.len - 2].Object; |
| 1147 | 1137 | var key = p.stack.items[p.stack.len - 1].String; |
| 1148 | 1138 | |
| 1149 | | switch (token.id) { |
| 1150 | | Token.Id.ObjectBegin => { |
| 1139 | switch (token) { |
| 1140 | .ObjectBegin => { |
| 1151 | 1141 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1152 | 1142 | p.state = State.ObjectKey; |
| 1153 | 1143 | }, |
| 1154 | | Token.Id.ArrayBegin => { |
| 1144 | .ArrayBegin => { |
| 1155 | 1145 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1156 | 1146 | p.state = State.ArrayValue; |
| 1157 | 1147 | }, |
| 1158 | | Token.Id.String => { |
| 1159 | | _ = try object.put(key, try p.parseString(allocator, token, input, i)); |
| 1148 | .String => |s| { |
| 1149 | _ = try object.put(key, try p.parseString(allocator, s, input, i)); |
| 1160 | 1150 | _ = p.stack.pop(); |
| 1161 | 1151 | p.state = State.ObjectKey; |
| 1162 | 1152 | }, |
| 1163 | | Token.Id.Number => { |
| 1164 | | _ = try object.put(key, try p.parseNumber(token, input, i)); |
| 1153 | .Number => |n| { |
| 1154 | _ = try object.put(key, try p.parseNumber(n, input, i)); |
| 1165 | 1155 | _ = p.stack.pop(); |
| 1166 | 1156 | p.state = State.ObjectKey; |
| 1167 | 1157 | }, |
| 1168 | | Token.Id.True => { |
| 1158 | .True => { |
| 1169 | 1159 | _ = try object.put(key, Value{ .Bool = true }); |
| 1170 | 1160 | _ = p.stack.pop(); |
| 1171 | 1161 | p.state = State.ObjectKey; |
| 1172 | 1162 | }, |
| 1173 | | Token.Id.False => { |
| 1163 | .False => { |
| 1174 | 1164 | _ = try object.put(key, Value{ .Bool = false }); |
| 1175 | 1165 | _ = p.stack.pop(); |
| 1176 | 1166 | p.state = State.ObjectKey; |
| 1177 | 1167 | }, |
| 1178 | | Token.Id.Null => { |
| 1168 | .Null => { |
| 1179 | 1169 | _ = try object.put(key, Value.Null); |
| 1180 | 1170 | _ = p.stack.pop(); |
| 1181 | 1171 | p.state = State.ObjectKey; |
| 1182 | 1172 | }, |
| 1183 | | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { |
| 1173 | .ObjectEnd, .ArrayEnd => { |
| 1184 | 1174 | unreachable; |
| 1185 | 1175 | }, |
| 1186 | 1176 | } |
| ... | ... | @@ -1188,8 +1178,8 @@ pub const Parser = struct { |
| 1188 | 1178 | State.ArrayValue => { |
| 1189 | 1179 | var array = &p.stack.items[p.stack.len - 1].Array; |
| 1190 | 1180 | |
| 1191 | | switch (token.id) { |
| 1192 | | Token.Id.ArrayEnd => { |
| 1181 | switch (token) { |
| 1182 | .ArrayEnd => { |
| 1193 | 1183 | if (p.stack.len == 1) { |
| 1194 | 1184 | return; |
| 1195 | 1185 | } |
| ... | ... | @@ -1197,59 +1187,59 @@ pub const Parser = struct { |
| 1197 | 1187 | var value = p.stack.pop(); |
| 1198 | 1188 | try p.pushToParent(&value); |
| 1199 | 1189 | }, |
| 1200 | | Token.Id.ObjectBegin => { |
| 1190 | .ObjectBegin => { |
| 1201 | 1191 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1202 | 1192 | p.state = State.ObjectKey; |
| 1203 | 1193 | }, |
| 1204 | | Token.Id.ArrayBegin => { |
| 1194 | .ArrayBegin => { |
| 1205 | 1195 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1206 | 1196 | p.state = State.ArrayValue; |
| 1207 | 1197 | }, |
| 1208 | | Token.Id.String => { |
| 1209 | | try array.append(try p.parseString(allocator, token, input, i)); |
| 1198 | .String => |s| { |
| 1199 | try array.append(try p.parseString(allocator, s, input, i)); |
| 1210 | 1200 | }, |
| 1211 | | Token.Id.Number => { |
| 1212 | | try array.append(try p.parseNumber(token, input, i)); |
| 1201 | .Number => |n| { |
| 1202 | try array.append(try p.parseNumber(n, input, i)); |
| 1213 | 1203 | }, |
| 1214 | | Token.Id.True => { |
| 1204 | .True => { |
| 1215 | 1205 | try array.append(Value{ .Bool = true }); |
| 1216 | 1206 | }, |
| 1217 | | Token.Id.False => { |
| 1207 | .False => { |
| 1218 | 1208 | try array.append(Value{ .Bool = false }); |
| 1219 | 1209 | }, |
| 1220 | | Token.Id.Null => { |
| 1210 | .Null => { |
| 1221 | 1211 | try array.append(Value.Null); |
| 1222 | 1212 | }, |
| 1223 | | Token.Id.ObjectEnd => { |
| 1213 | .ObjectEnd => { |
| 1224 | 1214 | unreachable; |
| 1225 | 1215 | }, |
| 1226 | 1216 | } |
| 1227 | 1217 | }, |
| 1228 | | State.Simple => switch (token.id) { |
| 1229 | | Token.Id.ObjectBegin => { |
| 1218 | State.Simple => switch (token) { |
| 1219 | .ObjectBegin => { |
| 1230 | 1220 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| 1231 | 1221 | p.state = State.ObjectKey; |
| 1232 | 1222 | }, |
| 1233 | | Token.Id.ArrayBegin => { |
| 1223 | .ArrayBegin => { |
| 1234 | 1224 | try p.stack.append(Value{ .Array = Array.init(allocator) }); |
| 1235 | 1225 | p.state = State.ArrayValue; |
| 1236 | 1226 | }, |
| 1237 | | Token.Id.String => { |
| 1238 | | try p.stack.append(try p.parseString(allocator, token, input, i)); |
| 1227 | .String => |s| { |
| 1228 | try p.stack.append(try p.parseString(allocator, s, input, i)); |
| 1239 | 1229 | }, |
| 1240 | | Token.Id.Number => { |
| 1241 | | try p.stack.append(try p.parseNumber(token, input, i)); |
| 1230 | .Number => |n| { |
| 1231 | try p.stack.append(try p.parseNumber(n, input, i)); |
| 1242 | 1232 | }, |
| 1243 | | Token.Id.True => { |
| 1233 | .True => { |
| 1244 | 1234 | try p.stack.append(Value{ .Bool = true }); |
| 1245 | 1235 | }, |
| 1246 | | Token.Id.False => { |
| 1236 | .False => { |
| 1247 | 1237 | try p.stack.append(Value{ .Bool = false }); |
| 1248 | 1238 | }, |
| 1249 | | Token.Id.Null => { |
| 1239 | .Null => { |
| 1250 | 1240 | try p.stack.append(Value.Null); |
| 1251 | 1241 | }, |
| 1252 | | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { |
| 1242 | .ObjectEnd, .ArrayEnd => { |
| 1253 | 1243 | unreachable; |
| 1254 | 1244 | }, |
| 1255 | 1245 | }, |
| ... | ... | @@ -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 | 1271 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1282 | 1272 | // characters if flagged with the option. |
| 1283 | | const slice = token.slice(input, i); |
| 1273 | const slice = s.slice(input, i); |
| 1284 | 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 { |
| 1288 | | return if (token.number_is_integer) |
| 1289 | | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } |
| 1277 | fn parseNumber(p: *Parser, n: std.meta.TagPayloadType(Token, Token.Number), input: []const u8, i: usize) !Value { |
| 1278 | return if (n.is_integer) |
| 1279 | Value{ .Integer = try std.fmt.parseInt(i64, n.slice(input, i), 10) } |
| 1290 | 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 | |