summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-10-08 21:15:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2011-10-08 21:15:34 -0700
commite4f1c4c7efa33df19a22cc577c93e590ca99543b (patch)
tree8f4f7cc5b92a717e5e94da2b742f03460bb5c0cc
parent9b352a96e064d5d201e2d448f9650a0dd9d67b68 (diff)
downloadtxr-e4f1c4c7efa33df19a22cc577c93e590ca99543b.tar.gz
txr-e4f1c4c7efa33df19a22cc577c93e590ca99543b.tar.bz2
txr-e4f1c4c7efa33df19a22cc577c93e590ca99543b.zip
* match.c (vars_k): New symbol variable.
(match_files): Implemented :vars in collect. (match_init): New symbol variable initialized.
-rw-r--r--ChangeLog6
-rw-r--r--match.c45
2 files changed, 48 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 12f53050..599611bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2011-10-08 Kaz Kylheku <kaz@kylheku.com>
+ * match.c (vars_k): New symbol variable.
+ (match_files): Implemented :vars in collect.
+ (match_init): New symbol variable initialized.
+
+2011-10-08 Kaz Kylheku <kaz@kylheku.com>
+
* txr.1: Augment example of @/.*/ being used to skip to the
end of the line with @(skip) which is now better style,
since it avoids reaching for regexes.
diff --git a/match.c b/match.c
index 839d9e06..aec7e63d 100644
--- a/match.c
+++ b/match.c
@@ -50,6 +50,7 @@ int output_produced;
val mingap_k, maxgap_k, gap_k, mintimes_k, maxtimes_k, times_k;
val lines_k, chars_k;
val choose_s, longest_k, shortest_k, greedy_k;
+val vars_k;
static void debugf(val fmt, ...)
{
@@ -1637,6 +1638,7 @@ repeat_spec_same_data:
val mintimes = getplist(args, mintimes_k);
val maxtimes = getplist(args, maxtimes_k);
val lines = getplist(args, lines_k);
+ val vars = getplist(args, vars_k);
cnum cmax = nump(gap) ? c_num(gap) : (nump(max) ? c_num(max) : 0);
cnum cmin = nump(gap) ? c_num(gap) : (nump(min) ? c_num(min) : 0);
cnum mincounter = cmin, maxcounter = 0;
@@ -1652,6 +1654,24 @@ repeat_spec_same_data:
if (gap && (max || min))
sem_error(spec_linenum, lit("collect: cannot mix :gap with :mingap or :maxgap"), nao);
+ if (vars) {
+ list_collect_decl (fixed_vars, tail);
+
+ if (!consp(vars))
+ sem_error(spec_linenum, lit("collect: invalid argument to :vars"), nao);
+ for (iter = vars; iter; iter = cdr(iter)) {
+ val item = car(iter);
+ if (bindable(item)) {
+ list_collect (tail, cons(item, nil));
+ } else if (consp(item) && bindable(first(item))) {
+ list_collect (tail, cons(first(item), second(item)));
+ } else {
+ sem_error(spec_linenum, lit("not a variable spec: ~a"), item, nao);
+ }
+ }
+ vars = fixed_vars;
+ }
+
if ((times && ctimes == 0) || (lines && clines == 0)) {
if ((spec = rest(spec)) == nil)
break;
@@ -1711,13 +1731,31 @@ repeat_spec_same_data:
debuglf(spec_linenum, lit("collect matched ~a:~a"),
first(files), num(data_lineno), nao);
+ for (iter = vars; iter; iter = cdr(iter)) {
+ cons_bind (var, dfl, car(iter));
+ val exists = assoc(new_bindings, var);
+
+ if (!exists) {
+ if (!dfl)
+ sem_error(spec_linenum, lit("collect failed to bind ~a"),
+ var, nao);
+ else
+ strictly_new_bindings = acons(strictly_new_bindings,
+ var, dfl);
+ }
+ }
+
for (iter = strictly_new_bindings; iter; iter = cdr(iter))
{
val binding = car(iter);
- val existing = assoc(bindings_coll, car(binding));
+ val vars_binding = assoc(vars, car(binding));
+
+ if (!vars || vars_binding) {
+ val existing = assoc(bindings_coll, car(binding));
- bindings_coll = acons_new(bindings_coll, car(binding),
- cons(cdr(binding), cdr(existing)));
+ bindings_coll = acons_new(bindings_coll, car(binding),
+ cons(cdr(binding), cdr(existing)));
+ }
}
}
@@ -2311,4 +2349,5 @@ void match_init(void)
longest_k = intern(lit("longest"), keyword_package);
shortest_k = intern(lit("shortest"), keyword_package);
greedy_k = intern(lit("greedy"), keyword_package);
+ vars_k = intern(lit("vars"), keyword_package);
}