summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-10-06 22:20:16 -0700
committerKaz Kylheku <kaz@kylheku.com>2011-10-06 22:20:16 -0700
commit5ab2b46a0f5d6c73b6e81a0efc47c29d29928966 (patch)
tree3d1c0c229308c7c6da8ee84938124275e3beb814 /match.c
parent9776ad45285a46cacd5fc7288489d374f6480f37 (diff)
downloadtxr-5ab2b46a0f5d6c73b6e81a0efc47c29d29928966.tar.gz
txr-5ab2b46a0f5d6c73b6e81a0efc47c29d29928966.tar.bz2
txr-5ab2b46a0f5d6c73b6e81a0efc47c29d29928966.zip
Extending syntax to allow for @VAR and @(...) forms inside
nested lists. This is in anticipation of future features. * lib.c (expr_s): New symbol variable. (obj_init): expr_s initialized. * lib.h (expr_s): Declared. * match.c (dest_bind): Now takes linenum. Tests for the meta-syntax denoted by the system symbols var_s and expr_s, and throws an error. (eval_form): Similar error checks added. Also, hack: do not add file and line number to an exception which begins with a '(' character; just re-throw it. This suppresses duplicate line number addition when this throw occurs across some nestings. (match_files): Updated calls to dest_bind. * parser.l (yybadtoken): Handle new token kind, METAVAR and METAPAR. (grammar): Refactoring among patterns: TOK broken into SYM and NUM, NTOK introduced, unused NUM_END removed. Rule for @( producing METAPAR in nested state. * parser.y (METAVAR, METAPAR): New tokens. (meta_expr): New nonterminal. (expr): meta_expr and META_VAR productions handled.
Diffstat (limited to 'match.c')
-rw-r--r--match.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/match.c b/match.c
index a3c5b7ed..19b527b5 100644
--- a/match.c
+++ b/match.c
@@ -226,7 +226,7 @@ static val bindable(val obj)
return (obj && symbolp(obj) && obj != t && !keywordp(obj)) ? t : nil;
}
-static val dest_bind(val bindings, val pattern, val value)
+static val dest_bind(val linenum, val bindings, val pattern, val value)
{
if (symbolp(pattern)) {
if (bindable(pattern)) {
@@ -246,9 +246,22 @@ static val dest_bind(val bindings, val pattern, val value)
} else if (consp(pattern)) {
val piter = pattern, viter = value;
+ if (first(pattern) == var_s) {
+ uw_throwf(query_error_s,
+ lit("metavariable @~a syntax cannot be used here"),
+ second(pattern), nao);
+ }
+
+ if (first(pattern) == expr_s) {
+ uw_throwf(query_error_s,
+ lit("the @~s syntax cannot be used here"),
+ rest(pattern), nao);
+ }
+
+
while (consp(piter) && consp(viter))
{
- bindings = dest_bind(bindings, car(piter), car(viter));
+ bindings = dest_bind(linenum, bindings, car(piter), car(viter));
if (bindings == t)
return t;
piter = cdr(piter);
@@ -256,7 +269,7 @@ static val dest_bind(val bindings, val pattern, val value)
}
if (bindable(piter)) {
- bindings = dest_bind(bindings, piter, viter);
+ bindings = dest_bind(linenum, bindings, piter, viter);
if (bindings == t)
return t;
} else {
@@ -823,10 +836,16 @@ static val eval_form(val lineno, val form, val bindings)
} else if (bindable(form)) {
ret = assoc(bindings, form);
} else if (consp(form)) {
- if (car(form) == quasi_s) {
+ if (first(form) == quasi_s) {
ret = cons(t, cat_str(subst_vars(rest(form), bindings, nil), nil));
} else if (regexp(car(form))) {
ret = cons(t, form);
+ } else if (first(form) == var_s) {
+ sem_error(lineno, lit("metavariable @~a syntax cannot be used here"),
+ second(form), nao);
+ } else if (first(form) == expr_s) {
+ sem_error(lineno, lit("the @~s syntax cannot be used here"),
+ rest(form), nao);
} else {
val subforms = mapcar(curry_123_2(func_n3(eval_form),
lineno, bindings), form);
@@ -841,6 +860,12 @@ static val eval_form(val lineno, val form, val bindings)
}
uw_catch (exc_sym, exc) {
+ if (stringp(exc) && !equal(exc, lit("")) &&
+ chr_str(exc, zero) == chr('('))
+ {
+ uw_throw (exc_sym, exc);
+ }
+
sem_error(lineno, lit("~a"), exc, nao);
}
}
@@ -1718,7 +1743,7 @@ repeat_spec_same_data:
val form = second(args);
val val = eval_form(spec_linenum, form, bindings);
- bindings = dest_bind(bindings, pattern, cdr(val));
+ bindings = dest_bind(spec_linenum, bindings, pattern, cdr(val));
if (bindings == t)
return nil;
@@ -1871,7 +1896,8 @@ repeat_spec_same_data:
val value = car(viter);
if (value) {
- bindings = dest_bind(bindings, param, cdr(value));
+ bindings = dest_bind(spec_linenum, bindings,
+ param, cdr(value));
if (bindings == t) {
all_bind = nil;
@@ -2077,7 +2103,8 @@ repeat_spec_same_data:
if (symbolp(arg)) {
val newbind = assoc(new_bindings, param);
if (newbind) {
- bindings = dest_bind(bindings, arg, cdr(newbind));
+ bindings = dest_bind(spec_linenum, bindings,
+ arg, cdr(newbind));
if (bindings == t) {
debuglf(spec_linenum,
lit("binding mismatch on ~a "