aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/parse.zig
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-17 23:31:40 +0900
committernsfisis <nsfisis@gmail.com>2026-01-18 00:37:54 +0900
commit6739144edaf34d10e0c0901231b196f377007934 (patch)
tree015d78a96fa66390fe332226a1f27e7a55bda52e /src/jq/parse.zig
parent0295edea4c2d5e6f2e0a6761483cc9e2c64544f8 (diff)
downloadzgjq-6739144edaf34d10e0c0901231b196f377007934.tar.gz
zgjq-6739144edaf34d10e0c0901231b196f377007934.tar.zst
zgjq-6739144edaf34d10e0c0901231b196f377007934.zip
implement addition
Diffstat (limited to 'src/jq/parse.zig')
-rw-r--r--src/jq/parse.zig76
1 files changed, 53 insertions, 23 deletions
diff --git a/src/jq/parse.zig b/src/jq/parse.zig
index 7ceda69..244d2a3 100644
--- a/src/jq/parse.zig
+++ b/src/jq/parse.zig
@@ -13,6 +13,11 @@ pub const AstKind = enum {
array_index,
object_key,
literal,
+ binary_expr,
+};
+
+pub const BinaryOp = enum {
+ add,
};
pub const Ast = union(AstKind) {
@@ -20,6 +25,7 @@ pub const Ast = union(AstKind) {
array_index: *Ast,
object_key: []const u8,
literal: *jv.Value,
+ binary_expr: struct { op: BinaryOp, lhs: *Ast, rhs: *Ast },
pub fn kind(self: @This()) AstKind {
return self;
@@ -70,42 +76,66 @@ pub fn parse(allocator: std.mem.Allocator, tokens: []const Token) !*Ast {
}
// GRAMMAR
-// query := filter
+// query := expr
fn parseQuery(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast {
- const result = try parseFilter(allocator, tokens);
+ const result = try parseExpr(allocator, tokens);
_ = try tokens.expect(.end);
return result;
}
// GRAMMAR
-// filter := "." accessor?
-fn parseFilter(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast {
- _ = try tokens.expect(.dot);
-
- const next_token = try tokens.peek();
-
- if (next_token.kind() == .end) {
+// expr := term
+// | 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.* = .identity;
- return ast;
+ ast.* = .{ .binary_expr = .{
+ .op = .add,
+ .lhs = lhs,
+ .rhs = rhs,
+ } };
+ lhs = ast;
}
-
- return parseAccessor(allocator, tokens);
+ return lhs;
}
// GRAMMAR
-// accessor := field_access | index_access
-fn parseAccessor(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast {
- const token = try tokens.peek();
-
- if (token.kind() == .identifier) {
- return parseFieldAccess(allocator, tokens);
- }
- if (token.kind() == .bracket_left) {
- return parseIndexAccess(allocator, tokens);
+// term := "."
+// | "." field_access
+// | "." index_access
+// | NUMBER
+fn parseTerm(allocator: std.mem.Allocator, tokens: *TokenStream) !*Ast {
+ const first_token = try tokens.peek();
+ if (first_token.kind() == .number) {
+ _ = try tokens.next();
+ const number_value = try allocator.create(jv.Value);
+ number_value.* = .{ .integer = first_token.number };
+ const number_node = try allocator.create(Ast);
+ number_node.* = .{ .literal = number_value };
+ return number_node;
}
- return error.InvalidQuery;
+ _ = try tokens.expect(.dot);
+
+ const next_token = try tokens.peek();
+ switch (next_token.kind()) {
+ .end => {
+ const ast = try allocator.create(Ast);
+ ast.* = .identity;
+ return ast;
+ },
+ .identifier => {
+ return parseFieldAccess(allocator, tokens);
+ },
+ .bracket_left => {
+ return parseIndexAccess(allocator, tokens);
+ },
+ else => return error.InvalidQuery,
+ }
}
// GRAMMAR