diff options
-rw-r--r-- | match.c | 61 | ||||
-rw-r--r-- | txr.1 | 47 |
2 files changed, 104 insertions, 4 deletions
@@ -814,6 +814,16 @@ static val h_coll(match_line_ctx *c) val mintimes = txeval(elem, getplist(args, mintimes_k), c->bindings); val maxtimes = txeval(elem, getplist(args, maxtimes_k), c->bindings); val chars = txeval(elem, getplist(args, chars_k), c->bindings); + val counter_spec = getplist(args, counter_k); + val consp_counter = consp(counter_spec); + val counter = if3(consp_counter, first(counter_spec), counter_spec); + val counter_base = if3(consp_counter, + eval_with_bindings(second(counter_spec), + elem, + c->bindings, + counter_spec), zero); + val counter_binding = if2(counter, cons(counter, nil)); + val bindings_with_counter = if2(counter, cons(counter_binding, nil)); val have_vars; val vars = getplist_f(args, vars_k, mkcloc(have_vars)); cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0); @@ -834,6 +844,11 @@ static val h_coll(match_line_ctx *c) have_vars = t; } + if (counter && !bindable(counter)) + sem_error(elem, lit("~s: ~s specified as :counter isn't a bindable symbol"), + op_sym, counter, nao); + + vars = vars_to_bindings(elem, vars, c->bindings); if (((times || maxtimes) && ctimax == 0) || (chars && cchars == 0)) @@ -849,8 +864,20 @@ static val h_coll(match_line_ctx *c) break; { - cons_set (new_bindings, new_pos, - match_line(ml_specline(*c, coll_specline))); + if (counter) { + rplacd(counter_binding, plus(num(timescounter), counter_base)); + rplacd(bindings_with_counter, c->bindings); + cons_set (new_bindings, new_pos, + match_line(ml_bindings_specline(*c, bindings_with_counter, coll_specline))); + + if (!new_bindings) { + rplacd(counter_binding, nil); + new_bindings = bindings_with_counter; + } + } else { + cons_set (new_bindings, new_pos, + match_line(ml_specline(*c, coll_specline))); + } if (until_last_specline) { uses_or2; @@ -2840,6 +2867,16 @@ static val v_collect(match_files_ctx *c) val mintimes = txeval(specline, getplist(args, mintimes_k), c->bindings); val maxtimes = txeval(specline, getplist(args, maxtimes_k), c->bindings); val lines = txeval(specline, getplist(args, lines_k), c->bindings); + val counter_spec = getplist(args, counter_k); + val consp_counter = consp(counter_spec); + val counter = if3(consp_counter, first(counter_spec), counter_spec); + val counter_base = if3(consp_counter, + eval_with_bindings(second(counter_spec), + specline, + c->bindings, + counter_spec), zero); + val counter_binding = if2(counter, cons(counter, nil)); + val bindings_with_counter = if2(counter, cons(counter_binding, nil)); val have_vars; volatile val vars = getplist_f(args, vars_k, mkcloc(have_vars)); cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0); @@ -2867,6 +2904,10 @@ static val v_collect(match_files_ctx *c) have_vars = t; } + if (counter && !bindable(counter)) + sem_error(specline, lit("~s: ~s specified as :counter isn't a bindable symbol"), + op_sym, counter, nao); + vars = vars_to_bindings(specline, vars, c->bindings); if ((times && ctimes == 0) || (lines && clines == 0)) @@ -2884,8 +2925,20 @@ static val v_collect(match_files_ctx *c) break; { - cons_set (new_bindings, success, - match_files(mf_spec(*c, coll_spec))); + if (counter) { + rplacd(counter_binding, plus(num(timescounter), counter_base)); + rplacd(bindings_with_counter, c->bindings); + cons_set (new_bindings, success, + match_files(mf_spec_bindings(*c, coll_spec, bindings_with_counter))); + + if (!new_bindings) { + rplacd(counter_binding, nil); + new_bindings = bindings_with_counter; + } + } else { + cons_set (new_bindings, success, + match_files(mf_spec(*c, coll_spec))); + } /* Until/last clause sees un-collated bindings from collect. */ if (until_last_spec) @@ -5015,6 +5015,53 @@ The behavior of the .code :vars keyword is specified in the following section, "Specifying variables in .codn collect \(dq. + +.meIP :counter >> { variable | >> ( variable << starting-value )} +The +.code :counter +keyword's argument is a variable name symbol, +or a compound expression consisting of a variable name symbol +and an \*(TL expression. +If this keyword argument is specified, then a binding for +.meta variable +is established prior to each repetition of the +.code collect +body, to an integer value representing the repetition count. +By default, repetition counts begin at zero. +If +.meta starting-value +is specified, it must evaluate to a number. This number is +then added to each repetition count, and +.meta variable +takes on the resulting displaced value. + +If there is an existing binding for +.meta variable +prior to the processing of the +.codn collect , +then the variable is shadowed. + +The binding is collected in the same way as other bindings +that are established in the +.code collect +body. + +The repetition count only increments after a successful match. + +The +.code variable +is visible to the +.codn collect 's +.cod3 until / last +clause. If that clause is being processed after a successful match +of the body, then +.meta variable +holds an integer value. If the body fails to match, then the +.cod3 until / last +clause sees a binding for +.code variable +with a value of +.codn nil . .PP .coNP Specifying variables in @ collect |