thp-zig/src/01_lexic/utils.zig

91 lines
2.1 KiB
Zig

const token = @import("./token.zig");
const LexError = token.LexError;
const LexReturn = token.LexReturn;
pub fn is_decimal_digit(c: u8) bool {
return '0' <= c and c <= '9';
}
pub fn is_octal_digit(c: u8) bool {
return '0' <= c and c <= '7';
}
pub fn is_binary_digit(c: u8) bool {
return c == '0' or c == '1';
}
pub fn is_hex_digit(c: u8) bool {
return ('0' <= c and c <= '9') or ('a' <= c and c <= 'f') or ('A' <= c and c <= 'F');
}
pub fn is_lowercase(c: u8) bool {
return 'a' <= c and c <= 'z';
}
pub fn is_lowercase_underscore(c: u8) bool {
return c == '_' or ('a' <= c and c <= 'z');
}
/// identifier_letter = underscore | lowercase | uppercase | digit
pub fn is_identifier_char(c: u8) bool {
return c == '_' or ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z') or ('0' <= c and c <= '9');
}
/// Runs a discriminator function at least once,
/// and returns the end position of the lex.
///
/// If there is no more input or the lexer does not match
/// at least once, returns null.
pub fn lex_many_1(
comptime lex_fun: fn (c: u8) bool,
input: []const u8,
start: usize,
) usize {
// assert that there is input left
const cap = input.len;
var current_pos = start;
if (current_pos >= cap) {
return null;
}
// run the lexer at least once
if (!lex_fun(input[current_pos])) {
return null;
}
current_pos += 1;
// run the lexer many times
while (current_pos < cap and lex_fun(input[current_pos])) {
current_pos += 1;
}
return current_pos;
}
/// Runs a discriminator function zero, one or more times
/// and returns the end position of the lex.
///
/// If there is no more input or the lexer does not match
/// at least once, returns null.
pub fn lex_many(
comptime lex_fun: fn (c: u8) bool,
input: []const u8,
start: usize,
) ?usize {
// assert that there is input left
const cap = input.len;
var current_pos = start;
if (current_pos >= cap) {
return null;
}
// run the lexer many times
while (current_pos < cap and lex_fun(input[current_pos])) {
current_pos += 1;
}
return current_pos;
}