summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-01-15 20:21:48 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-01-15 20:21:48 -0800
commitef72683bf0d5980f82d85ee0b29392755adcf1ca (patch)
tree5eca7e3e5a4177b505a1f27622b310697e3b7d1f /match.c
parentde2c2b47f9c0858f785cafc276104377a7357630 (diff)
downloadtxr-ef72683bf0d5980f82d85ee0b29392755adcf1ca.tar.gz
txr-ef72683bf0d5980f82d85ee0b29392755adcf1ca.tar.bz2
txr-ef72683bf0d5980f82d85ee0b29392755adcf1ca.zip
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.
Diffstat (limited to 'match.c')
-rw-r--r--match.c43
1 files changed, 36 insertions, 7 deletions
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);