diff options
Diffstat (limited to 'src/jq')
| -rw-r--r-- | src/jq/compile.zig | 8 | ||||
| -rw-r--r-- | src/jq/execute.zig | 4 | ||||
| -rw-r--r-- | src/jq/parse.zig | 54 |
3 files changed, 47 insertions, 19 deletions
diff --git a/src/jq/compile.zig b/src/jq/compile.zig index e3937c6..f4044c9 100644 --- a/src/jq/compile.zig +++ b/src/jq/compile.zig @@ -54,6 +54,14 @@ pub fn compile(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocato try instrs.append(allocator, .subexp_end); try instrs.append(allocator, .add); }, + .pipe => |pipe_expr| { + const lhs_instrs = try compile(allocator, compile_allocator, pipe_expr.lhs); + defer allocator.free(lhs_instrs); + const rhs_instrs = try compile(allocator, compile_allocator, pipe_expr.rhs); + defer allocator.free(rhs_instrs); + try instrs.appendSlice(allocator, lhs_instrs); + try instrs.appendSlice(allocator, rhs_instrs); + }, } return instrs.toOwnedSlice(allocator); diff --git a/src/jq/execute.zig b/src/jq/execute.zig index 29025b4..8982458 100644 --- a/src/jq/execute.zig +++ b/src/jq/execute.zig @@ -100,6 +100,8 @@ pub fn execute(allocator: std.mem.Allocator, instrs: []const Instr, input: jv.Va const cur = instrs[pc]; switch (cur) { .nop => {}, + .subexp_begin => try value_stack.dup(), + .subexp_end => value_stack.swap(), .array_index => { const array = try value_stack.popArray(); const index: usize = @intCast(try value_stack.popInteger()); @@ -113,8 +115,6 @@ pub fn execute(allocator: std.mem.Allocator, instrs: []const Instr, input: jv.Va const result = lhs + rhs; try value_stack.push(.{ .integer = result }); }, - .subexp_begin => try value_stack.dup(), - .subexp_end => value_stack.swap(), .object_key => |key| { const obj = try value_stack.popObject(); const result = obj.get(key) orelse .null; diff --git a/src/jq/parse.zig b/src/jq/parse.zig index 244d2a3..26458f9 100644 --- a/src/jq/parse.zig +++ b/src/jq/parse.zig @@ -14,6 +14,7 @@ pub const AstKind = enum { object_key, literal, binary_expr, + pipe, }; pub const BinaryOp = enum { @@ -26,6 +27,7 @@ pub const Ast = union(AstKind) { object_key: []const u8, literal: *jv.Value, binary_expr: struct { op: BinaryOp, lhs: *Ast, rhs: *Ast }, + pipe: struct { lhs: *Ast, rhs: *Ast }, pub fn kind(self: @This()) AstKind { return self; @@ -76,29 +78,47 @@ pub fn parse(allocator: std.mem.Allocator, tokens: []const Token) !*Ast { } // GRAMMAR -// query := expr +// query := expr ("|" expr)* fn parseQuery(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast { - const result = try parseExpr(allocator, tokens); + var lhs = try parseExpr(allocator, tokens); + while (true) { + const token = try tokens.peek(); + if (token.kind() == .pipe) { + _ = try tokens.next(); + const rhs = try parseExpr(allocator, tokens); + const ast = try allocator.create(Ast); + ast.* = .{ .pipe = .{ + .lhs = lhs, + .rhs = rhs, + } }; + lhs = ast; + } else { + break; + } + } _ = try tokens.expect(.end); - return result; + return lhs; } // GRAMMAR -// expr := term -// | term + term +// expr := term ("+" term)* fn parseExpr(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast { var lhs = try parseTerm(allocator, tokens); - const token = try tokens.peek(); - if (token.kind() == .plus) { - _ = try tokens.next(); - const rhs = try parseTerm(allocator, tokens); - const ast = try allocator.create(Ast); - ast.* = .{ .binary_expr = .{ - .op = .add, - .lhs = lhs, - .rhs = rhs, - } }; - lhs = ast; + while (true) { + const token = try tokens.peek(); + if (token.kind() == .plus) { + _ = try tokens.next(); + const rhs = try parseTerm(allocator, tokens); + const ast = try allocator.create(Ast); + ast.* = .{ .binary_expr = .{ + .op = .add, + .lhs = lhs, + .rhs = rhs, + } }; + lhs = ast; + } else { + break; + } } return lhs; } @@ -123,7 +143,7 @@ fn parseTerm(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast { const next_token = try tokens.peek(); switch (next_token.kind()) { - .end => { + .end, .pipe, .plus => { const ast = try allocator.create(Ast); ast.* = .identity; return ast; |
