authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-12-30 23:09:43+11:00
committergravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-12-30 23:47:29+11:00
log80d37a13c0e2be9aff63745e03ac4fab8f55aa98
treeb083d757da224febc9a166ac6a6ccb7622451286
parent51943ff432f3e73c2dc21015fae4bdcd8f81ae61
signature Commit is signed but in an unrecognized format.

std: use a union(enum) for std.json.Token


1 files changed, 154 insertions(+), 164 deletions(-)

lib/std/json.zig+154-164
...@@ -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.
16pub const Token = struct {16pub const Token = union(enum) {
17 id: Id,17 ObjectBegin,
1818 ObjectEnd,
19 /// How many bytes do we skip before counting19 ArrayBegin,
20 offset: u1,20 ArrayEnd,
2121 String: struct {
22 /// Whether string contains an escape sequence and cannot be zero-copied22 /// How many bytes the token is.
23 string_has_escape: bool,23 count: usize,
2424
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,
2727
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 {
3030 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 }
5236
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 }
6239
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};
8949
90/// A small streaming JSON parser. This accepts input one byte at a time and returns tokens as50/// 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;
238198
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;
248208
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 }
336296
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 }
362322
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;
376336
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;
390350
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;
445405
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;
459419
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 }
521481
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 }
539499
540 token.* = Token.initMarker(Token.Id.ObjectEnd);500 token.* = Token.ObjectEnd;
541 },501 },
542 0x09, 0x0A, 0x0D, 0x20 => {502 0x09, 0x0A, 0x0D, 0x20 => {
543 // whitespace503 // 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 }
573533
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};
925915
926fn checkNext(p: *TokenStream, id: Token.Id) void {916fn 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}
930920
931test "json.token" {921test "json.token" {
...@@ -948,35 +938,35 @@ test "json.token" {...@@ -948,35 +938,35 @@ test "json.token" {
948938
949 var p = TokenStream.init(s);939 var p = TokenStream.init(s);
950940
951 checkNext(&p, Token.Id.ObjectBegin);941 checkNext(&p, .ObjectBegin);
952 checkNext(&p, Token.Id.String); // Image942 checkNext(&p, .String); // Image
953 checkNext(&p, Token.Id.ObjectBegin);943 checkNext(&p, .ObjectBegin);
954 checkNext(&p, Token.Id.String); // Width944 checkNext(&p, .String); // Width
955 checkNext(&p, Token.Id.Number);945 checkNext(&p, .Number);
956 checkNext(&p, Token.Id.String); // Height946 checkNext(&p, .String); // Height
957 checkNext(&p, Token.Id.Number);947 checkNext(&p, .Number);
958 checkNext(&p, Token.Id.String); // Title948 checkNext(&p, .String); // Title
959 checkNext(&p, Token.Id.String);949 checkNext(&p, .String);
960 checkNext(&p, Token.Id.String); // Thumbnail950 checkNext(&p, .String); // Thumbnail
961 checkNext(&p, Token.Id.ObjectBegin);951 checkNext(&p, .ObjectBegin);
962 checkNext(&p, Token.Id.String); // Url952 checkNext(&p, .String); // Url
963 checkNext(&p, Token.Id.String);953 checkNext(&p, .String);
964 checkNext(&p, Token.Id.String); // Height954 checkNext(&p, .String); // Height
965 checkNext(&p, Token.Id.Number);955 checkNext(&p, .Number);
966 checkNext(&p, Token.Id.String); // Width956 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); // Animated959 checkNext(&p, .String); // Animated
970 checkNext(&p, Token.Id.False);960 checkNext(&p, .False);
971 checkNext(&p, Token.Id.String); // IDs961 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);
980970
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;
11481138
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;
11901180
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 }
12791269
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 escape1271 // 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 }
12861276
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 else1280 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};
12941284