summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-09-29 08:45:26 -0700
committerKaz Kylheku <kaz@kylheku.com>2011-09-29 08:45:26 -0700
commit4e33de0b5b4a32e9b9b44c2ac23f4d757eb6e92e (patch)
tree02f7a406a9cf8c7c8a6031b0fcefcb783b357755 /match.c
parente24b844825e726b0f050faaf28d00798c29e342f (diff)
downloadtxr-4e33de0b5b4a32e9b9b44c2ac23f4d757eb6e92e.tar.gz
txr-4e33de0b5b4a32e9b9b44c2ac23f4d757eb6e92e.tar.bz2
txr-4e33de0b5b4a32e9b9b44c2ac23f4d757eb6e92e.zip
* match.c (mingap_k, maxgap_k, gap_k, times_k, lines_k): New
symbol variables. (match_lines): Keyword arguments in collect implemented. (match_init): New function. * match.h (match_init): Declared. * parser.l (COLLECT): Lexical syntax changed for COLLECT to allow for argument material. * parser.y (%union): obj renamed to val. (exprs_opt): New nonterminal. (collect_clause): Rewritten for arguments. * txr.c (main): Call to match_init introduced.
Diffstat (limited to 'match.c')
-rw-r--r--match.c132
1 files changed, 91 insertions, 41 deletions
diff --git a/match.c b/match.c
index 81d7df95..53177865 100644
--- a/match.c
+++ b/match.c
@@ -47,6 +47,8 @@
int output_produced;
+val mingap_k, maxgap_k, gap_k, times_k, lines_k;
+
static void debugf(val fmt, ...)
{
if (opt_loglevel >= 2) {
@@ -1306,71 +1308,110 @@ repeat_spec_same_data:
} else if (sym == collect_s) {
val coll_spec = second(first_spec);
val until_spec = third(first_spec);
+ val args = fourth(first_spec);
val bindings_coll = nil;
+ val max = getplist(args, maxgap_k);
+ val min = getplist(args, mingap_k);
+ val gap = getplist(args, gap_k);
+ val times = getplist(args, times_k);
+ val lines = getplist(args, lines_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;
+ cnum timescounter = 0, linescounter = 0;
+ cnum ctimes = nump(times) ? c_num(times) : 0;
+ cnum clines = nump(lines) ? c_num(lines) : 0;
val iter;
+ if (gap && (max || min))
+ sem_error(spec_linenum, lit("collect: cannot mix :gap with :mingap or :maxgap"), nao);
+
+ if ((times && ctimes == 0) || (lines && clines == 0)) {
+ if ((spec = rest(spec)) == nil)
+ break;
+
+ goto repeat_spec_same_data;
+ }
+
uw_block_begin(nil, result);
result = t;
while (data) {
- cons_bind (new_bindings, success,
- match_files(coll_spec, files, bindings,
- data, num(data_lineno)));
+ if ((gap || min) && mincounter < cmin)
+ goto next_collect;
+
+ if (lines && linescounter++ >= clines)
+ break;
- /* Until clause sees un-collated bindings from collect. */
- if (until_spec)
{
- cons_bind (discarded_bindings, success,
- match_files(until_spec, files, new_bindings,
+ cons_bind (new_bindings, success,
+ match_files(coll_spec, files, bindings,
data, num(data_lineno)));
- if (success) {
- (void) discarded_bindings;
- break;
+ /* Until clause sees un-collated bindings from collect. */
+ if (until_spec)
+ {
+ cons_bind (discarded_bindings, success,
+ match_files(until_spec, files, new_bindings,
+ data, num(data_lineno)));
+
+ if (success) {
+ (void) discarded_bindings;
+ break;
+ }
}
- }
- if (success) {
- debuglf(spec_linenum, lit("collect matched ~a:~a"),
- first(files), num(data_lineno), nao);
+ if (success) {
+ debuglf(spec_linenum, lit("collect matched ~a:~a"),
+ first(files), num(data_lineno), nao);
- for (iter = new_bindings; iter && iter != bindings;
- iter = cdr(iter))
- {
- val binding = car(iter);
- val existing = assoc(bindings_coll, car(binding));
+ for (iter = new_bindings; iter && iter != bindings;
+ iter = cdr(iter))
+ {
+ val binding = car(iter);
+ 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)));
+ }
}
- }
- if (success) {
- if (consp(success)) {
- cons_bind (new_data, new_line, success);
- cnum new_lineno = c_num(new_line);
+ if (success) {
+ if (consp(success)) {
+ cons_bind (new_data, new_line, success);
+ cnum new_lineno = c_num(new_line);
- bug_unless (new_lineno >= data_lineno);
+ bug_unless (new_lineno >= data_lineno);
- if (new_lineno == data_lineno) {
- new_data = cdr(new_data);
- new_lineno++;
- }
+ if (new_lineno == data_lineno) {
+ new_data = cdr(new_data);
+ new_lineno++;
+ }
- debuglf(spec_linenum, lit("collect advancing from line ~a to ~a"),
- num(data_lineno), num(new_lineno), nao);
+ debuglf(spec_linenum, lit("collect advancing from line ~a to ~a"),
+ num(data_lineno), num(new_lineno), nao);
- data = new_data;
- data_lineno = new_lineno;
- *car_l(success) = nil;
+ data = new_data;
+ data_lineno = new_lineno;
+ *car_l(success) = nil;
+
+ if (times && ++timescounter >= ctimes)
+ break;
+ } else {
+ debuglf(spec_linenum, lit("collect consumed entire file"), nao);
+ data = nil;
+ }
+ mincounter = 0;
+ maxcounter = 0;
} else {
- debuglf(spec_linenum, lit("collect consumed entire file"), nao);
- data = nil;
+ next_collect:
+ mincounter++;
+ if ((gap || max) && ++maxcounter > cmax)
+ break;
+ data_lineno++;
+ data = rest(data);
}
- } else {
- data = rest(data);
- data_lineno++;
}
}
@@ -1911,3 +1952,12 @@ int extract(val spec, val files, val predefined_bindings)
return success ? 0 : EXIT_FAILURE;
}
+
+void match_init(void)
+{
+ mingap_k = intern(lit("mingap"), keyword_package);
+ maxgap_k = intern(lit("maxgap"), keyword_package);
+ gap_k = intern(lit("gap"), keyword_package);
+ times_k = intern(lit("times"), keyword_package);
+ lines_k = intern(lit("lines"), keyword_package);
+}