diff --git a/language.zig b/language.zig index 3e8f82a..d07db40 100644 --- a/language.zig +++ b/language.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const mem = std.mem; const Tokenizer = @import("tokenizer.zig"); const TokenType = Tokenizer.TokenType; const Token = Tokenizer.Token; @@ -6,6 +7,9 @@ const StringPool = @import("strings.zig"); const StringIndex = StringPool.StringIndex; const assert = std.debug.assert; +// data structures +const Object = std.StringArrayHashMapUnmanaged(JsonInput); + const Self = @This(); pub const Error = enum { @@ -38,7 +42,7 @@ pub const JsonInput = union(JsonType) { array: []JsonInput, object: std.StringArrayHashMapUnmanaged(JsonInput), - pub fn deinit(self: JsonInput, allocator: std.mem.Allocator) void { + pub fn deinit(self: JsonInput, allocator: mem.Allocator) void { switch (self) { JsonInput.array => |array| { for (array) |json_input| { @@ -126,26 +130,26 @@ options: Options = .{}, pub const init = Self{}; -pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { +pub fn deinit(self: *Self, allocator: mem.Allocator) void { self.index.deinit(allocator); self.property_index.deinit(allocator); self.string_index.deinit(allocator); } -fn addNumber(self: *Self, allocator: std.mem.Allocator, number: f64) !usize { +fn addNumber(self: *Self, allocator: mem.Allocator, number: f64) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); self.index.set(idx, .{ .number = number }); return idx; } -fn addProperty(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usize { +fn addProperty(self: *Self, allocator: mem.Allocator, bytes: []const u8) !usize { const stridx = try self.property_index.add(allocator, bytes); try self.index.ensureUnusedCapacity(allocator, 1); return @intFromEnum(stridx); } -fn addString(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usize { +fn addString(self: *Self, allocator: mem.Allocator, bytes: []const u8) !usize { const stridx = try self.string_index.add(allocator, bytes); try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); @@ -153,7 +157,7 @@ fn addString(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usiz return idx; } -fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize { +fn addEmptyObject(self: *Self, allocator: mem.Allocator) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); const object: ObjectEntry = .{ @@ -165,7 +169,7 @@ fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize { return idx; } -fn addEmptyArray(self: *Self, allocator: std.mem.Allocator) !usize { +fn addEmptyArray(self: *Self, allocator: mem.Allocator) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); self.index.set(idx, .{ .array = ArraySlice{ @@ -175,14 +179,14 @@ fn addEmptyArray(self: *Self, allocator: std.mem.Allocator) !usize { return idx; } -fn addBool(self: *Self, allocator: std.mem.Allocator, value: bool) !usize { +fn addBool(self: *Self, allocator: mem.Allocator, value: bool) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); self.index.set(idx, .{ .bool = value }); return idx; } -fn addNull(self: *Self, allocator: std.mem.Allocator) !usize { +fn addNull(self: *Self, allocator: mem.Allocator) !usize { try self.index.ensureUnusedCapacity(allocator, 1); const idx = self.index.addOneAssumeCapacity(); self.index.set(idx, .{ .null = {} }); @@ -198,7 +202,7 @@ fn getNumber(self: *Self, index: usize) ?f64 { return null; } -fn getObject(self: *Self, allocator: std.mem.Allocator, index: usize) !struct { +fn getObject(self: *Self, allocator: mem.Allocator, index: usize) !struct { []StringIndex, []usize, } { @@ -225,7 +229,7 @@ fn getObject(self: *Self, allocator: std.mem.Allocator, index: usize) !struct { return .{ keys, values }; } -fn getArray(self: *Self, allocator: std.mem.Allocator, index: usize) ![]usize { +fn getArray(self: *Self, allocator: mem.Allocator, index: usize) ![]usize { const entry = self.index.get(index); if (entry.array.len == 0) { @@ -313,7 +317,7 @@ fn skipNestedProps(self: *Self, pptr: *usize, slot: usize) void { fn getValue( self: *Self, - allocator: std.mem.Allocator, + allocator: mem.Allocator, idx: usize, ) !JsonInput { const entry = self.index.get(idx); @@ -365,7 +369,8 @@ test getValue { const json = \\ { - \\ "array": [1,2,3,[4,5,6]] + \\ "array":[{"cute":true}, + \\ {"funny":false}] \\ } ; @@ -444,6 +449,9 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { .value_idx = 1, } }); } else { + //order + const parent_idx = query.get(query.len - 1); + const idx_ptr = try query.addOne(); idx_ptr.* = try self.addEmptyObject(allocator); self.index.set(idx_ptr.*, .{ @@ -453,6 +461,15 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { .value_idx = self.index.len, }, }); + 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; @@ -463,7 +480,7 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { } }, .object_end, .array_end => { - defer tokenizer.skipWhitespace(); + tokenizer.skipWhitespace(); assert(query.pop() != null); const next = it.next() orelse @@ -588,9 +605,7 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize { } } }, - else => { - // std.debug.print("token: {s}\n", .{@tagName(token.type)}); - }, + else => unreachable, } return root;