aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/parse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/jq/parse.zig')
-rw-r--r--src/jq/parse.zig40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/jq/parse.zig b/src/jq/parse.zig
index 6abd7c2..ad64824 100644
--- a/src/jq/parse.zig
+++ b/src/jq/parse.zig
@@ -12,6 +12,7 @@ pub const ParseError = error{
pub const AstKind = enum {
identity,
index,
+ slice,
literal,
binary_expr,
or_expr,
@@ -47,6 +48,7 @@ pub const BinaryOp = enum {
pub const Ast = union(AstKind) {
identity,
index: struct { base: *Ast, index: *Ast, is_optional: bool },
+ slice: struct { base: *Ast, from: ?*Ast, to: ?*Ast, is_optional: bool },
literal: ConstIndex,
binary_expr: struct { op: BinaryOp, lhs: *Ast, rhs: *Ast },
or_expr: struct { lhs: *Ast, rhs: *Ast },
@@ -397,13 +399,43 @@ const Parser = struct {
fn parseSuffix(self: *Self, base: *Ast) Error!*Ast {
_ = try self.tokens.expect(.bracket_left);
- const index_expr = try self.parseExpr();
- _ = try self.tokens.expect(.bracket_right);
- const is_optional = self.tokens.consumeIf(.question);
+ // Handle [:to] form.
+ if (self.tokens.consumeIf(.colon)) {
+ const to_expr = try self.parseQuery();
+ _ = try self.tokens.expect(.bracket_right);
+ const is_optional = self.tokens.consumeIf(.question);
+ const ast = try self.compile_allocator.create(Ast);
+ ast.* = .{ .slice = .{ .base = base, .from = null, .to = to_expr, .is_optional = is_optional } };
+ return ast;
+ }
+
+ const first_query = try self.parseQuery();
+ // Handle [from:to] or [from:] form.
+ if (self.tokens.consumeIf(.colon)) {
+ if (self.tokens.consumeIf(.bracket_right)) {
+ // [from:]
+ const is_optional = self.tokens.consumeIf(.question);
+ const ast = try self.compile_allocator.create(Ast);
+ ast.* = .{ .slice = .{ .base = base, .from = first_query, .to = null, .is_optional = is_optional } };
+ return ast;
+ } else {
+ // [from:to]
+ const to_expr = try self.parseQuery();
+ _ = try self.tokens.expect(.bracket_right);
+ const is_optional = self.tokens.consumeIf(.question);
+ const ast = try self.compile_allocator.create(Ast);
+ ast.* = .{ .slice = .{ .base = base, .from = first_query, .to = to_expr, .is_optional = is_optional } };
+ return ast;
+ }
+ }
+
+ // Handle [index] form.
+ _ = try self.tokens.expect(.bracket_right);
+ const is_optional = self.tokens.consumeIf(.question);
const ast = try self.compile_allocator.create(Ast);
- ast.* = .{ .index = .{ .base = base, .index = index_expr, .is_optional = is_optional } };
+ ast.* = .{ .index = .{ .base = base, .index = first_query, .is_optional = is_optional } };
return ast;
}
};