91 lines
2.1 KiB
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;
|
|
}
|