support arrays finally done
This commit is contained in:
parent
31107aa9d4
commit
3128f9e768
159
language.zig
159
language.zig
@ -153,38 +153,6 @@ fn addString(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usiz
|
|||||||
return idx;
|
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 {
|
fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize {
|
||||||
try self.index.ensureUnusedCapacity(allocator, 1);
|
try self.index.ensureUnusedCapacity(allocator, 1);
|
||||||
const idx = self.index.addOneAssumeCapacity();
|
const idx = self.index.addOneAssumeCapacity();
|
||||||
@ -197,33 +165,6 @@ fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize {
|
|||||||
return idx;
|
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 {
|
fn addEmptyArray(self: *Self, allocator: std.mem.Allocator) !usize {
|
||||||
try self.index.ensureUnusedCapacity(allocator, 1);
|
try self.index.ensureUnusedCapacity(allocator, 1);
|
||||||
const idx = self.index.addOneAssumeCapacity();
|
const idx = self.index.addOneAssumeCapacity();
|
||||||
@ -248,17 +189,6 @@ fn addNull(self: *Self, allocator: std.mem.Allocator) !usize {
|
|||||||
return idx;
|
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 {
|
fn getProperty(self: *Self, index: []const u8) ?StringIndex {
|
||||||
return self.property_index.string_table.get(index);
|
return self.property_index.string_table.get(index);
|
||||||
}
|
}
|
||||||
@ -435,18 +365,7 @@ test getValue {
|
|||||||
|
|
||||||
const json =
|
const json =
|
||||||
\\ {
|
\\ {
|
||||||
\\ "name": "Yuzu",
|
\\ "array": [1,2,3,[4,5,6]]
|
||||||
\\ "author": true,
|
|
||||||
\\ "age": 15,
|
|
||||||
\\ "address": {
|
|
||||||
\\ "street": 1,
|
|
||||||
\\ "deeply_nested": {
|
|
||||||
\\ "k": 5,
|
|
||||||
\\ "socialist": "expansion",
|
|
||||||
\\ "idk": {"a":"b"}
|
|
||||||
\\ }
|
|
||||||
\\ },
|
|
||||||
\\ "offset": "yes"
|
|
||||||
\\ }
|
\\ }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -543,7 +462,7 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
|
|||||||
else => return error.InvalidSyntax,
|
else => return error.InvalidSyntax,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.object_end => {
|
.object_end, .array_end => {
|
||||||
defer tokenizer.skipWhitespace();
|
defer tokenizer.skipWhitespace();
|
||||||
assert(query.pop() != null);
|
assert(query.pop() != null);
|
||||||
|
|
||||||
@ -552,25 +471,66 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
|
|||||||
token = next;
|
token = next;
|
||||||
switch (next.type) {
|
switch (next.type) {
|
||||||
.comma => continue :flag .comma,
|
.comma => continue :flag .comma,
|
||||||
.object_end, .array_end => |t| continue :flag t,
|
.object_end, .array_end => continue :flag next.type,
|
||||||
else => return error.InvalidSyntax,
|
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 => {
|
.true, .false => {
|
||||||
defer tokenizer.skipWhitespace();
|
defer tokenizer.skipWhitespace();
|
||||||
|
const idx = try self.addBool(allocator, if (token.type == .true) true else false);
|
||||||
_ = 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;
|
const next = it.next() orelse return error.InvalidSyntax;
|
||||||
token = next;
|
token = next;
|
||||||
switch (next.type) {
|
switch (next.type) {
|
||||||
.comma => continue :flag .comma,
|
.comma => continue :flag .comma,
|
||||||
.object_end => continue :flag .object_end,
|
.object_end, .array_end => continue :flag next.type,
|
||||||
else => return error.InvalidSyntax,
|
else => return error.InvalidSyntax,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.string => {
|
.string => {
|
||||||
defer tokenizer.skipWhitespace();
|
defer tokenizer.skipWhitespace();
|
||||||
|
const parent_idx = query.get(query.len - 1);
|
||||||
|
|
||||||
const next = it.next() orelse return error.InvalidSyntax;
|
const next = it.next() orelse return error.InvalidSyntax;
|
||||||
switch (next.type) {
|
switch (next.type) {
|
||||||
@ -578,8 +538,17 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
|
|||||||
continue :flag .property;
|
continue :flag .property;
|
||||||
},
|
},
|
||||||
else => |t| {
|
else => |t| {
|
||||||
_ = try self.addString(allocator, token.value.?.string);
|
const idx = try self.addString(allocator, token.value.?.string);
|
||||||
allocator.free(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;
|
token = next;
|
||||||
continue :flag t;
|
continue :flag t;
|
||||||
@ -589,13 +558,23 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
|
|||||||
.number => {
|
.number => {
|
||||||
defer tokenizer.skipWhitespace();
|
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;
|
const next = it.next() orelse return error.InvalidSyntax;
|
||||||
token = next;
|
token = next;
|
||||||
switch (next.type) {
|
switch (next.type) {
|
||||||
.comma => continue :flag .comma,
|
.comma => continue :flag .comma,
|
||||||
.object_end => continue :flag .object_end,
|
.object_end, .array_end => continue :flag next.type,
|
||||||
else => return error.InvalidSyntax,
|
else => return error.InvalidSyntax,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user