From ef72683bf0d5980f82d85ee0b29392755adcf1ca Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 15 Jan 2016 20:21:48 -0800 Subject: New :mandatory keyword in until/last clauses. * match.c (mandatory_k): New keyword variable. (h_coll, v_gather, v_collect): Implement :mandatory logic. (syms_init): Initialize mandatory_k. * parser.l (grammar): The UNTIL and LAST tokens must be matched similarly to collect, without consuming the closing parenthesis, allowing a list of items to be parsed between the symbol and the closure, in the NESTED state. * parser.y (gather_clause, collect_clause, elem, repeat_parts_opt, rep_parts_opt): Adjust to new until/last syntax. In the matching productions, the abstract syntax changes to incorporate the options. In the output productions, we throw an error if options are present. * txr.1: Documented :mandatory for collect, coll and gather. --- match.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'match.c') diff --git a/match.c b/match.c index 22bb3fb5..7d738b6d 100644 --- a/match.c +++ b/match.c @@ -65,7 +65,7 @@ val include_s, close_s, require_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, counter_k; -val named_k, continue_k, finish_k; +val named_k, continue_k, finish_k, mandatory_k; val filter_s; @@ -798,6 +798,9 @@ static val h_coll(match_line_ctx *c) val op_sym = first(elem); val coll_specline = second(elem); val until_last_specline = third(elem); + cons_bind (ul_sym, ul_args, until_last_specline); + cons_bind (ul_opts, spec, ul_args); + val ul_match = nil; val args = fourth(elem); val bindings_coll = nil; val last_bindings = nil; @@ -848,7 +851,6 @@ static val h_coll(match_line_ctx *c) if (until_last_specline) { uses_or2; - cons_bind (sym, spec, until_last_specline); cons_bind (until_last_bindings, until_pos, match_line(ml_bindings_specline(*c, or2(new_bindings, c->bindings), @@ -858,11 +860,12 @@ static val h_coll(match_line_ctx *c) until_pos = minus(until_pos, c->base); LOG_MATCH("until/last", until_pos); - if (sym == last_s) { + if (ul_sym == last_s) { last_bindings = set_diff(until_last_bindings, new_bindings, eq_f, nil); c->pos = until_pos; } + ul_match = t; break; } else { LOG_MISMATCH("until/last"); @@ -940,6 +943,12 @@ next_coll: return nil; } + if (!ul_match && ul_opts && memq(mandatory_k, ul_opts)) { + debuglf(elem, lit("~s didn't match mandatory until/last"), + op_sym, nao); + return nil; + } + if (!bindings_coll) debuglf(elem, lit("nothing was collected"), nao); @@ -2596,6 +2605,9 @@ static val v_gather(match_files_ctx *c) val specs = copy_list(second(first_spec)); val args = third(first_spec); val until_last = fourth(first_spec); + cons_bind (ul_sym, ul_args, until_last); + cons_bind (ul_opts, ul_spec, ul_args); + val ul_match = nil; val have_vars; val vars = vars_to_bindings(specline, getplist_f(args, vars_k, mkcloc(have_vars)), @@ -2631,7 +2643,6 @@ 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))); @@ -2639,7 +2650,7 @@ static val v_gather(match_files_ctx *c) debuglf(specline, lit("until/last matched ~a:~d"), c->curfile, c->data_lineno, nao); /* Until discards bindings and position, last keeps them. */ - if (sym == last_s) { + if (ul_sym == last_s) { val last_bindings = set_diff(until_last_bindings, c->bindings, eq_f, nil); c->bindings = nappend2(last_bindings, orig_bindings); @@ -2651,6 +2662,7 @@ static val v_gather(match_files_ctx *c) c->data_lineno = new_line; } } + ul_match = t; break; } } @@ -2672,6 +2684,11 @@ static val v_gather(match_files_ctx *c) } } + if (!ul_match && ul_opts && memq(mandatory_k, ul_opts)) { + debuglf(specline, lit("gather didn't match mandatory until/last"), nao); + return nil; + } + if (have_vars) { val iter; @@ -2706,6 +2723,9 @@ static val v_collect(match_files_ctx *c) val op_sym = first(first_spec); val coll_spec = second(first_spec); val until_last_spec = third(first_spec); + cons_bind (ul_sym, ul_args, until_last_spec); + cons_bind (ul_opts, ul_spec, ul_args); + val ul_match = nil, accept_jump = t; val args = fourth(first_spec); volatile val bindings_coll = nil; volatile val last_bindings = nil; @@ -2767,7 +2787,6 @@ static val v_collect(match_files_ctx *c) if (until_last_spec) { uses_or2; - cons_bind (sym, ul_spec, until_last_spec); cons_bind (until_last_bindings, success, match_files(mf_spec_bindings(*c, ul_spec, or2(new_bindings, c->bindings)))); @@ -2776,7 +2795,7 @@ static val v_collect(match_files_ctx *c) debuglf(specline, lit("until/last matched ~a:~d"), c->curfile, c->data_lineno, nao); /* Until discards bindings and position, last keeps them. */ - if (sym == last_s) { + if (ul_sym == last_s) { last_bindings = set_diff(until_last_bindings, new_bindings, eq_f, nil); if (success == t) { @@ -2788,6 +2807,7 @@ static val v_collect(match_files_ctx *c) c->data_lineno = new_line; } } + ul_match = t; break; } } @@ -2869,6 +2889,8 @@ next_collect: } } + accept_jump = nil; + uw_block_end; if (!result) { @@ -2882,6 +2904,12 @@ next_collect: return nil; } + if (!ul_match && ul_opts && memq(mandatory_k, ul_opts) && !accept_jump) { + debuglf(specline, lit("~s didn't match mandatory until/last"), + op_sym, nao); + return nil; + } + if (!bindings_coll) debuglf(specline, lit("nothing was collected"), nao); @@ -4076,6 +4104,7 @@ static void syms_init(void) named_k = intern(lit("named"), keyword_package); continue_k = intern(lit("continue"), keyword_package); finish_k = intern(lit("finish"), keyword_package); + mandatory_k = intern(lit("mandatory"), keyword_package); filter_s = intern(lit("filter"), user_package); noval_s = intern(lit("noval"), system_package); -- cgit v1.2.3