diff options
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | lib.c | 28 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | tests/015/split.tl | 15 | ||||
-rw-r--r-- | txr.1 | 15 |
5 files changed, 52 insertions, 10 deletions
@@ -7217,7 +7217,7 @@ void eval_init(void) reg_fun(intern(lit("spl"), user_package), func_n3o(spl, 2)); reg_fun(intern(lit("split-str-set"), user_package), func_n2(split_str_set)); reg_fun(intern(lit("sspl"), user_package), func_n2(sspl)); - reg_fun(intern(lit("tok-str"), user_package), func_n3o(tok_str, 2)); + reg_fun(intern(lit("tok-str"), user_package), func_n4o(tok_str, 2)); reg_fun(intern(lit("tok"), user_package), func_n3o(tok, 2)); reg_fun(intern(lit("tok-where"), user_package), func_n2(tok_where)); reg_fun(intern(lit("list-str"), user_package), func_n1(list_str)); @@ -5895,15 +5895,23 @@ val sspl(val set, val str) return split_str_set(str, set); } -val tok_str(val str, val tok_regex, val keep_sep) +val tok_str(val str, val tok_regex, val keep_sep_opt, val count_opt) { + val self = lit("tok-str"); list_collect_decl (out, iter); val pos = zero; val last_end = zero; val slen = length(str); int prev_empty = 1; + val keep_sep = default_null_arg(keep_sep_opt); + val count = default_null_arg(count_opt); + cnum cnt = c_num(if3(count, count, negone), self); + + if (count && cnt < 0) + uw_throwf(error_s, lit("~a: count must be nonnegative"), self, nao); - keep_sep = default_null_arg(keep_sep); + if (count == zero) + return if2(keep_sep || slen != zero, cons(str, nil)); if (opt_compat && opt_compat <= 155) for (;;) { cons_bind (new_pos, len, search_regex(str, tok_regex, pos, nil)); @@ -5922,6 +5930,12 @@ val tok_str(val str, val tok_regex, val keep_sep) pos = plus(new_pos, len); iter = list_collect(iter, sub_str(str, new_pos, pos)); + + if (cnt > 0 && --cnt == 0) { + if (pos != slen || keep_sep) + iter = list_collect(iter, sub_str(str, pos, t)); + break; + } } else for (;;) { cons_bind (new_pos, len, search_regex(str, tok_regex, pos, nil)); @@ -5945,6 +5959,12 @@ val tok_str(val str, val tok_regex, val keep_sep) if (len == zero) pos = succ(pos); + + if (cnt > 0 && --cnt == 0) { + if (pos != slen || keep_sep) + iter = list_collect(iter, sub_str(str, pos, t)); + break; + } } return out; @@ -5953,8 +5973,8 @@ val tok_str(val str, val tok_regex, val keep_sep) val tok(val tok_regex, val arg1, val arg2) { return if3(missingp(arg2), - tok_str(arg1, tok_regex, arg2), - tok_str(arg2, tok_regex, arg1)); + tok_str(arg1, tok_regex, arg2, nil), + tok_str(arg2, tok_regex, arg1, nil)); } val tok_where(val str, val tok_regex) @@ -929,7 +929,7 @@ val split_str_keep(val str, val sep, val keep_sep_opt, val count_opt); val spl(val sep, val arg1, val arg2); val split_str_set(val str, val set); val sspl(val set, val str); -val tok_str(val str, val tok_regex, val keep_sep); +val tok_str(val str, val tok_regex, val keep_sep_opt, val count_opt); val tok(val tok_regex, val arg1, val arg2); val tok_where(val str, val tok_regex); val list_str(val str); diff --git a/tests/015/split.tl b/tests/015/split.tl index 8cdf7f04..9e952342 100644 --- a/tests/015/split.tl +++ b/tests/015/split.tl @@ -196,6 +196,21 @@ (tok-str "abcacabcac" #/ab?/ t) ("" "ab" "c" "a" "c" "ab" "c" "a" "c")) (mtest + (tok-str "" #/[^,]/ : 0) () + (tok-str "a,b,c" #/[^,]/ : 0) ("a,b,c") + (tok-str "a,b,c" #/[^,]/ : 1) ("a" ",b,c") + (tok-str "a,b,c" #/[^,]/ : 2) ("a" "b" ",c") + (tok-str "a,b,c" #/[^,]/ : 3) #"a b c" + (tok-str "a,b,c" #/[^,]/ : 4) #"a b c") + +(mtest + (tok-str "a,b,c" #/[^,]/ t 0) ("a,b,c") + (tok-str "a,b,c" #/[^,]/ t 1) ("" "a" ",b,c") + (tok-str "a,b,c" #/[^,]/ t 2) ("" "a" "," "b" ",c") + (tok-str "a,b,c" #/[^,]/ t 3) ("" "a" "," "b" "," "c" "") + (tok-str "a,b,c" #/[^,]/ t 4) ("" "a" "," "b" "," "c" "")) + +(mtest (join) "" (join "") "" (join "" "") "" @@ -25563,7 +25563,7 @@ is argument order. .coNP Functions @ tok-str and @ tok-where .synb -.mets (tok-str < string < regex <> [ keep-between ]) +.mets (tok-str < string < regex >> [ keep-between <> [ count ]]) .mets (tok-where < string << regex ) .syne .desc @@ -25619,9 +25619,7 @@ character and is extracted. If the .meta keep-between -argument is specified, and is not -.codn nil , -then the behavior +argument is true, then the behavior of .code tok-str changes in the following way. The pieces of @@ -25640,6 +25638,15 @@ substring of .meta string between the last token and the end. +If +.meta count +is specified, it must be a nonnegative integer. The value limits the +number of tokens which are extracted. The returned list then includes +one more item: the remainder of the string after the last extracted token. +This item is omitted if the rest of the string is empty, unless +.meta keep-between +is true. + The .code tok-where function works similarly to |