From 1419843508b4b47fa55ed25fb6a1e5ad6b0d4968 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Mon, 1 Sep 2025 13:46:16 +0100 Subject: [PATCH] add function to convert string to an unescaped string --- fcore/escape-string.sml | 63 +++++++++++++++++++++++++++++++++++++++++ shf.mlb | 1 + 2 files changed, 64 insertions(+) create mode 100644 fcore/escape-string.sml diff --git a/fcore/escape-string.sml b/fcore/escape-string.sml new file mode 100644 index 0000000..ed6c687 --- /dev/null +++ b/fcore/escape-string.sml @@ -0,0 +1,63 @@ +structure EscapeString = +struct + (* The specific escape sequences handled are in the + * `rewriteAcc` function below. + * These escape sequences were decided on because + * they are the same escape sequences recognised in Standard ML. + * A reference is available here: + * https://smlfamily.github.io/Basis/char.html#SIG:CHAR.fromCString:VAL + * + * However, thre omissions have been made: + * - \ddd denoting an integer in the range 0 - 255 + * - \uxxxx denoting the character whose code is the integer xxxx + * - \f f\ denoting a sequence of characters to ignore + * + * In the first two cases, it is easier to type the character directly. + * In the third case, there is little use for it. + * *) + fun rewriteAcc (#"\\", acc) = + (case acc of + #"a" :: tl => #"\a" :: tl + | #"b" :: tl => #"\b" :: tl + | #"t" :: tl => #"\t" :: tl + | #"n" :: tl => #"\n" :: tl + | #"v" :: tl => #"\v" :: tl + | #"f" :: tl => #"\f" :: tl + | #"r" :: tl => #"\r" :: tl + | #"?" :: tl => #"?" :: tl + | #"\\" :: tl => #"\\" :: tl + | #"\"" :: tl => #"\"" :: tl + | #"'" :: tl => #"'" :: tl + | #"^" :: hd :: tl => + (* handle control characters *) + let + val code = Char.ord hd + in + if code >= 64 andalso code <= 95 then + let val chr = Char.chr (code - 64) + in chr :: tl + end + else + (* invalid escape sequence: leave alone *) + #"\\" :: acc + end + | _ => + (* when there is no valid escape sequence, + * just leave slash in output *) + #"\\" :: acc) + | rewriteAcc (chr, acc) = chr :: acc + + fun help (pos, str, acc) = + if pos < 0 then + String.implode acc + else + let + val chr = String.sub (str, pos) + val acc = rewriteAcc (chr, acc) + in + help (pos - 1, str, acc) + end + + fun unescape str = + help (String.size str - 1, str, []) +end diff --git a/shf.mlb b/shf.mlb index f5ca1b6..712dcee 100644 --- a/shf.mlb +++ b/shf.mlb @@ -16,6 +16,7 @@ in fcore/persistent-vector.sml end +fcore/escape-string.sml fcore/bin-search.sml fcore/search-list.sml