Added the datatype date, time and datetime Moved all custom erros to a single file Cleaned code to be more readable and created some small utils Other stuffs that I dont recall. Basically preparing for the relationship implementation
238 lines
9.0 KiB
Zig
238 lines
9.0 KiB
Zig
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const DataType = @import("types/dataType.zig").DataType;
|
|
const Toker = @import("tokenizers/schema.zig").Tokenizer;
|
|
const Token = @import("tokenizers/schema.zig").Token;
|
|
const send = @import("stuffs/utils.zig").send;
|
|
const printError = @import("stuffs/utils.zig").printError;
|
|
|
|
const SchemaParserError = @import("stuffs/errors.zig").SchemaParserError;
|
|
|
|
const State = enum {
|
|
end,
|
|
invalid,
|
|
expect_struct_name_OR_end,
|
|
expect_member_name,
|
|
expect_l_paren,
|
|
expect_member_name_OR_r_paren,
|
|
expect_value_type,
|
|
expext_array_type,
|
|
expect_two_dot,
|
|
expect_comma,
|
|
};
|
|
|
|
pub const Parser = struct {
|
|
toker: *Toker,
|
|
allocator: Allocator,
|
|
|
|
pub fn init(toker: *Toker, allocator: Allocator) Parser {
|
|
return .{
|
|
.allocator = allocator,
|
|
.toker = toker,
|
|
};
|
|
}
|
|
|
|
pub const SchemaStruct = struct {
|
|
allocator: Allocator,
|
|
name: Token.Loc,
|
|
members: std.ArrayList(Token.Loc),
|
|
types: std.ArrayList(DataType),
|
|
|
|
pub fn init(allocator: Allocator, name: Token.Loc) SchemaStruct {
|
|
return SchemaStruct{
|
|
.allocator = allocator,
|
|
.name = name,
|
|
.members = std.ArrayList(Token.Loc).init(allocator),
|
|
.types = std.ArrayList(DataType).init(allocator),
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: *SchemaStruct) void {
|
|
self.types.deinit();
|
|
self.members.deinit();
|
|
}
|
|
};
|
|
|
|
pub fn parse(self: *Parser, struct_array: *std.ArrayList(SchemaStruct)) !void {
|
|
var state: State = .expect_struct_name_OR_end;
|
|
var index: usize = 0;
|
|
var keep_next = false;
|
|
|
|
errdefer {
|
|
for (0..struct_array.items.len) |i| {
|
|
struct_array.items[i].deinit();
|
|
}
|
|
|
|
for (0..struct_array.items.len) |_| {
|
|
_ = struct_array.pop();
|
|
}
|
|
}
|
|
|
|
var token = self.toker.next();
|
|
while ((state != .end) and (state != .invalid)) : ({
|
|
token = if (!keep_next) self.toker.next() else token;
|
|
keep_next = false;
|
|
}) switch (state) {
|
|
.expect_struct_name_OR_end => switch (token.tag) {
|
|
.identifier => {
|
|
state = .expect_l_paren;
|
|
struct_array.append(SchemaStruct.init(self.allocator, token.loc)) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.eof => state = .end,
|
|
else => return printError(
|
|
"Error parsing schema: Expected a struct name",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expect_l_paren => switch (token.tag) {
|
|
.l_paren => state = .expect_member_name,
|
|
else => return printError(
|
|
"Error parsing schema: Expected (",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expect_member_name_OR_r_paren => switch (token.tag) {
|
|
.identifier => {
|
|
state = .expect_member_name;
|
|
keep_next = true;
|
|
},
|
|
.r_paren => {
|
|
state = .expect_struct_name_OR_end;
|
|
index += 1;
|
|
},
|
|
else => return printError(
|
|
"Error parsing schema: Expected member name or )",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expect_member_name => {
|
|
state = .expect_two_dot;
|
|
struct_array.items[index].members.append(token.loc) catch return SchemaParserError.MemoryError;
|
|
},
|
|
|
|
.expect_two_dot => switch (token.tag) {
|
|
.two_dot => state = .expect_value_type,
|
|
else => return printError(
|
|
"Error parsing schema: Expected :",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expect_value_type => switch (token.tag) {
|
|
.type_int => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.int) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_str => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.str) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_float => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.float) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_bool => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.bool) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_date => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.date) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_time => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.time) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_datetime => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.datetime) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.identifier => return SchemaParserError.FeatureMissing,
|
|
.lr_bracket => state = .expext_array_type,
|
|
else => return printError(
|
|
"Error parsing schema: Expected data type",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expext_array_type => switch (token.tag) {
|
|
.type_int => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.int_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_str => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.str_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_float => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.float_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_bool => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.bool_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_date => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.date_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_time => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.time_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.type_datetime => {
|
|
state = .expect_comma;
|
|
struct_array.items[index].types.append(DataType.datetime_array) catch return SchemaParserError.MemoryError;
|
|
},
|
|
.identifier => return printError(
|
|
"Error parsing schema: Relationship not yet implemented",
|
|
SchemaParserError.FeatureMissing,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
else => return printError(
|
|
"Error parsing schema: Expected data type",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
.expect_comma => switch (token.tag) {
|
|
.comma => state = .expect_member_name_OR_r_paren,
|
|
else => return printError(
|
|
"Error parsing schema: Expected ,",
|
|
SchemaParserError.SynthaxError,
|
|
self.toker.buffer,
|
|
token.loc.start,
|
|
token.loc.end,
|
|
),
|
|
},
|
|
|
|
else => unreachable,
|
|
};
|
|
}
|
|
};
|
|
|
|
// TODO: Some test, weird that there isn't any yet
|