different strategy for tokenizing keywords
throughput: 279 MiB/s => 347 MiB/s
This commit is contained in:
parent
b6e1670d2b
commit
ba41a9d5d7
@ -13,14 +13,11 @@ pub const Token = struct {
|
|||||||
pub const Keyword = struct {
|
pub const Keyword = struct {
|
||||||
bytes: []const u8,
|
bytes: []const u8,
|
||||||
id: Id,
|
id: Id,
|
||||||
hash: u32,
|
|
||||||
|
|
||||||
fn init(bytes: []const u8, id: Id) Keyword {
|
fn init(bytes: []const u8, id: Id) Keyword {
|
||||||
@setEvalBranchQuota(2000);
|
|
||||||
return .{
|
return .{
|
||||||
.bytes = bytes,
|
.bytes = bytes,
|
||||||
.id = id,
|
.id = id,
|
||||||
.hash = std.hash_map.hashString(bytes),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -79,15 +76,49 @@ pub const Token = struct {
|
|||||||
Keyword.init("while", .Keyword_while),
|
Keyword.init("while", .Keyword_while),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO perfect hash at comptime
|
|
||||||
pub fn getKeyword(bytes: []const u8) ?Id {
|
pub fn getKeyword(bytes: []const u8) ?Id {
|
||||||
var hash = std.hash_map.hashString(bytes);
|
const precomputed = comptime blk: {
|
||||||
for (keywords) |kw| {
|
@setEvalBranchQuota(2000);
|
||||||
if (kw.hash == hash and mem.eql(u8, kw.bytes, bytes)) {
|
var sorted_keywords = keywords;
|
||||||
return kw.id;
|
const lenAsc = (struct {
|
||||||
|
fn lenAsc(a: Keyword, b: Keyword) bool {
|
||||||
|
return a.bytes.len < b.bytes.len;
|
||||||
|
}
|
||||||
|
}).lenAsc;
|
||||||
|
std.sort.sort(Keyword, &sorted_keywords, lenAsc);
|
||||||
|
const min_len = sorted_keywords[0].bytes.len;
|
||||||
|
const max_len = sorted_keywords[sorted_keywords.len - 1].bytes.len;
|
||||||
|
var len_indexes: [max_len + 1]usize = undefined;
|
||||||
|
var len: usize = 0;
|
||||||
|
var kw_i: usize = 0;
|
||||||
|
while (len <= max_len) : (len += 1) {
|
||||||
|
// find the first keyword len == len
|
||||||
|
while (len > sorted_keywords[kw_i].bytes.len) {
|
||||||
|
kw_i += 1;
|
||||||
|
}
|
||||||
|
len_indexes[len] = kw_i;
|
||||||
}
|
}
|
||||||
|
break :blk .{
|
||||||
|
.min_len = min_len,
|
||||||
|
.max_len = max_len,
|
||||||
|
.sorted_keywords = sorted_keywords,
|
||||||
|
.len_indexes = len_indexes,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (bytes.len < precomputed.min_len or bytes.len > precomputed.max_len)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var i = precomputed.len_indexes[bytes.len];
|
||||||
|
while (true) {
|
||||||
|
const kw = precomputed.sorted_keywords[i];
|
||||||
|
if (kw.bytes.len != bytes.len)
|
||||||
|
return null;
|
||||||
|
if (mem.eql(u8, kw.bytes, bytes))
|
||||||
|
return kw.id;
|
||||||
|
i += 1;
|
||||||
|
if (i >= precomputed.sorted_keywords.len)
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Id = enum {
|
pub const Id = enum {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user