hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

ctype.ha (3546B)


      1 // License: MPL-2.0
      2 // (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
      3 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      4 
      5 def U: u8 = 0o1;
      6 def L: u8 = 0o2;
      7 def N: u8 = 0o4;
      8 def S: u8 = 0o10;
      9 def P: u8 = 0o20;
     10 def C: u8 = 0o40;
     11 def B: u8 = 0o100;
     12 def X: u8 = 0o200;
     13 
     14 // LUT of bitfields with character attributes
     15 const cclass: []u8 = [
     16 //	 0	 1	 2	 3	 4	 5	 6	 7
     17 	C,	C,	C,	C,	C,	C,	C,	C,	// 0
     18 	C,	S|C,	S|C,	S|C,	S|C,	S|C,	C,	C,	// 10
     19 	C,	C,	C,	C,	C,	C,	C,	C,	// 20
     20 	C,	C,	C,	C,	C,	C,	C,	C,	// 30
     21 	S|B,	P,	P,	P,	P,	P,	P,	P,	// 40
     22 	P,	P,	P,	P,	P,	P,	P,	P,	// 50
     23 	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	// 60
     24 	N|X,	N|X,	P,	P,	P,	P,	P,	P,	// 70
     25 	P,	U|X,	U|X,	U|X,	U|X,	U|X,	U|X,	U,	// 100
     26 	U,	U,	U,	U,	U,	U,	U,	U,	// 110
     27 	U,	U,	U,	U,	U,	U,	U,	U,	// 120
     28 	U,	U,	U,	P,	P,	P,	P,	P,	// 130
     29 	P,	L|X,	L|X,	L|X,	L|X,	L|X,	L|X,	L,	// 140
     30 	L,	L,	L,	L,	L,	L,	L,	L,	// 150
     31 	L,	L,	L,	L,	L,	L,	L,	L,	// 160
     32 	L,	L,	L,	P,	P,	P,	P,	C,	// 170
     33 ];
     34 
     35 // Returns true if an ASCII character is a letter.
     36 export fn isalpha(c: rune) bool =
     37 	if (!valid(c)) false else cclass[c: u32] & (U | L) > 0;
     38 
     39 // Returns true if an ASCII character is uppercase.
     40 export fn isupper(c: rune) bool =
     41 	if (!valid(c)) false else cclass[c: u32] & U > 0;
     42 
     43 // Returns true if an ASCII character is lowercase.
     44 export fn islower(c: rune) bool =
     45 	if (!valid(c)) false else cclass[c: u32] & L > 0;
     46 
     47 // Returns true if an ASCII character is a digit.
     48 export fn isdigit(c: rune) bool =
     49 	if (!valid(c)) false else cclass[c: u32] & N > 0;
     50 
     51 // Returns true if an ASCII character is a hexadecimal digit.
     52 export fn isxdigit(c: rune) bool =
     53 	if (!valid(c)) false else cclass[c: u32] & X > 0;
     54 
     55 // Returns true if an ASCII character is a white-space character -
     56 // one of '\f', '\n', '\r', '\t', '\v', ' '.
     57 export fn isspace(c: rune) bool =
     58 	if (!valid(c)) false else cclass[c: u32] & S > 0;
     59 
     60 // Returns true if an ASCII character is punctuation.
     61 export fn ispunct(c: rune) bool =
     62 	if (!valid(c)) false else cclass[c: u32] & P > 0;
     63 
     64 // Returns true if an ASCII character is alphanumeric.
     65 export fn isalnum(c: rune) bool =
     66 	if (!valid(c)) false else cclass[c: u32] & (U | L | N) > 0;
     67 
     68 // Returns true if an ASCII character is printable.
     69 export fn isprint(c: rune) bool =
     70 	if (!valid(c)) false else cclass[c: u32] & (P | U | L | N | B ) > 0;
     71 
     72 // Returns true if an ASCII character is any printable character other than
     73 // space.
     74 export fn isgraph(c: rune) bool =
     75 	if (!valid(c)) false else cclass[c: u32] & (P | U | L | N) > 0;
     76 
     77 // Returns true if an ASCII character is a control character.
     78 export fn iscntrl(c: rune) bool =
     79 	if (!valid(c)) false else cclass[c: u32] & C > 0;
     80 
     81 // Returns true if a rune is a space or a tab.
     82 export fn isblank(c: rune) bool = (c == ' ' || c == '\t');
     83 
     84 // Returns the uppercase form of an ASCII character, or the original character
     85 // if it was not a lowercase letter (or was not ASCII).
     86 export fn toupper(c: rune) rune = {
     87 	return if (islower(c)) {
     88 		yield (c: u32 - 'a' + 'A'): rune;
     89 	} else c;
     90 };
     91 
     92 // Returns the lowercase form of an ASCII character, or the original character
     93 // if it was not an uppercase letter (or was not ASCII).
     94 export fn tolower(c: rune) rune = {
     95 	return if (isupper(c)) {
     96 		yield (c: u32 - 'A' + 'a'): rune;
     97 	} else c;
     98 };
     99 
    100 @test fn ctype() void = {
    101 	// Just some simple tests
    102 	assert(isspace(' ') && !isspace('x') && !isspace('こ'));
    103 	assert(isalnum('a') && isalnum('8') && !isalnum('こ'));
    104 	assert(!ispunct('\0') && iscntrl('\b'));
    105 	assert(tolower('A') == 'a' && tolower('こ') == 'こ');
    106 	assert(isblank(' ') && isblank('\t') && !isblank('6'));
    107 };