From 22a5d1617e79f176ecfca22d6c72be215f0da8b6 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 17 Jan 2026 18:40:47 +0900 Subject: implement object key access --- src/jq/compile.zig | 3 +++ src/jq/execute.zig | 13 +++++++++++++ src/jq/parse.zig | 15 +++++++++++++++ src/root.zig | 12 ++++++++++++ 4 files changed, 43 insertions(+) (limited to 'src') diff --git a/src/jq/compile.zig b/src/jq/compile.zig index ddb4be5..0c30a3d 100644 --- a/src/jq/compile.zig +++ b/src/jq/compile.zig @@ -5,12 +5,14 @@ const Ast = @import("./parse.zig").Ast; pub const Opcode = enum { nop, array_index, + object_key, literal, }; pub const Instr = union(Opcode) { nop, array_index, + object_key: []const u8, literal: *jv.Value, pub fn op(self: @This()) Opcode { @@ -29,6 +31,7 @@ pub fn compile(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocato try instrs.appendSlice(allocator, index_instrs); try instrs.append(allocator, .array_index); }, + .object_key => |key| try instrs.append(allocator, .{ .object_key = key }), .literal => |value| try instrs.append(allocator, .{ .literal = value }), } diff --git a/src/jq/execute.zig b/src/jq/execute.zig index a07204a..8e9bbb0 100644 --- a/src/jq/execute.zig +++ b/src/jq/execute.zig @@ -66,6 +66,14 @@ const ValueStack = struct { else => error.InvalidType, }; } + + pub fn popObject(self: *Self) ExecuteError!jv.Object { + const value = try self.pop(); + return switch (value) { + .object => |o| o, + else => error.InvalidType, + }; + } }; pub fn execute(allocator: std.mem.Allocator, instrs: []const Instr, input: jv.Value) !jv.Value { @@ -86,6 +94,11 @@ pub fn execute(allocator: std.mem.Allocator, instrs: []const Instr, input: jv.Va const result = if (index < array.items.len) array.items[index] else .null; try value_stack.push(result); }, + .object_key => |key| { + const obj = try value_stack.popObject(); + const result = obj.get(key) orelse .null; + try value_stack.push(result); + }, .literal => |value| { try value_stack.push(value.*); }, diff --git a/src/jq/parse.zig b/src/jq/parse.zig index 5269ef5..dc9f6b9 100644 --- a/src/jq/parse.zig +++ b/src/jq/parse.zig @@ -10,12 +10,14 @@ pub const ParseError = error{ pub const AstKind = enum { identity, array_index, + object_key, literal, }; pub const Ast = union(AstKind) { identity, array_index: *Ast, + object_key: []const u8, literal: *jv.Value, pub fn kind(self: @This()) AstKind { @@ -42,6 +44,19 @@ pub fn parse(allocator: std.mem.Allocator, tokens: []const Token) !*Ast { return root; } + if (t2.kind() == .identifier) { + i += 1; + const t3 = tokens[i]; + if (t3.kind() != .end) { + return error.InvalidQuery; + } + const root = try allocator.create(Ast); + root.* = .{ + .object_key = t2.identifier, + }; + return root; + } + if (t2.kind() != .bracket_left) { return error.InvalidQuery; } diff --git a/src/root.zig b/src/root.zig index fa48c7b..f75f062 100644 --- a/src/root.zig +++ b/src/root.zig @@ -58,3 +58,15 @@ test "array index filter" { \\ 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100] , ".[100]"); } + +test "object key filter" { + var debug_allocator = std.heap.DebugAllocator(.{}).init; + defer std.debug.assert(debug_allocator.deinit() == .ok); + const allocator = debug_allocator.allocator(); + + try testRun("123", allocator, "{\"a\":123}", ".a"); + try testRun("null", allocator, "{\"a\":123}", ".b"); + try testRun("\"hello\"", allocator, "{\"foo\":\"hello\"}", ".foo"); + try testRun("[1,2,3]", allocator, "{\"arr\":[1,2,3]}", ".arr"); + try testRun("{\"bar\":true}", allocator, "{\"foo\":{\"bar\":true}}", ".foo"); +} -- cgit v1.3-1-g0d28