From 8cdbb92688207d0d9f3bcd37279f89a2cbcdf7a3 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 6 Jan 2012 15:39:33 -0800 Subject: * match.c (v_gather): Implemented until/last clause. * parser.y (gather_parts, additional_gather_parts): New nonterminals. (gather_clause): Syntax refactored for until/last clause. * txr.1: Updated. --- ChangeLog | 9 +++++++++ match.c | 28 ++++++++++++++++++++++++++++ parser.y | 23 +++++++++++++++++++++-- txr.1 | 16 ++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d59677a1..b179ae08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-01-06 Kaz Kylheku + + * match.c (v_gather): Implemented until/last clause. + + * parser.y (gather_parts, additional_gather_parts): New nonterminals. + (gather_clause): Syntax refactored for until/last clause. + + * txr.1: Updated. + 2012-01-02 Kaz Kylheku * eval.c (eval_init): Fix regression introduced in diff --git a/match.c b/match.c index 044e1300..f37aabdf 100644 --- a/match.c +++ b/match.c @@ -2312,6 +2312,7 @@ static val v_gather(match_files_ctx *c) spec_bind (specline, first_spec, c->spec); val specs = copy_list(second(first_spec)); val args = third(first_spec); + val until_last = fourth(first_spec); val vars = vars_to_bindings(specline, getplist(args, vars_k), c->bindings); while (specs && c->data) { @@ -2319,6 +2320,7 @@ static val v_gather(match_files_ctx *c) val max_line = zero; val max_data = nil; val iter, next; + val orig_bindings = c->bindings; for (iter = specs, next = cdr(iter); iter != nil; iter = next, next = cdr(iter)) { val nested_spec = first(iter); @@ -2341,6 +2343,32 @@ static val v_gather(match_files_ctx *c) } } + if (until_last) + { + cons_bind (sym, ul_spec, until_last); + cons_bind (until_last_bindings, success, + match_files(mf_spec(*c, ul_spec))); + + if (success) { + debuglf(specline, lit("until/last matched ~a:~a"), + first(c->files), c->data_lineno, nao); + /* Until discards bindings and position, last keeps them. */ + if (sym == last_s) { + val last_bindings = set_diff(until_last_bindings, c->bindings, eq_f, nil); + c->bindings = nappend2(last_bindings, orig_bindings); + + if (success == t) { + c->data = t; + } else { + cons_bind (new_data, new_line, success); + c->data = new_data; + c->data_lineno = new_line; + } + } + break; + } + } + specs = new_specs; if (consp(max_data)) { diff --git a/parser.y b/parser.y index c6e53276..21571920 100644 --- a/parser.y +++ b/parser.y @@ -82,7 +82,7 @@ static val parsed_spec; %type spec clauses clauses_opt clause %type all_clause some_clause none_clause maybe_clause %type cases_clause choose_clause gather_clause collect_clause until_last -%type clause_parts additional_parts +%type clause_parts additional_parts gather_parts additional_gather_parts %type output_clause define_clause try_clause catch_clauses_opt %type line elems_opt elems clause_parts_h additional_parts_h %type text texts elem var var_op meta_expr vector @@ -208,11 +208,23 @@ choose_clause : CHOOSE exprs_opt ')' ; gather_clause : GATHER exprs_opt ')' - newl clause_parts { $$ = list(gather_s, + newl gather_parts + END newl { $$ = list(gather_s, append2(mapcar(curry_12_1(func_n2(cons), nil), first($5)), rest($5)), $2, nao); rl($$, num($1)); } + + | GATHER exprs_opt ')' + newl gather_parts + until_last newl + clauses + END newl { $$ = list(gather_s, + append2(mapcar(curry_12_1(func_n2(cons), nil), + first($5)), rest($5)), + $2, cons(cdr($6), $8), nao); + rl($$, num($1)); } + | GATHER exprs_opt ')' newl error { $$ = nil; yybadtoken(yychar, @@ -222,6 +234,13 @@ gather_clause : GATHER exprs_opt ')' yyerror("empty gather clause"); } ; +gather_parts : clauses additional_gather_parts { $$ = cons($1, $2); } + ; + +additional_gather_parts : AND newl clauses additional_gather_parts { $$ = cons($3, $4); } + | OR newl clauses additional_parts { $$ = cons($3, $4); } + | /* empty */ { $$ = nil; } + ; collect_clause : COLLECT exprs_opt ')' newl clauses END newl { $$ = list(collect_s, diff --git a/txr.1 b/txr.1 index 8ba7afaf..69f1cc5e 100644 --- a/txr.1 +++ b/txr.1 @@ -1829,6 +1829,14 @@ The syntax follows this pattern Of course the multi-line clauses are optional. The gather directive takes keyword parameters, see below. +Similarly to @(collect), @(gather) has an optional until/last clause: + + @(gather) + ... + @(until) + ... + @(end) + How gather works is that the text is searched for matches for the single line and multi-line queries. The clauses are applied in the order in which they appear. Whenever one of the clauses matches, any bindings it produces are retained and @@ -1849,6 +1857,14 @@ order: SHELL=@SHELL @(end) +If the until or last clause is present and a match occurs, then the matches +from the other clauses are discarded and the gather terminates. The difference +between until and last is that any bindings bindings established in last are +retained, and the input position is advanced past the matched material. +The until/last clause has visibility to bindings established in the +previous clauses in that same iteration, even though those bindings +end up thrown away. + .SS Gather Keyword Parameters The gather diretive accepts the keyword parameter :vars. The argument to vars is a list -- cgit v1.2.3