290 lines
13 KiB
Zig
290 lines
13 KiB
Zig
const std = @import("std");
|
|
const dtype = @import("dtype");
|
|
const UUID = dtype.UUID;
|
|
const Allocator = std.mem.Allocator;
|
|
const Token = @import("../tokenizer.zig").Token;
|
|
const Filter = @import("../../dataStructure/filter.zig").Filter;
|
|
const ConditionValue = @import("../../dataStructure/filter.zig").ConditionValue;
|
|
const AdditionalData = @import("../../dataStructure/additionalData.zig").AdditionalData;
|
|
const printError = @import("../../utils.zig").printError;
|
|
|
|
const ZipponError = @import("error").ZipponError;
|
|
|
|
const Self = @import("../parser.zig");
|
|
|
|
/// To run just after a condition like = or > or >= to get the corresponding ConditionValue that you need to compare
|
|
pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []const u8, member_name: []const u8, data_type: dtype.DataType, token: *Token) ZipponError!ConditionValue {
|
|
const start_index = token.loc.start;
|
|
const expected_tag: ?Token.Tag = switch (data_type) {
|
|
.int => .int_literal,
|
|
.float => .float_literal,
|
|
.str => .string_literal,
|
|
.self => .uuid_literal,
|
|
.int_array => .int_literal,
|
|
.float_array => .float_literal,
|
|
.str_array => .string_literal,
|
|
.bool, .bool_array, .link, .link_array, .date, .time, .datetime, .date_array, .time_array, .datetime_array => null, // handle separately
|
|
};
|
|
|
|
// Check if the all next tokens are the right one
|
|
if (expected_tag) |tag| {
|
|
if (data_type.is_array()) {
|
|
token.* = try self.checkTokensInArray(tag);
|
|
} else {
|
|
if (token.tag != tag) {
|
|
return printError(
|
|
"Error: Wrong type", // TODO: Print the expected type
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
}
|
|
}
|
|
} else switch (data_type) {
|
|
.bool => if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
|
|
return printError(
|
|
"Error: Expected bool",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
},
|
|
.bool_array => {
|
|
token.* = self.toker.next();
|
|
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
|
if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
|
|
return printError(
|
|
"Error: Expected bool or ]",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
}
|
|
}
|
|
},
|
|
.date => if (token.tag != .date_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected date",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
},
|
|
.date_array => {
|
|
token.* = self.toker.next();
|
|
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
|
if (token.tag != .date_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected date",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
}
|
|
}
|
|
},
|
|
.time => if (token.tag != .time_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected time",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
},
|
|
.time_array => {
|
|
token.* = self.toker.next();
|
|
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
|
if (token.tag != .time_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected time",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
}
|
|
}
|
|
},
|
|
.datetime => if (token.tag != .datetime_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected datetime",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
},
|
|
.datetime_array => {
|
|
token.* = self.toker.next();
|
|
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
|
if (token.tag != .datetime_literal and token.tag != .keyword_now) {
|
|
return printError(
|
|
"Error: Expected datetime",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
}
|
|
}
|
|
},
|
|
.link, .link_array => {},
|
|
else => unreachable,
|
|
}
|
|
|
|
// And finally create the ConditionValue
|
|
switch (data_type) {
|
|
.int => return ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]),
|
|
.float => return ConditionValue.initFloat(self.toker.buffer[start_index..token.loc.end]),
|
|
.str => return ConditionValue.initStr(self.toker.buffer[start_index + 1 .. token.loc.end - 1]),
|
|
.date => return ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]),
|
|
.time => return ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]),
|
|
.datetime => return ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]),
|
|
.bool => return ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]),
|
|
.int_array => return try ConditionValue.initArrayInt(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.str_array => return try ConditionValue.initArrayStr(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.bool_array => return try ConditionValue.initArrayBool(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.float_array => return try ConditionValue.initArrayFloat(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.date_array => return try ConditionValue.initArrayDate(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.time_array => return try ConditionValue.initArrayTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.datetime_array => return try ConditionValue.initArrayDateTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
|
.link => switch (token.tag) {
|
|
.keyword_none => { // TODO: Stop creating a map if empty, can be null or something. Or maybe just keep one map link that in memory, so I dont create it everytime
|
|
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
map.put(dtype.Zero, {}) catch return ZipponError.MemoryError;
|
|
_ = self.toker.next();
|
|
return ConditionValue.initLink(map);
|
|
},
|
|
.uuid_literal => {
|
|
const uuid = UUID.parse(self.toker.buffer[start_index..token.loc.end]) catch return ZipponError.InvalidUUID;
|
|
if (!self.schema_engine.isUUIDExist(struct_name, uuid)) return printError(
|
|
"Error: UUID do not exist in database.",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
|
|
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
map.put(uuid, {}) catch return ZipponError.MemoryError;
|
|
_ = self.toker.next();
|
|
return ConditionValue.initLink(map);
|
|
},
|
|
.l_brace, .l_bracket => {
|
|
var filter: ?Filter = null;
|
|
defer if (filter != null) filter.?.deinit();
|
|
|
|
var additional_data_arena = std.heap.ArenaAllocator.init(allocator);
|
|
defer additional_data_arena.deinit();
|
|
var additional_data = AdditionalData.init(additional_data_arena.allocator());
|
|
|
|
if (token.tag == .l_bracket) {
|
|
try self.parseAdditionalData(allocator, &additional_data, struct_name);
|
|
token.* = self.toker.next();
|
|
}
|
|
|
|
additional_data.limit = 1;
|
|
|
|
const link_sstruct = try self.schema_engine.linkedStructName(struct_name, member_name);
|
|
if (token.tag == .l_brace) filter = try self.parseFilter(
|
|
allocator,
|
|
link_sstruct.name,
|
|
false,
|
|
) else return printError(
|
|
"Error: Expected filter",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
|
|
filter = switch (filter.?.root.*) {
|
|
.empty => null,
|
|
else => filter,
|
|
};
|
|
|
|
// Here I have the filter and additionalData
|
|
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
try self.file_engine.populateVoidUUIDMap(
|
|
link_sstruct.name,
|
|
filter,
|
|
map,
|
|
&additional_data,
|
|
);
|
|
return ConditionValue.initLink(map);
|
|
},
|
|
|
|
else => return printError(
|
|
"Error: Expected uuid or none",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
.link_array => switch (token.tag) {
|
|
.keyword_none => {
|
|
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
_ = self.toker.next();
|
|
return ConditionValue.initArrayLink(map);
|
|
},
|
|
.l_brace, .l_bracket => {
|
|
var filter: ?Filter = null;
|
|
defer if (filter != null) filter.?.deinit();
|
|
|
|
var additional_data_arena = std.heap.ArenaAllocator.init(allocator);
|
|
defer additional_data_arena.deinit();
|
|
var additional_data = AdditionalData.init(additional_data_arena.allocator());
|
|
|
|
if (token.tag == .l_bracket) {
|
|
try self.parseAdditionalData(allocator, &additional_data, struct_name);
|
|
token.* = self.toker.next();
|
|
}
|
|
|
|
const link_sstruct = try self.schema_engine.linkedStructName(struct_name, member_name);
|
|
if (token.tag == .l_brace) filter = try self.parseFilter(allocator, link_sstruct.name, false) else return printError(
|
|
"Error: Expected filter",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
);
|
|
|
|
filter = switch (filter.?.root.*) {
|
|
.empty => null,
|
|
else => filter,
|
|
};
|
|
|
|
// Here I have the filter and additionalData
|
|
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
try self.file_engine.populateVoidUUIDMap(
|
|
struct_name,
|
|
filter,
|
|
map,
|
|
&additional_data,
|
|
);
|
|
return ConditionValue.initArrayLink(map);
|
|
},
|
|
else => return printError(
|
|
"Error: Expected uuid or none",
|
|
ZipponError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
.self => unreachable,
|
|
}
|
|
}
|