aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/parse.zig
blob: 5269ef502c1886171cf5dba987f2fb75397d4a3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
const std = @import("std");
const jv = @import("../jv.zig");
const Token = @import("./tokenize.zig").Token;

pub const ParseError = error{
    UnexpectedEnd,
    InvalidQuery,
};

pub const AstKind = enum {
    identity,
    array_index,
    literal,
};

pub const Ast = union(AstKind) {
    identity,
    array_index: *Ast,
    literal: *jv.Value,

    pub fn kind(self: @This()) AstKind {
        return self;
    }
};

pub fn parse(allocator: std.mem.Allocator, tokens: []const Token) !*Ast {
    if (tokens.len < 2) {
        return error.InvalidQuery;
    }

    var i: usize = 0;
    const t1 = tokens[i];
    if (t1.kind() != .dot) {
        return error.InvalidQuery;
    }
    i += 1;
    const t2 = tokens[i];

    if (t2.kind() == .end) {
        const root = try allocator.create(Ast);
        root.* = .identity;
        return root;
    }

    if (t2.kind() != .bracket_left) {
        return error.InvalidQuery;
    }

    i += 1;
    if (tokens.len < 5) {
        return error.UnexpectedEnd;
    }
    const t3 = tokens[i];
    i += 1;
    const t4 = tokens[i];
    i += 1;
    const t5 = tokens[i];

    if (t3.kind() != .number) {
        return error.InvalidQuery;
    }
    if (t4.kind() != .bracket_right) {
        return error.InvalidQuery;
    }
    if (t5.kind() != .end) {
        return error.InvalidQuery;
    }

    const index_value = try allocator.create(jv.Value);
    index_value.* = .{
        .integer = t3.number,
    };
    const index_node = try allocator.create(Ast);
    index_node.* = .{
        .literal = index_value,
    };
    const root = try allocator.create(Ast);
    root.* = .{
        .array_index = index_node,
    };
    return root;
}