summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--lib.c41
-rw-r--r--lib.h3
-rw-r--r--match.c37
-rw-r--r--txr.19
5 files changed, 89 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 64d6b155..353e258a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2011-11-19 Kaz Kylheku <kaz@kylheku.com>
+ deffilter grows in power: it can take quasistrings.
+
+ * lib.c (cdr_f): New global variable.
+ (funcall1, funcall2, funcall3, funcall4): Fix unterminated
+ arguments in uw_throwf call by using uw_throw instead.
+ (do_or): New static function.
+ (orf): New function.
+ (obj_init): gc_protect and initialize cdr_f.
+
+ * lib.h (cdr_f, orf): Declared.
+
+ * match.c (v_deffilter): Treat the table as forms to be evaluated which
+ must reduce to strings, rather than literal strings.
+
+ * txr.1: Documented.
+
+2011-11-19 Kaz Kylheku <kaz@kylheku.com>
+
* parser.y (yybadtoken): Use ~a to print bad character rather than #\
notation.
diff --git a/lib.c b/lib.c
index f1079030..c1d27c97 100644
--- a/lib.c
+++ b/lib.c
@@ -77,7 +77,7 @@ val null_string;
val nil_string;
val null_list;
-val identity_f, equal_f, eql_f, eq_f, car_f;
+val identity_f, equal_f, eql_f, eq_f, car_f, cdr_f;
val prog_string;
@@ -1535,7 +1535,7 @@ val funcall1(val fun, val arg)
case N1:
return fun->f.f.n1(arg);
default:
- uw_throwf(error_s, lit("funcall1: wrong number of arguments"));
+ uw_throw(error_s, lit("funcall1: wrong number of arguments"));
}
}
@@ -1549,7 +1549,7 @@ val funcall2(val fun, val arg1, val arg2)
case N2:
return fun->f.f.n2(arg1, arg2);
default:
- uw_throwf(error_s, lit("funcall2: wrong number of arguments"));
+ uw_throw(error_s, lit("funcall2: wrong number of arguments"));
}
}
@@ -1563,7 +1563,7 @@ val funcall3(val fun, val arg1, val arg2, val arg3)
case N3:
return fun->f.f.n3(arg1, arg2, arg3);
default:
- uw_throwf(error_s, lit("funcall3: wrong number of arguments"));
+ uw_throw(error_s, lit("funcall3: wrong number of arguments"));
}
}
@@ -1577,7 +1577,7 @@ val funcall4(val fun, val arg1, val arg2, val arg3, val arg4)
case N4:
return fun->f.f.n4(arg1, arg2, arg3, arg4);
default:
- uw_throwf(error_s, lit("funcall4: wrong number of arguments"));
+ uw_throw(error_s, lit("funcall4: wrong number of arguments"));
}
}
@@ -1730,6 +1730,34 @@ val swap_12_21(val fun)
return func_f2(fun, do_swap_12_21);
}
+static val do_or(val fun1_list, val arg)
+{
+ for (; fun1_list; fun1_list = cdr(fun1_list))
+ if (funcall1(car(fun1_list), arg))
+ return t;
+
+ return nil;
+}
+
+val orf(val first_fun, ...)
+{
+ va_list vl;
+ list_collect_decl (out, iter);
+
+ if (first_fun != nao) {
+ val next_fun;
+ va_start (vl, first_fun);
+ list_collect (iter, first_fun);
+
+ while ((next_fun = va_arg(vl, val)) != nao)
+ list_collect (iter, next_fun);
+
+ va_end (vl);
+ }
+
+ return func_f1(out, do_or);
+}
+
val vector(val alloc)
{
cnum alloc_plus = c_num(alloc) + 2;
@@ -2401,7 +2429,7 @@ static void obj_init(void)
protect(&packages, &system_package, &keyword_package,
&user_package, &null_string, &nil_string,
- &null_list, &equal_f, &eq_f, &eql_f, &car_f,
+ &null_list, &equal_f, &eq_f, &eql_f, &car_f, &cdr_f,
&identity_f, &prog_string, &env_list,
(val *) 0);
@@ -2513,6 +2541,7 @@ static void obj_init(void)
eql_f = func_n2(eql);
identity_f = func_n1(identity);
car_f = func_n1(car);
+ cdr_f = func_n1(cdr);
prog_string = string(progname);
}
diff --git a/lib.h b/lib.h
index 5700a35c..4ad5e7a0 100644
--- a/lib.h
+++ b/lib.h
@@ -261,7 +261,7 @@ extern val nothrow_k, args_k;
extern val null_string;
extern val null_list; /* (nil) */
-extern val identity_f, equal_f, eq_f, car_f;
+extern val identity_f, equal_f, eq_f, car_f, cdr_f;
extern const wchar_t *progname;
extern val prog_string;
@@ -399,6 +399,7 @@ val curry_123_23(val fun3, val arg1);
val curry_1234_34(val fun3, val arg1, val arg2);
val chain(val first_fun, ...);
val andf(val first_fun, ...);
+val orf(val first_fun, ...);
val swap_12_21(val fun);
val vector(val alloc);
val vec_get_fill(val vec);
diff --git a/match.c b/match.c
index f5d23760..2b78cc8e 100644
--- a/match.c
+++ b/match.c
@@ -2899,18 +2899,37 @@ static val v_deffilter(match_files_ctx *c)
sem_error(specline, lit("deffilter: ~a is not a symbol"),
first(first_spec), nao);
- if (!all_satisfy(table, andf(func_n1(listp),
- chain(func_n1(length),
- curry_12_1(func_n2(ge), two), nao),
- chain(func_n1(rest),
- curry_123_1(func_n3(all_satisfy),
- func_n1(stringp), nil), nao),
- nao),
- nil))
+ if (!all_satisfy(table, func_n1(listp), nil))
+ sem_error(specline,
+ lit("deffilter arguments must be lists"),
+ nao);
+
+ {
+ val table_evaled = mapcar(curry_12_2(func_n2(mapcar),
+ chain(curry_123_2(func_n3(eval_form),
+ specline, c->bindings),
+ cdr_f,
+ nao)),
+ table);
+
+ if (!all_satisfy(table_evaled, andf(func_n1(listp),
+ chain(func_n1(length),
+ curry_12_1(func_n2(ge), two), nao),
+ chain(func_n1(rest),
+ curry_123_1(func_n3(all_satisfy),
+ func_n1(stringp),
+ nil),
+ nao),
+ nao),
+ nil))
sem_error(specline,
lit("deffilter arguments must be lists of at least two strings"),
nao);
- register_filter(sym, table);
+
+ register_filter(sym, table_evaled);
+ }
+
+
/* TODO: warn about replaced filter. */
return next_spec_k;
}
diff --git a/txr.1 b/txr.1
index 33f21df7..cd30c208 100644
--- a/txr.1
+++ b/txr.1
@@ -3564,9 +3564,10 @@ This directive's syntax is illustrated in this example:
The deffilter symbol must be followed by the name of the filter to be defined,
-followed by tuples of strings. Each tuple specifies one or more texts
-which are mapped to a replacement text. For instance, the following specifies
-a telephone keypad mapping from upper case letters to digits.
+followed by tuples of forms which evaluate to strings. Each tuple specifies one
+or more texts which are mapped to a replacement text. For instance, the
+following specifies a telephone keypad mapping from upper case letters to
+digits. Quasiliterals may be used.
@(deffilter alpha_to_phone ("E" "0")
("J" "N" "Q" "1")
@@ -3579,6 +3580,8 @@ a telephone keypad mapping from upper case letters to digits.
("L" "O" "P" "8")
("G" "H" "Z" "9"))
+ @(deffilter foo (`@a` `@b`) ("c" `->@d`))
+
Filtering works using a longest match algorithm. The input is scanned from left
to right, and the longest piece of text is identified at every character
position which matches a string on the left hand side, and that text is