summaryrefslogtreecommitdiffstats
path: root/parser.y
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-08-17 21:38:13 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-08-17 21:38:13 -0700
commit8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6 (patch)
treed10f3588a0b1de6c6d1addcf0987904141cd5d78 /parser.y
parent42ba138efa6159e1d0387b8f3c7b3fb1a34721ad (diff)
downloadtxr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.tar.gz
txr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.tar.bz2
txr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.zip
txr: identify output repeat vars at parse time
Up to now the @(repeat) and @(rep) directives have scanned their interior to find output variables. We now hoist that into the parser; the variables are found up-front and integrated into the abstract syntax. This work anticipates doing a more proper job of identifying free variables in Lisp expressions. * match.c (extract_vars): Delete static this function here. It moves into parser.y. (extract_bindings): Don't call extract_vars to obtain the variables occurring in the repeat body. Get it as a new argument, occur_vars. (do_output_line, do_repeat): Extract the new occur_vars element of the abstract syntax node and pass it to extract_bindings. * parser.y (extract_vars): New static function, moved here from match.c. (repeat_rep_helper): Scan over each of the repeat subclauses with extract vars. Catenate the resulting lists together and pass through uniq to squash repeated symbols. Then add the resulting vars as a new element of the returned syntax node.
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y58
1 files changed, 57 insertions, 1 deletions
diff --git a/parser.y b/parser.y
index 97c8f020..d829b4f7 100644
--- a/parser.y
+++ b/parser.y
@@ -1481,6 +1481,53 @@ static val expand_repeat_rep_args(val args)
return out;
}
+static val extract_vars(val output_spec)
+{
+ list_collect_decl (vars, tai);
+
+ if (consp(output_spec)) {
+ val sym = first(output_spec);
+ if (sym == var_s) {
+ val name = second(output_spec);
+ val modifiers = third(output_spec);
+
+ if (bindable(name))
+ tai = list_collect(tai, name);
+ else
+ tai = list_collect_nconc(tai, extract_vars(name));
+
+ for (; modifiers; modifiers = cdr(modifiers)) {
+ val mod = car(modifiers);
+ if (bindable(mod)) {
+ tai = list_collect(tai, mod);
+ } else if (consp(mod)) {
+ val msym = car(mod);
+
+ if (msym == dwim_s) {
+ val arg = second(mod);
+
+ if (bindable(arg)) {
+ tai = list_collect(tai, arg);
+ } else if (consp(arg) && car(arg) == rcons_s) {
+ val f = second(arg);
+ val t = third(arg);
+ if (bindable(f))
+ tai = list_collect(tai, f);
+ if (bindable(t))
+ tai = list_collect(tai, t);
+ }
+ }
+ }
+ }
+ } else if (sym != expr_s) {
+ for (; output_spec; output_spec = cdr(output_spec))
+ tai = list_collect_nconc(tai, extract_vars(car(output_spec)));
+ }
+ }
+
+ return vars;
+}
+
static val repeat_rep_helper(val sym, val args, val main, val parts)
{
uses_or2;
@@ -1491,6 +1538,7 @@ static val repeat_rep_helper(val sym, val args, val main, val parts)
val empty_parts = nil, empty_parts_p = nil;
val mod_parts = nil, mod_parts_p = nil;
val modlast_parts = nil, modlast_parts_p = nil;
+ val occur_vars = nil;
val iter;
for (iter = parts; iter != nil; iter = cdr(iter)) {
@@ -1528,9 +1576,17 @@ static val repeat_rep_helper(val sym, val args, val main, val parts)
mod_parts = or2(nreverse(mod_parts), mod_parts_p);
modlast_parts = or2(nreverse(modlast_parts), modlast_parts_p);
+ occur_vars = extract_vars(main);
+ occur_vars = nappend2(occur_vars, extract_vars(single_parts));
+ occur_vars = nappend2(occur_vars, extract_vars(first_parts));
+ occur_vars = nappend2(occur_vars, extract_vars(last_parts));
+ occur_vars = nappend2(occur_vars, extract_vars(empty_parts));
+ occur_vars = nappend2(occur_vars, extract_vars(mod_parts));
+ occur_vars = uniq(occur_vars);
+
return list(sym, exp_args, main, single_parts, first_parts,
last_parts, empty_parts, nreverse(mod_parts),
- nreverse(modlast_parts), nao);
+ nreverse(modlast_parts), occur_vars, nao);
}
static void process_catch_exprs(val exprs)