summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-12-26 20:14:13 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-12-26 20:14:13 -0800
commit837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4 (patch)
tree51014445b28a04de955cbdc8bd251538e464f8c0 /match.c
parent5335d788dc601a50fc26319d39b21bdcaf1457b6 (diff)
downloadtxr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.tar.gz
txr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.tar.bz2
txr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.zip
TXR quasiliterals and output vars treated as Lisp.
* eval.c (format_field): Function moved here from match.c, along with the introduction of a new behavior: if a meta-expr occurs among the modifiers, its constituent expression is evaluated in its place. This allows for @{a @[expr]} which was previously not allowed in Lisp quasiliterals, but worked in TXR quasiliterals due to the treatment of @ by txeval. (subst_vars): Static function turns external, so code in match.c can call it instead of the subst_vars in that module. For that purpose, it needs to take a filter argument and process filters, like the match.c subst_vars. (op_quasi_lit): Pass nil as filter argument to subst_vars. * eval.h (format_field, subst_vars): Declared. * match.c (format_field): Function removed, moved to eval.c and slightly changed. (subst_vars): Renamed to tx_subst_vars. By default, now just a wrapper for subst_vars. In compatibility mode, invokes the old logic. (do_txeval, do_output_line): Call tx_subst_vars rather than subst_vars. * match.h (format_field): Declaration removed. * parser.y (expr): Grammar production removed: no longer referenced. (o_var): Braced variable case now parsed as n_expr, and expanded as expr by default, since this is Lisp now. In compatibility mode, expanded using expand_meta. Also SYMTOK case must be subject to expansion; an output var can now be a symbol macro. (expand_meta): Expand a quasi-literal as Lisp, except in compatibility mode. * txr.1: Bit of a documentation update. Existing doc isn't totally clear.
Diffstat (limited to 'match.c')
-rw-r--r--match.c216
1 files changed, 69 insertions, 147 deletions
diff --git a/match.c b/match.c
index 999d971b..68f228ec 100644
--- a/match.c
+++ b/match.c
@@ -1384,164 +1384,86 @@ static val match_line_completely(match_line_ctx c)
return result;
}
-
-val format_field(val obj, val modifier, val filter, val eval_fun)
-{
- val n = zero, sep = lit(" ");
- val plist = nil;
- val str;
-
- for (; modifier; pop(&modifier)) {
- val item = first(modifier);
- if (regexp(item)) {
- uw_throw(query_error_s, lit("bad field format: regex modifier in output"));
- } else if (keywordp(item)) {
- plist = modifier;
- break;
- } else if (consp(item) && car(item) == dwim_s) {
- val arg_expr = second(item);
-
- if (consp(arg_expr) && car(arg_expr) == range_s) {
- val from = funcall1(eval_fun, second(arg_expr));
- val to = funcall1(eval_fun, third(arg_expr));
-
- obj = sub(obj, from, to);
- } else {
- val arg = funcall1(eval_fun, arg_expr);
- if (bignump(arg) || fixnump(arg)) {
- obj = ref(obj, arg);
- } else if (rangep(arg)) {
- obj = sub(obj, from(arg), to(arg));
- } else {
- uw_throwf(query_error_s, lit("format_field: bad index: ~s"),
- arg, nao);
- }
- }
- } else {
- val v = funcall1(eval_fun, item);
- if (fixnump(v))
- n = v;
- else if (stringp(v))
- sep = v;
- else
- uw_throwf(query_error_s,
- lit("bad field format: bad modifier object: ~s"),
- item, nao);
- }
- }
-
- if (listp(obj))
- str = cat_str(mapcar(func_n1(tostringp), obj), sep);
- else
- str = if3(stringp(obj), obj, tostringp(obj));
-
- {
- val filter_sym = getplist(plist, filter_k);
-
- if (filter_sym) {
- filter = get_filter(filter_sym);
-
- if (!filter) {
- uw_throwf(query_error_s,
- lit("bad field format: ~s specifies unknown filter"),
- filter_sym, nao);
- }
- }
-
- if (filter)
- str = filter_string_tree(filter, str);
- }
-
- {
- val right = lt(n, zero);
- val width = if3(lt(n, zero), neg(n), n);
- val diff = minus(width, length_str(str));
-
- if (le(diff, zero))
- return str;
-
- if (ge(length_str(str), width))
- return str;
-
- {
- val padding = mkstring(diff, chr(' '));
-
- return if3(right,
- cat_str(list(padding, str, nao), nil),
- cat_str(list(str, padding, nao), nil));
- }
- }
-}
-
-static val subst_vars(val spec, val bindings, val filter)
+static val tx_subst_vars(val spec, val bindings, val filter)
{
- list_collect_decl(out, iter);
- uw_env_begin;
+ if (opt_compat && opt_compat <= 128) {
+ list_collect_decl(out, iter);
+ uw_env_begin;
- uw_set_match_context(cons(spec, bindings));
+ uw_set_match_context(cons(spec, bindings));
- while (spec) {
- val elem = first(spec);
+ while (spec) {
+ val elem = first(spec);
- if (consp(elem)) {
- val sym = first(elem);
+ if (consp(elem)) {
+ val sym = first(elem);
- if (sym == var_s) {
- val expr = second(elem);
- val modifiers = third(elem);
- val str = txeval(spec, expr, bindings);
+ if (sym == var_s) {
+ val expr = second(elem);
+ val modifiers = third(elem);
+ val str = txeval(spec, expr, bindings);
- /* If the object is a list, we let format_field deal with the
- conversion to text, because the modifiers influence how
- it is done. */
- if (!stringp(str) && !listp(str))
- str = tostringp(str);
+ /* If the object is a list, we let format_field deal with the
+ conversion to text, because the modifiers influence how
+ it is done. */
+ if (!stringp(str) && !listp(str))
+ str = tostringp(str);
- if (modifiers) {
- spec = cons(format_field(str, modifiers, filter,
- curry_123_2(func_n3(txeval), spec, bindings)),
- rest(spec));
- } else {
- if (listp(str))
- str = cat_str(mapcar(func_n1(tostringp), str), lit(" "));
+ if (modifiers) {
+ spec = cons(format_field(str, modifiers, filter,
+ curry_123_2(func_n3(txeval), spec, bindings)),
+ rest(spec));
+ } else {
+ if (listp(str))
+ str = cat_str(mapcar(func_n1(tostringp), str), lit(" "));
- spec = cons(filter_string_tree(filter, str), rest(spec));
- }
+ spec = cons(filter_string_tree(filter, str), rest(spec));
+ }
- continue;
- } else if (sym == quasi_s) {
- val nested = subst_vars(rest(elem), bindings, filter);
- iter = list_collect_append(iter, nested);
- spec = cdr(spec);
- continue;
- } else if (sym == expr_s) {
- if (opt_compat && opt_compat < 100) {
- val result = eval_with_bindings(rest(elem), spec, bindings, elem);
- spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec));
continue;
+ } else if (sym == quasi_s) {
+ val nested = tx_subst_vars(rest(elem), bindings, filter);
+ iter = list_collect_append(iter, nested);
+ spec = cdr(spec);
+ continue;
+ } else if (sym == expr_s) {
+ if (opt_compat && opt_compat < 100) {
+ val result = eval_with_bindings(rest(elem), spec, bindings, elem);
+ spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec));
+ continue;
+ } else {
+ val str = eval_with_bindings(rest(elem), spec, bindings, elem);
+ if (listp(str))
+ str = cat_str(mapcar(func_n1(tostringp), str), lit(" "));
+ else if (!stringp(str))
+ str = tostringp(str);
+ spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec));
+ continue;
+ }
} else {
- val str = eval_with_bindings(rest(elem), spec, bindings, elem);
- if (listp(str))
- str = cat_str(mapcar(func_n1(tostringp), str), lit(" "));
- else if (!stringp(str))
- str = tostringp(str);
- spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec));
+ val nested = tx_subst_vars(elem, bindings, filter);
+ iter = list_collect_append(iter, nested);
+ spec = cdr(spec);
continue;
}
- } else {
- val nested = subst_vars(elem, bindings, filter);
- iter = list_collect_append(iter, nested);
- spec = cdr(spec);
- continue;
}
+
+ iter = list_collect(iter, elem);
+ spec = cdr(spec);
}
- iter = list_collect(iter, elem);
- spec = cdr(spec);
- }
+ uw_env_end;
+ return out;
+ } else {
+ val saved_de = set_dyn_env(make_env(bindings, nil, nil));
+ val out;
- uw_env_end;
- return out;
+ uw_set_match_context(cons(spec, bindings));
+ out = subst_vars(spec, nil, filter);
+ set_dyn_env(saved_de);
+
+ return out;
+ }
}
static val do_txeval(val spec, val form, val bindings, val allow_unbound)
@@ -1570,12 +1492,12 @@ static val do_txeval(val spec, val form, val bindings, val allow_unbound)
} else if (consp(form)) {
val sym = first(form);
if (sym == quasi_s) {
- ret = cat_str(subst_vars(rest(form), bindings, nil), nil);
+ ret = cat_str(tx_subst_vars(rest(form), bindings, nil), nil);
} else if (sym == quasilist_s) {
val iter;
list_collect_decl (out, tail);
for (iter = rest(form); iter != nil; iter = cdr(iter))
- tail = list_collect(tail, subst_vars(cdr(car(iter)), bindings, nil));
+ tail = list_collect(tail, tx_subst_vars(cdr(car(iter)), bindings, nil));
ret = out;
} else if (sym == var_s) {
ret = eval_with_bindings(second(form), spec, bindings, form);
@@ -1770,8 +1692,8 @@ static void do_output_line(val bindings, val specline, val filter, val out)
val directive = first(elem);
if (directive == var_s) {
- val str = cat_str(subst_vars(cons(elem, nil),
- bindings, filter), nil);
+ val str = cat_str(tx_subst_vars(cons(elem, nil),
+ bindings, filter), nil);
if (str == nil)
sem_error(specline, lit("bad substitution: ~a"),
second(elem), nao);
@@ -1884,8 +1806,8 @@ static void do_output_line(val bindings, val specline, val filter, val out)
format(out, lit("~a"),
eval_with_bindings(rest(elem), elem, bindings, elem), nao);
} else {
- val str = cat_str(subst_vars(cons(elem, nil),
- bindings, filter), nil);
+ val str = cat_str(tx_subst_vars(cons(elem, nil),
+ bindings, filter), nil);
if (str == nil)
sem_error(specline, lit("bad substitution: ~a"),
second(elem), nao);