ken@titan ~/tmp/pm_11155205_uni_char_class $ ls -l *3* -rw-r--r-- 1 ken None 993 Oct 29 05:03 PolyUniCharClass3.pm -rwxr-xr-x 1 ken None 344 Oct 29 05:03 uni_char_class_3.pl #### #!/usr/bin/env perl use v5.38; use open OUT => qw{:encoding(UTF-8) :std}; use lib '.'; # DEMO ONLY -- DON'T use in PRODUCTION! use PolyUniCharClass3; for my $prefix (qw{In Is If}) { for my $class (qw{H L M}) { my $cons = "${prefix}Thai${class}Cons"; say "$cons:"; say PolyUniCharClass3::list($cons)->@*; } } #### package PolyUniCharClass3; use v5.38; sub list ($char_class) { state $valid_char_class = {map +($_ => 1), qw{ InThaiHCons IsThaiHCons InThaiLCons IsThaiLCons }}; unless (exists $valid_char_class->{$char_class}) { warn "Char class '$char_class' doesn't exist!\n"; return []; } return [map chr, ThaiCons(substr $char_class, 2)->@*]; } sub ThaiCons ($cons) { state $code_ranges = { ThaiHCons => [qw{0E02-0E03 0E09 0E10 0E16}], ThaiLCons => [qw{0E04-0E07 0E0A-0E0D 0E11}], }; state $ThaiCons_expanded; return $ThaiCons_expanded->{$cons} //= _expand($code_ranges->{$cons}); } sub _expand ($code_range_list) { state $re = qr{^([0-9A-Fa-f]+)-([0-9A-Fa-f]+)$}; my @full_list; for my $range ($code_range_list->@*) { if ($range =~ $re) { push @full_list, hex($1) .. hex($2); } else { push @full_list, hex $range; } } return [@full_list]; }