diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | match.c | 12 | ||||
-rw-r--r-- | parser.y | 23 | ||||
-rw-r--r-- | txr.1 | 19 |
4 files changed, 59 insertions, 12 deletions
@@ -1,5 +1,22 @@ 2012-05-17 Kaz Kylheku <kaz@kylheku.com> + * match.c (v_collect): Implemented semantics for repeat symbol. + (dir_tables_init): Register dispatch for repeat to v_collect + function. + + * parser.y (collect_repeat): New nonterminal symbol. + (clause): Removed repeat_clause error case because that now clashes + with the syntax in collect_clause. + (collect_clause): Repeat syntax implemented, with help of + collect_repeat. + (out_clause): Error case for collect_clause removed due to + syntactic clash. + + * txr.1: Added mention of @(collect :vars nil) and documented + @(repeat) as the shorthand. + +2012-05-17 Kaz Kylheku <kaz@kylheku.com> + * configure: Do not capture the stderr of GNU Make in the configure step; send it to /dev/null. @@ -2617,6 +2617,7 @@ static val v_gather(match_files_ctx *c) static val v_collect(match_files_ctx *c) { spec_bind (specline, first_spec, c->spec); + val op_sym = first(first_spec); val coll_spec = second(first_spec); val until_last_spec = third(first_spec); val args = fourth(first_spec); @@ -2644,7 +2645,15 @@ static val v_collect(match_files_ctx *c) val iter; if (gap && (max || min)) - sem_error(specline, lit("collect: cannot mix :gap with :mingap or :maxgap"), nao); + sem_error(specline, lit("~s: cannot mix :gap with :mingap or :maxgap"), + op_sym, nao); + + if (op_sym == repeat_s) { + if (have_vars) + sem_error(specline, lit("~s: collect takes :vars, repeat does not"), + op_sym, nao); + have_vars = t; + } vars = vars_to_bindings(specline, vars, c->bindings); @@ -3787,6 +3796,7 @@ static void dir_tables_init(void) sethash(v_directive_table, choose_s, cptr((mem_t *) v_parallel)); sethash(v_directive_table, gather_s, cptr((mem_t *) v_gather)); sethash(v_directive_table, collect_s, cptr((mem_t *) v_collect)); + sethash(v_directive_table, repeat_s, cptr((mem_t *) v_collect)); sethash(v_directive_table, flatten_s, cptr((mem_t *) v_flatten)); sethash(v_directive_table, forget_s, cptr((mem_t *) v_forget_local)); sethash(v_directive_table, local_s, cptr((mem_t *) v_forget_local)); @@ -82,6 +82,7 @@ static val parsed_spec; %type <val> spec clauses clauses_opt clause %type <val> all_clause some_clause none_clause maybe_clause block_clause %type <val> cases_clause choose_clause gather_clause collect_clause until_last +%type <val> collect_repeat %type <val> clause_parts additional_parts gather_parts additional_gather_parts %type <val> output_clause define_clause try_clause catch_clauses_opt %type <val> line elems_opt elems clause_parts_h additional_parts_h @@ -143,8 +144,6 @@ clause : all_clause { $$ = cons($1, nil); rlcp($$, $1); } | try_clause { $$ = cons($1, nil); rlcp($$, $1); } | output_clause { $$ = cons($1, nil); rlcp($$, $1); } | line { $$ = $1; } - | repeat_clause { $$ = nil; - yyerror("repeat outside of output"); } ; all_clause : ALL newl clause_parts { $$ = list(all_s, $3, nao); @@ -260,19 +259,19 @@ additional_gather_parts : AND newl clauses additional_gather_parts { $$ = c | /* empty */ { $$ = nil; } ; -collect_clause : COLLECT exprs_opt ')' newl - clauses END newl { $$ = list(collect_s, +collect_clause : collect_repeat exprs_opt ')' newl + clauses END newl { $$ = list(car($1), $5, nil, $2, nao); - rl($$, num($1)); } - | COLLECT exprs_opt ')' + rl($$, cdr($1)); } + | collect_repeat exprs_opt ')' newl clauses until_last - newl clauses END newl { $$ = list(collect_s, $5, + newl clauses END newl { $$ = list(car($1), $5, cons(cdr($6), $8), $2, nao); - rl($$, num($1)); + rl($$, cdr($1)); rl($8, car($6)); } - | COLLECT exprs_opt ')' + | collect_repeat exprs_opt ')' newl error { $$ = nil; if (yychar == UNTIL || yychar == END || @@ -283,6 +282,10 @@ collect_clause : COLLECT exprs_opt ')' newl lit("collect clause")); } ; +collect_repeat : COLLECT { $$ = cons(collect_s, num($1)); } + | REPEAT { $$ = cons(repeat_s, num($1)); } + ; + until_last : UNTIL { $$ = cons(num($1), until_s); } | LAST { $$ = cons(num($1), last_s); } ; @@ -494,8 +497,6 @@ out_clause : repeat_clause { $$ = cons($1, nil); } yyerror("match clause in output"); } | choose_clause { $$ = nil; yyerror("choose clause in output"); } - | collect_clause { $$ = nil; - yyerror("match clause in output"); } | define_clause { $$ = nil; yyerror("match clause in output"); } @@ -2111,6 +2111,13 @@ or with an until or last clause: ... lines of subquery: last clause @(end) +The repeat symbol may be specified instead of collect, which changes +the meaning, see below: + + @(repeat) + ... lines of subquery + @(end) + The subquery is matched repeatedly, starting at the current line. If it fails to match, it is tried starting at the subsequent line. If it matches successfully, it is tried at the line following the @@ -2369,6 +2376,18 @@ an empty list. @a @(end) +The following means: do not allow any variables to propagate out of any +iteration of the collect and therefore collect nothing: + + @(collect :vars nil) + ... + @(end) + +Instead of writing @(collect :vars nil), it is possible to write +@(repeat). @(repeat) takes all collect keywords, except for :vars. +There is a repeat directive used in @(output) clauses; that is +a different repeat directive. + .SS The Coll Directive The coll directive is a kind of miniature version of the collect directive. |