summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-29 23:28:45 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-29 23:28:45 -0800
commit0b81b8b4c39b6c60cbbe8de5a6a785beb43c3dbb (patch)
treefcdcd0614874951ad5d9521f3cc75febd765302a /match.c
parent3e09c38f75b087e583abb30762a9a251b8f424f9 (diff)
downloadtxr-0b81b8b4c39b6c60cbbe8de5a6a785beb43c3dbb.tar.gz
txr-0b81b8b4c39b6c60cbbe8de5a6a785beb43c3dbb.tar.bz2
txr-0b81b8b4c39b6c60cbbe8de5a6a785beb43c3dbb.zip
New functionality: mod and modlast directives in repeat and rep.
* eval.c (eval_init): Use new symbol variable mod_s instead of calling intern. * match.c (mod_s, modlast_s): Symbol variables defined. (do_output_line): mod and modlast directives implemented under rep. (do_output): likewise under repeat. (syms_init): Initialize new symbol variables. * match.h (mod_s, modlast_s): Declared. * parser.l (MOD, MODLAST): Parse new token types. * parser.y (MOD, MODLAST): New tokens. (repeat_parts_opt, rep_parts_opt): New syntax. (repeat_rep_helper): Handle mod and modlast syntax. * txr.1: Updated. * txr.vim: Updated.
Diffstat (limited to 'match.c')
-rw-r--r--match.c122
1 files changed, 107 insertions, 15 deletions
diff --git a/match.c b/match.c
index c53d16b0..e87b7496 100644
--- a/match.c
+++ b/match.c
@@ -55,7 +55,7 @@ int opt_arraydims = 1;
val decline_k, next_spec_k, repeat_spec_k;
val mingap_k, maxgap_k, gap_k, mintimes_k, maxtimes_k, times_k;
val lines_k, chars_k;
-val text_s, choose_s, gather_s, do_s;
+val text_s, choose_s, gather_s, do_s, mod_s, modlast_s;
val longest_k, shortest_k, greedy_k;
val vars_k, resolve_k;
val append_k, into_k, var_k, list_k, string_k, env_k;
@@ -1533,11 +1533,14 @@ static void do_output_line(val bindings, val specline, val filter, val out)
second(elem), nao);
put_string(out, str);
} else if (directive == rep_s) {
- val main_clauses = second(elem);
- val single_clauses = third(elem);
- val first_clauses = fourth(elem);
- val last_clauses = fifth(elem);
- val empty_clauses = sixth(elem);
+ val clauses = cdr(elem);
+ val main_clauses = pop(&clauses);
+ val single_clauses = pop(&clauses);
+ val first_clauses = pop(&clauses);
+ val last_clauses = pop(&clauses);
+ val empty_clauses = pop(&clauses);
+ val mod_clauses = pop(&clauses);
+ val modlast_clauses = pop(&clauses);
val bind_cp = extract_bindings(bindings, elem);
val max_depth = reduce_left(func_n2(max2),
bind_cp, zero,
@@ -1559,8 +1562,49 @@ static void do_output_line(val bindings, val specline, val filter, val out)
if (i == 0 && first_clauses) {
do_output_line(bind_a, first_clauses, filter, out);
- } else if (i == c_num(max_depth) - 1 && last_clauses) {
- do_output_line(bind_a, last_clauses, filter, out);
+ } else if (i == c_num(max_depth) - 1 &&
+ (last_clauses || modlast_clauses)) {
+ if (modlast_clauses) {
+ val iter;
+ list_collect_decl (active_mods, ptail);
+
+ for (iter = modlast_clauses; iter != nil; iter = cdr(iter)) {
+ val clause = car(iter);
+ val args = first(clause);
+ val n = txeval(args, first(args), bind_a);
+ val m = txeval(args, second(args), bind_a);
+
+ if (eql(mod(num_fast(i), m), n))
+ list_collect_append (ptail, rest(clause));
+ }
+
+ if (active_mods)
+ do_output_line(bind_a, active_mods, filter, out);
+ else if (last_clauses)
+ do_output_line(bind_a, last_clauses, filter, out);
+ else
+ goto mod_fallback;
+ } else {
+ do_output_line(bind_a, last_clauses, filter, out);
+ }
+ } else if (mod_clauses) mod_fallback: {
+ val iter;
+ list_collect_decl (active_mods, ptail);
+
+ for (iter = mod_clauses; iter != nil; iter = cdr(iter)) {
+ val clause = car(iter);
+ val args = first(clause);
+ val n = txeval(args, first(args), bind_a);
+ val m = txeval(args, second(args), bind_a);
+
+ if (eql(mod(num_fast(i), m), n))
+ list_collect_append (ptail, rest(clause));
+ }
+
+ if (active_mods)
+ do_output_line(bind_a, active_mods, filter, out);
+ else
+ do_output_line(bind_a, main_clauses, filter, out);
} else {
do_output_line(bind_a, main_clauses, filter, out);
}
@@ -1600,11 +1644,14 @@ static void do_output(val bindings, val specs, val filter, val out)
val sym = first(first_elem);
if (sym == repeat_s) {
- val main_clauses = second(first_elem);
- val single_clauses = third(first_elem);
- val first_clauses = fourth(first_elem);
- val last_clauses = fifth(first_elem);
- val empty_clauses = sixth(first_elem);
+ val clauses = cdr(first_elem);
+ val main_clauses = pop(&clauses);
+ val single_clauses = pop(&clauses);
+ val first_clauses = pop(&clauses);
+ val last_clauses = pop(&clauses);
+ val empty_clauses = pop(&clauses);
+ val mod_clauses = pop(&clauses);
+ val modlast_clauses = pop(&clauses);
val bind_cp = extract_bindings(bindings, first_elem);
val max_depth = reduce_left(func_n2(max2),
bind_cp, zero,
@@ -1626,8 +1673,50 @@ static void do_output(val bindings, val specs, val filter, val out)
if (i == 0 && first_clauses) {
do_output(bind_a, first_clauses, filter, out);
- } else if (i == c_num(max_depth) - 1 && last_clauses) {
- do_output(bind_a, last_clauses, filter, out);
+ } else if (i == c_num(max_depth) - 1 &&
+ (last_clauses || modlast_clauses))
+ {
+ if (modlast_clauses) {
+ val iter;
+ list_collect_decl (active_mods, ptail);
+
+ for (iter = modlast_clauses; iter != nil; iter = cdr(iter)) {
+ val clause = car(iter);
+ val args = first(clause);
+ val n = txeval(args, first(args), bind_a);
+ val m = txeval(args, second(args), bind_a);
+
+ if (eql(mod(num_fast(i), m), n))
+ list_collect_append (ptail, rest(clause));
+ }
+
+ if (active_mods)
+ do_output(bind_a, active_mods, filter, out);
+ else if (last_clauses)
+ do_output(bind_a, last_clauses, filter, out);
+ else
+ goto mod_fallback;
+ } else {
+ do_output(bind_a, last_clauses, filter, out);
+ }
+ } else if (mod_clauses) mod_fallback: {
+ val iter;
+ list_collect_decl (active_mods, ptail);
+
+ for (iter = mod_clauses; iter != nil; iter = cdr(iter)) {
+ val clause = car(iter);
+ val args = first(clause);
+ val n = txeval(args, first(args), bind_a);
+ val m = txeval(args, second(args), bind_a);
+
+ if (eql(mod(num_fast(i), m), n))
+ list_collect_append (ptail, rest(clause));
+ }
+
+ if (active_mods)
+ do_output(bind_a, active_mods, filter, out);
+ else
+ do_output(bind_a, main_clauses, filter, out);
} else {
do_output(bind_a, main_clauses, filter, out);
}
@@ -3323,6 +3412,9 @@ static void syms_init(void)
filter_s = intern(lit("filter"), user_package);
noval_s = intern(lit("noval"), system_package);
+
+ mod_s = intern(lit("mod"), system_package);
+ modlast_s = intern(lit("modlast"), system_package);
}
static void dir_tables_init(void)