diff --git a/language.zig b/language.zig index e6cd23d..3e8f82a 100644 --- a/language.zig +++ b/language.zig @@ -153,38 +153,6 @@ fn addString(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usiz return idx; } -fn addObject(self: *Self, allocator: std.mem.Allocator, object: std.AutoArrayHashMapUnmanaged([]const u8, JsonInput)) !usize { - var entry: ?ObjectEntry = null; - - for (object.keys(), object.values(), 0..) |key, value, times| { - const stridx = try self.property_index.add(allocator, key); - try self.index.ensureUnusedCapacity(allocator, 1); - const vidx = self.index.addOneAssumeCapacity(); - self.index.set(vidx, @unionInit(JsonValue, std.meta.activeTag(value), self.addValue(allocator, value))); - if (times == 0) { - entry = ObjectEntry{ - .len = object.entries.len, - .property_idx = stridx, - .value_idx = vidx, - }; - } - } - - try self.index.ensureUnusedCapacity(allocator, 1); - const idx = self.index.addOneAssumeCapacity(); - if (entry) |e| { - self.index.set(idx, .{ .object = e }); - return idx; - } else { - self.index.set(idx, .{ .object = ObjectEntry{ - .len = 0, - .property_idx = 0, - .value_idx = 1, - } }); - return idx; - } -} - fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); @@ -197,33 +165,6 @@ fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize { return idx; } -fn addArray(self: *Self, allocator: std.mem.Allocator, array: []JsonInput) !usize { - var entry: ?ArraySlice = null; - for (array, 0..) |value, times| { - try self.index.ensureUnusedCapacity(allocator, 1); - const idx = self.index.addOneAssumeCapacity(); - self.index.set(idx, @unionInit(JsonValue, std.meta.activeTag(value), self.addValue(allocator, value))); - if (times == 0) { - entry = ArraySlice{ - .start = idx, - .len = array.len, - }; - } - } - try self.index.ensureUnusedCapacity(allocator, 1); - const idx = self.index.addOneAssumeCapacity(); - if (entry) |e| { - self.index.set(idx, .{ .array = e }); - return idx; - } else { - self.index.set(idx, .{ .array = ArraySlice{ - .start = 0, - .len = 0, - } }); - return idx; - } -} - fn addEmptyArray(self: *Self, allocator: std.mem.Allocator) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); @@ -248,17 +189,6 @@ fn addNull(self: *Self, allocator: std.mem.Allocator) !usize { return idx; } -fn addValue(self: *Self, allocator: std.mem.Allocator, value: JsonInput) !void { - switch (value) { - .null => try self.addNull(allocator), - .bool => try self.addBool(allocator, value.bool), - .number => try self.addNumber(allocator, value.number), - .string => try self.addString(allocator, value.string), - .array => try self.addArray(allocator, value.array), - .object => try self.addObject(allocator, value.object), - } -} - fn getProperty(self: *Self, index: []const u8) ?StringIndex { return self.property_index.string_table.get(index); } @@ -435,18 +365,7 @@ test getValue { const json = \\ { - \\ "name": "Yuzu", - \\ "author": true, - \\ "age": 15, - \\ "address": { - \\ "street": 1, - \\ "deeply_nested": { - \\ "k": 5, - \\ "socialist": "expansion", - \\ "idk": {"a":"b"} - \\ } - \\ }, - \\ "offset": "yes" + \\ "array": [1,2,3,[4,5,6]] \\ } ; @@ -543,7 +462,7 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { else => return error.InvalidSyntax, } }, - .object_end => { + .object_end, .array_end => { defer tokenizer.skipWhitespace(); assert(query.pop() != null); @@ -552,25 +471,66 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { token = next; switch (next.type) { .comma => continue :flag .comma, - .object_end, .array_end => |t| continue :flag t, + .object_end, .array_end => continue :flag next.type, else => return error.InvalidSyntax, } }, + .array_begin => { + defer tokenizer.skipWhitespace(); + + // order matters + const parent_idx = query.get(query.len - 1); + + const idx_ptr = try query.addOne(); + + idx_ptr.* = try self.addEmptyArray(allocator); + self.index.set(idx_ptr.*, .{ .array = ArraySlice{ + .len = 0, + .start = idx_ptr.* + 1, + } }); + + switch (self.index.get(parent_idx)) { + .array => |slice| { + self.index.set(parent_idx, .{ .array = ArraySlice{ + .len = slice.len + 1, + .start = if (slice.len == 0) idx_ptr.* else slice.start, + } }); + }, + else => {}, + } + + const next = it.next() orelse return error.InvalidSyntax; + token = next; + switch (next.type) { + .property => return error.InvalidSyntax, + else => continue :flag next.type, + } + }, .true, .false => { defer tokenizer.skipWhitespace(); - - _ = try self.addBool(allocator, if (token.type == .true) true else false); + const idx = try self.addBool(allocator, if (token.type == .true) true else false); + const parent_idx = query.get(query.len - 1); + switch (self.index.get(parent_idx)) { + .array => |slice| { + self.index.set(parent_idx, .{ .array = ArraySlice{ + .len = slice.len + 1, + .start = if (slice.len == 0) idx else slice.start, + } }); + }, + else => {}, + } const next = it.next() orelse return error.InvalidSyntax; token = next; switch (next.type) { .comma => continue :flag .comma, - .object_end => continue :flag .object_end, + .object_end, .array_end => continue :flag next.type, else => return error.InvalidSyntax, } }, .string => { defer tokenizer.skipWhitespace(); + const parent_idx = query.get(query.len - 1); const next = it.next() orelse return error.InvalidSyntax; switch (next.type) { @@ -578,8 +538,17 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { continue :flag .property; }, else => |t| { - _ = try self.addString(allocator, token.value.?.string); + const idx = try self.addString(allocator, token.value.?.string); allocator.free(token.value.?.string); + switch (self.index.get(parent_idx)) { + .array => |slice| { + self.index.set(parent_idx, .{ .array = ArraySlice{ + .len = slice.len + 1, + .start = if (slice.len == 0) idx else slice.start, + } }); + }, + else => {}, + } token = next; continue :flag t; @@ -589,13 +558,23 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { .number => { defer tokenizer.skipWhitespace(); - _ = try self.addNumber(allocator, token.value.?.number); + const parent_idx = query.get(query.len - 1); + const idx = try self.addNumber(allocator, token.value.?.number); + switch (self.index.get(parent_idx)) { + .array => |slice| { + self.index.set(parent_idx, .{ .array = ArraySlice{ + .len = slice.len + 1, + .start = if (slice.len == 0) idx else slice.start, + } }); + }, + else => {}, + } const next = it.next() orelse return error.InvalidSyntax; token = next; switch (next.type) { .comma => continue :flag .comma, - .object_end => continue :flag .object_end, + .object_end, .array_end => continue :flag next.type, else => return error.InvalidSyntax, } },