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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
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,
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 {
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() == .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;
}
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;
}
|