diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-03-16 23:18:25 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-03-16 23:18:25 -0700 |
commit | e84da36197b809c50a0c43cceb5c7b27b3d5733e (patch) | |
tree | 49ea25ca1b9299ae9c5c6b978a05a8d48e552f4b /parser.y | |
parent | c1e94e69d1bea54330bd94371b101828b31e9add (diff) | |
download | txr-e84da36197b809c50a0c43cceb5c7b27b3d5733e.tar.gz txr-e84da36197b809c50a0c43cceb5c7b27b3d5733e.tar.bz2 txr-e84da36197b809c50a0c43cceb5c7b27b3d5733e.zip |
Support binding in @(repeat)/@(rep) :vars.
* match.c (extract_bindings): Check for (var expr) syntax,
evaluate and bind.
* match.h (vars_k): Declared.
* parser.y (expand_repeat_rep_args): New static function.
(repeat_rep_helper): The :counter and :var arguments of
repeat/rep must be macro-expanded, since there can be Lisp
expressions there. This supports the new feature, but also
fixes the bug of :counter (var form) not expanding
form.
* txr.1: Updated documentation about :vars in @(repeat).
Diffstat (limited to 'parser.y')
-rw-r--r-- | parser.y | 48 |
1 files changed, 47 insertions, 1 deletions
@@ -1198,9 +1198,55 @@ static val sym_helper(parser_t *parser, wchar_t *lexeme, val meta_allowed) return leading_at ? rl(list(var_s, sym, nao), num(parser->lineno)) : sym; } +static val expand_repeat_rep_args(val args) +{ + list_collect_decl (out, ptail); + val exp_pair = nil, exp_pairs = nil; + + for (; args; args = cdr(args)) { + val arg = car(args); + + if (consp(arg)) { + if (exp_pairs) { + list_collect_decl (iout, iptail); + for (; arg; arg = cdr(arg)) { + val iarg = car(arg); + if (consp(iarg)) + iptail = list_collect(iptail, list(first(iarg), + expand(second(iarg), nil), + nao)); + else + iptail = list_collect(iptail, iarg); + } + ptail = list_collect(ptail, iout); + } else if (exp_pair) { + ptail = list_collect(ptail, list(first(arg), + expand(second(arg), nil), + nao)); + } else { + ptail = list_collect(ptail, arg); + } + } else if (arg == counter_k) { + exp_pair = t; + ptail = list_collect(ptail, arg); + continue; + } else if (arg == vars_k) { + exp_pairs = t; + ptail = list_collect(ptail, arg); + continue; + } + + exp_pair = exp_pairs = nil; + ptail = list_collect(ptail, arg); + } + + return out; +} + static val repeat_rep_helper(val sym, val args, val main, val parts) { uses_or2; + val exp_args = expand_repeat_rep_args(args); val single_parts = nil, single_parts_p = nil; val first_parts = nil, first_parts_p = nil; val last_parts = nil, last_parts_p = nil; @@ -1244,7 +1290,7 @@ 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); - return list(sym, args, main, single_parts, first_parts, + return list(sym, exp_args, main, single_parts, first_parts, last_parts, empty_parts, nreverse(mod_parts), nreverse(modlast_parts), nao); } |