pub fn TokenIterator(comptime T: type, comptime delimiter_type: DelimiterType) type buffer: []const Tdelimiter: switch (delimiter_type) { .sequence, .any => []const T, .scalar => T, }index: usizepub fn next(self: *Self) ?[]const TReturns a slice of the current token, or null if tokenization is complete, and advances to the next token.
pub fn peek(self: *Self) ?[]const TReturns a slice of the current token, or null if tokenization is complete. Does not advance to the next token.
pub fn rest(self: Self) []const TReturns a slice of the remaining bytes. Does not affect iterator state.
pub fn reset(self: *Self) voidResets the iterator to the initial token.
fn isDelimiter(self: Self, index: usize) bool3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398pub fn TokenIterator(comptime T: type, comptime delimiter_type: DelimiterType) type {
return struct {
buffer: []const T,
delimiter: switch (delimiter_type) {
.sequence, .any => []const T,
.scalar => T,
},
index: usize,
const Self = @This();
/// Returns a slice of the current token, or null if tokenization is
/// complete, and advances to the next token.
pub fn next(self: *Self) ?[]const T {
const result = self.peek() orelse return null;
self.index += result.len;
return result;
}
/// Returns a slice of the current token, or null if tokenization is
/// complete. Does not advance to the next token.
pub fn peek(self: *Self) ?[]const T {
// move to beginning of token
while (self.index < self.buffer.len and self.isDelimiter(self.index)) : (self.index += switch (delimiter_type) {
.sequence => self.delimiter.len,
.any, .scalar => 1,
}) {}
const start = self.index;
if (start == self.buffer.len) {
return null;
}
// move to end of token
var end = start;
while (end < self.buffer.len and !self.isDelimiter(end)) : (end += 1) {}
return self.buffer[start..end];
}
/// Returns a slice of the remaining bytes. Does not affect iterator state.
pub fn rest(self: Self) []const T {
// move to beginning of token
var index: usize = self.index;
while (index < self.buffer.len and self.isDelimiter(index)) : (index += switch (delimiter_type) {
.sequence => self.delimiter.len,
.any, .scalar => 1,
}) {}
return self.buffer[index..];
}
/// Resets the iterator to the initial token.
pub fn reset(self: *Self) void {
self.index = 0;
}
fn isDelimiter(self: Self, index: usize) bool {
switch (delimiter_type) {
.sequence => return startsWith(T, self.buffer[index..], self.delimiter),
.any => {
const item = self.buffer[index];
for (self.delimiter) |delimiter_item| {
if (item == delimiter_item) {
return true;
}
}
return false;
},
.scalar => return self.buffer[index] == self.delimiter,
}
}
};
}
Iterator type for tokenization operations, skipping empty sequences and delimiter sequences.