// ascii — byte-class predicates and case folding for the ASCII range. // Matches Hare's ascii::isdigit family. Bytes outside 0..127 always // answer `false`. The lexer hot path uses these inline; they are // expected to inline to a couple of compares. export fn isdigit(c: u8) bool = { if (c < 48u8) { return false; }; if (c > 57u8) { return false; }; return true; }; export fn isupper(c: u8) bool = { if (c < 65u8) { return false; }; if (c > 90u8) { return false; }; return true; }; export fn islower(c: u8) bool = { if (c < 97u8) { return false; }; if (c > 122u8) { return false; }; return true; }; export fn isalpha(c: u8) bool = { if (isupper(c)) { return true; }; return islower(c); }; export fn isalnum(c: u8) bool = { if (isalpha(c)) { return true; }; return isdigit(c); }; // isspace — the C/Hare set: space, tab, NL, VT, FF, CR. export fn isspace(c: u8) bool = { if (c == 32u8) { return true; }; // ' ' if (c == 9u8) { return true; }; // '\t' if (c == 10u8) { return true; }; // '\n' if (c == 11u8) { return true; }; // '\v' if (c == 12u8) { return true; }; // '\f' if (c == 13u8) { return true; }; // '\r' return false; }; export fn ishex(c: u8) bool = { if (isdigit(c)) { return true; }; if (c >= 65u8) { if (c <= 70u8) { return true; }; // 'A'..'F' }; if (c >= 97u8) { if (c <= 102u8) { return true; }; // 'a'..'f' }; return false; }; // digitval — value of `c` as a hex/decimal digit, or -1 if not one. // Useful when scanning numeric literals. export fn digitval(c: u8) i32 = { if (isdigit(c)) { return (c - 48u8): i32; }; if (c >= 65u8) { if (c <= 70u8) { return ((c - 65u8) + 10u8): i32; }; }; if (c >= 97u8) { if (c <= 102u8) { return ((c - 97u8) + 10u8): i32; }; }; return -1; }; // isidstart / isidpart — identifier classes used by the lexer. // Alpha or '_' starts; alnum or '_' continues. export fn isidstart(c: u8) bool = { if (isalpha(c)) { return true; }; if (c == 95u8) { return true; }; // '_' return false; }; export fn isidpart(c: u8) bool = { if (isalnum(c)) { return true; }; if (c == 95u8) { return true; }; return false; }; // tolower / toupper — fold ASCII case. Non-letters pass through. export fn tolower(c: u8) u8 = { if (isupper(c)) { return c + 32u8; }; return c; }; export fn toupper(c: u8) u8 = { if (islower(c)) { return c - 32u8; }; return c; };