String Operations
These are three functions to operate on strings.
extract :string # int # int -> string
extracts a substring from a string: the first argument is the source string,
the second argument is the starting position of the substring in the string
(the first character in a string is at position 1), and the third argument
is the length of the substring. It fails with string "extract"
if the numeric arguments are out of range.
match :string # string -> bool
returns true if the first argument is equal to the second argument, the
latter can contain special characters: ? is about to any character;
* refers to any string of characters; # refers
to any numeric character; @ refers to any alphabetic character.
StrLessThan :string # string -> bool
returns true if the first argument is equal to or less than the second one
(in the lexicographical order), false otherwise.
let extract:=
fun(x:string, f:int, L:int):string is
use s:= explode(x)
ext l:= count(s)
in if l < f Or l < f + L - 1
then failwith "extract"
else use r:= var {nth(s,f)}
and c:= var 1
in if L = 1
then implode(at r)
else (while (at c) <= L - 1 do
(r<- nth(s, (at c) + f) :: (at r);
c <- (at c) + 1 );
implode(reverse(at r))
);
let match := fun(a: string, b:string):bool is
use letters:= explode("qwertyuiopasdfghjklzxcvbnm") append
explode("QWERTYUIOPASDFGHJKLZXCVBNM")
and digits:= explode("1234567890")
ext rec try:= fun(a :seq string, b :seq string):bool is
if emptyseq(a)
then emptyseq(b)
else
if first(a) = "*"
then subsL(rest(a),b)
else
if emptyseq(b)
then false
else
if first(a) = "#"
then
if first(b) isin digits
then try(rest(a),rest(b))
else false
else
if first(a) = "@"
then
if first(b) isin letters
then try(rest(a),rest(b))
else false
else
if (first(a) = "?") Or (first(a) = first(b))
then try(rest(a),rest(b))
else false
and subsL:= fun(a :seq string, b :seq string): bool is
if try(a,b)
then true
else
if Not emptyseq(b)
then subsL(a, rest(b))
else false
in try(explode(b), explode(a));
let StrLessThan:= fun(x:string, y:string):bool is
use rec lessThanAscii:= fun(x:seq int, y:seq int):bool is
if emptyseq(x) then true
else if emptyseq(y) then false
else if first(x) = first(y)
then lessThanAscii(rest(x), rest(y))
else if first(x) first(y)
then true
else false
in lessThanAscii(explodeascii(x), explodeascii(y));