2019-04-15 22:14:18 -05:00
|
|
|
// Wraps a string and provides operations for that string.
|
|
|
|
//
|
|
|
|
// * len - property representing the length of the string in characters.
|
|
|
|
//
|
|
|
|
// * str - property the wrapped string.
|
|
|
|
//
|
|
|
|
// * split_on - module that splits the string on a character.
|
2019-04-26 18:48:46 -05:00
|
|
|
// - `on` field represents the string to split on.
|
2019-04-15 22:14:18 -05:00
|
|
|
//
|
|
|
|
// * split_at - function splits the wrapped string at an character index.
|
|
|
|
//
|
|
|
|
// * substr - module that returns a substr of the wrapped string.
|
|
|
|
// - `start` field is the index at which the substr starts (defaults to 0)
|
|
|
|
// - `end` field is the index at which the substr ends (defaults to end of string)
|
2019-02-18 20:15:20 -06:00
|
|
|
let ops = module {
|
|
|
|
str="",
|
2019-04-15 22:14:18 -05:00
|
|
|
} => ({len=len,
|
|
|
|
str=str,
|
2019-04-24 19:19:58 -05:00
|
|
|
chars=chars,
|
2019-04-15 22:14:18 -05:00
|
|
|
split_on=split_on,
|
|
|
|
split_at=split_at,
|
|
|
|
substr=substr,
|
2019-11-24 09:51:24 -05:00
|
|
|
parse_int=parse_int_func,
|
2019-04-15 22:14:18 -05:00
|
|
|
}) {
|
2019-11-24 09:51:24 -05:00
|
|
|
let lists = import "std/lists.ucg";
|
|
|
|
let len = lists.len(mod.str);
|
2019-04-15 22:14:18 -05:00
|
|
|
let str = mod.str;
|
2019-04-24 19:19:58 -05:00
|
|
|
let chars = reduce(func(acc, char) => acc + [char], [], mod.str);
|
2019-04-12 21:13:24 -05:00
|
|
|
|
2019-02-18 20:15:20 -06:00
|
|
|
let split_on = module{
|
|
|
|
on=" ",
|
2019-04-26 18:48:46 -05:00
|
|
|
buf = "",
|
|
|
|
out = [],
|
2019-02-18 20:15:20 -06:00
|
|
|
str=mod.str,
|
2019-02-24 08:16:07 -06:00
|
|
|
} => (result) {
|
2019-04-26 18:48:46 -05:00
|
|
|
let recurse = module {
|
|
|
|
buf = "",
|
|
|
|
acc = [],
|
|
|
|
str = mod.str,
|
|
|
|
sep = NULL,
|
|
|
|
} => (result) {
|
|
|
|
(mod.sep != NULL) || fail "mod.sep can not be NULL";
|
|
|
|
|
|
|
|
let pkg = mod.pkg();
|
|
|
|
let this = mod.this;
|
2019-02-18 20:15:20 -06:00
|
|
|
|
2019-04-26 18:48:46 -05:00
|
|
|
let check_str = pkg.ops{str=mod.str};
|
|
|
|
let split_str = pkg.ops{str=mod.sep};
|
|
|
|
|
|
|
|
let maybe_prefix = check_str.substr{end=split_str.len - 1};
|
|
|
|
let maybe_suffix = check_str.substr{start=split_str.len};
|
|
|
|
|
2019-11-02 11:01:47 -05:00
|
|
|
let result = select (maybe_prefix.len == 0) => {
|
2019-04-26 18:48:46 -05:00
|
|
|
// terminal condition
|
|
|
|
true = mod.acc + [mod.buf],
|
|
|
|
//true = mod,
|
|
|
|
// recurse condition.
|
2019-11-02 11:01:47 -05:00
|
|
|
false = select (maybe_prefix.str == mod.sep) => {
|
2019-04-26 18:48:46 -05:00
|
|
|
true = this{ // this is a match to our separator
|
|
|
|
str=maybe_suffix.str,
|
|
|
|
sep=mod.sep,
|
|
|
|
acc=mod.acc + [mod.buf],
|
|
|
|
},
|
|
|
|
false = this{
|
|
|
|
buf=mod.buf + check_str.chars.0,
|
|
|
|
str=check_str.substr{start=1}.str,
|
|
|
|
sep=mod.sep,
|
|
|
|
acc=mod.acc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
2019-02-18 20:15:20 -06:00
|
|
|
|
2019-04-26 18:48:46 -05:00
|
|
|
let result = recurse{sep=mod.on, str=mod.str};
|
2019-02-18 20:15:20 -06:00
|
|
|
};
|
2019-04-15 22:14:18 -05:00
|
|
|
|
2019-02-18 20:15:20 -06:00
|
|
|
let split_at = func(idx) => filter(
|
|
|
|
func(name, val) => name != "counter",
|
|
|
|
reduce(
|
|
|
|
func(acc, char) => acc{
|
|
|
|
counter = acc.counter + 1,
|
2019-11-02 11:01:47 -05:00
|
|
|
left = select (acc.counter < idx, acc.left) => {
|
2019-02-18 20:15:20 -06:00
|
|
|
true = acc.left + char,
|
|
|
|
},
|
2019-11-02 11:01:47 -05:00
|
|
|
right = select (acc.counter >= idx, acc.right) => {
|
2019-02-18 20:15:20 -06:00
|
|
|
true = acc.right + char,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{counter = 0, left = "", right = ""},
|
|
|
|
mod.str
|
|
|
|
)
|
|
|
|
);
|
2019-04-12 21:13:24 -05:00
|
|
|
|
2019-11-24 09:42:04 -05:00
|
|
|
let parse_int = module{
|
2019-11-24 09:51:24 -05:00
|
|
|
chars = [],
|
|
|
|
acc = "",
|
2019-11-24 09:42:04 -05:00
|
|
|
} => (f.maybe{val=result}) {
|
2019-11-24 09:51:24 -05:00
|
|
|
let this = mod.this;
|
2019-11-24 09:42:04 -05:00
|
|
|
let f = import "std/functional.ucg";
|
2019-11-24 09:51:24 -05:00
|
|
|
let lists = import "std/lists.ucg";
|
2019-11-24 09:42:04 -05:00
|
|
|
|
2019-11-24 09:51:24 -05:00
|
|
|
let is_int = func(c) => select (c, false) => {
|
|
|
|
"0" = true,
|
|
|
|
"1" = true,
|
|
|
|
"2" = true,
|
|
|
|
"3" = true,
|
|
|
|
"4" = true,
|
|
|
|
"5" = true,
|
|
|
|
"6" = true,
|
|
|
|
"7" = true,
|
|
|
|
"8" = true,
|
|
|
|
"9" = true,
|
2019-11-24 09:42:04 -05:00
|
|
|
};
|
2019-11-24 09:51:24 -05:00
|
|
|
|
|
|
|
let result = select (lists.len(mod.chars) == 0, mod.acc) => {
|
|
|
|
false = select (is_int(mod.chars.0), mod.acc) => {
|
|
|
|
true = this{chars=lists.tail(mod.chars), acc=mod.acc+mod.chars.0}.unwrap(),
|
|
|
|
},
|
2019-11-24 09:42:04 -05:00
|
|
|
};
|
2019-11-24 09:51:24 -05:00
|
|
|
|
2019-11-24 09:42:04 -05:00
|
|
|
};
|
|
|
|
|
2019-11-24 09:51:24 -05:00
|
|
|
let parse_int_func = func() => parse_int{chars=chars}.do(func(s) => int(s));
|
|
|
|
|
2019-04-12 21:13:24 -05:00
|
|
|
let substr = module{
|
|
|
|
str = mod.str,
|
|
|
|
start = 0,
|
|
|
|
end = len,
|
|
|
|
} => (result) {
|
2019-04-24 19:30:10 -05:00
|
|
|
let pkg = mod.pkg();
|
2019-04-12 21:13:24 -05:00
|
|
|
let reducer = func(acc, char) => acc{
|
|
|
|
counter = acc.counter + 1,
|
2019-11-02 11:01:47 -05:00
|
|
|
str = select ((acc.counter >= mod.start) && (acc.counter <= mod.end), acc.str) => {
|
2019-04-12 21:13:24 -05:00
|
|
|
true = acc.str + char,
|
|
|
|
},
|
|
|
|
};
|
2019-04-24 19:30:10 -05:00
|
|
|
let result = pkg.ops{str=reduce(
|
2019-04-15 22:14:18 -05:00
|
|
|
reducer, {counter = 0, str = ""}, mod.str).str};
|
2019-04-12 21:13:24 -05:00
|
|
|
};
|
2019-11-24 09:51:24 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let wrap = func(str) => ops{str=str};
|