summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--match.c5
-rw-r--r--parser.y66
-rw-r--r--tests/008/empty-clauses.expected6
-rw-r--r--tests/008/empty-clauses.txr18
5 files changed, 88 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index dff5c576..b4bbe9b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
2012-02-26 Kaz Kylheku <kaz@kylheku.com>
+ Fixing long-time (pre-GIT) bug. The object (nil) was stupidly used to
+ represent empty optional output clauses, distinguishing them from
+ missing clauses. This creates an ambiguity, so that an @(output)
+ block which puts out a single empty line is treated as empty.
+ Present but empty clauses are now represented by t.
+
+ * match.c (do_output_line): Check for t and bail.
+ (do_output): Check for t instead of (nil) and bail.
+
+ * parser.y (o_elems_opt2): Nonterminal deleted.
+ (out_clauses_opt): Empty case generates nil.
+ (req_parts_opt): o_elems_opt2 replaced by o_elems_opt.
+ (repeat_rep_helper): Function now keeps track of which
+ clauses were specified. For those that were specified, but
+ empty, it substitutes t.
+
+ * tests/008/empty-clauses.expected: New file.
+
+ * tests/008/empty-clauses.txr: New file.
+
+2012-02-26 Kaz Kylheku <kaz@kylheku.com>
+
Bug #35625
* parser.l (BSCHR, BSYM, BTOK): New lexical definitions.
diff --git a/match.c b/match.c
index e8fc7f65..5dda9602 100644
--- a/match.c
+++ b/match.c
@@ -1559,6 +1559,9 @@ static val extract_bindings(val bindings, val output_spec)
static void do_output_line(val bindings, val specline, val filter, val out)
{
+ if (specline == t)
+ return;
+
for (; specline; specline = rest(specline)) {
val elem = first(specline);
@@ -1689,7 +1692,7 @@ static void do_output_line(val bindings, val specline, val filter, val out)
static void do_output(val bindings, val specs, val filter, val out)
{
- if (equal(specs, null_list))
+ if (specs == t)
return;
for (; specs; specs = cdr(specs)) {
diff --git a/parser.y b/parser.y
index e5f06b54..8df15ae5 100644
--- a/parser.y
+++ b/parser.y
@@ -88,7 +88,7 @@ static val parsed_spec;
%type <val> text texts elem var var_op modifiers meta_expr vector
%type <val> list exprs exprs_opt expr out_clauses out_clauses_opt out_clause
%type <val> repeat_clause repeat_parts_opt o_line
-%type <val> o_elems_opt o_elems_opt2 o_elems o_elem o_var rep_elem rep_parts_opt
+%type <val> o_elems_opt o_elems o_elem o_var rep_elem rep_parts_opt
%type <val> regex lisp_regex regexpr regbranch
%type <val> regterm regclass regclassterm regrange
%type <val> strlit chrlit quasilit quasi_items quasi_item litchars
@@ -532,7 +532,7 @@ repeat_parts_opt : SINGLE newl
out_clauses_opt : out_clauses { $$ = $1; }
- | /* empty */ { $$ = null_list; }
+ | /* empty */ { $$ = nil; }
o_line : o_elems_opt '\n' { $$ = $1; }
;
@@ -542,11 +542,6 @@ o_elems_opt : o_elems { $$ = o_elems_transform($1);
| { $$ = nil; }
;
-o_elems_opt2 : o_elems { $$ = o_elems_transform($1);
- rl($$, num(lineno)); }
- | { $$ = null_list; }
- ;
-
o_elems : o_elem { $$ = cons($1, nil); }
| o_elem o_elems { $$ = cons($1, $2); }
;
@@ -570,25 +565,25 @@ rep_elem : REP exprs_opt ')' o_elems_opt
yybadtoken(yychar, lit("rep clause")); }
;
-rep_parts_opt : SINGLE o_elems_opt2
+rep_parts_opt : SINGLE o_elems_opt
rep_parts_opt { $$ = cons(cons(single_s, $2), $3);
rl($$, num($1)); }
- | FIRST o_elems_opt2
+ | FIRST o_elems_opt
rep_parts_opt { $$ = cons(cons(first_s, $2), $3);
rl($$, num($1)); }
- | LAST o_elems_opt2
+ | LAST o_elems_opt
rep_parts_opt { $$ = cons(cons(last_s, $2), $3);
rl($$, num($1)); }
- | EMPTY o_elems_opt2
+ | EMPTY o_elems_opt
rep_parts_opt { $$ = cons(cons(empty_s, $2), $3);
rl($$, num($1)); }
| MOD exprs_opt ')'
- o_elems_opt2
+ o_elems_opt
rep_parts_opt { $$ = cons(cons(mod_s,
cons($2, $4)), $5);
rl($$, num($1)); }
| MODLAST exprs_opt ')'
- o_elems_opt2
+ o_elems_opt
rep_parts_opt { $$ = cons(cons(modlast_s,
cons($2, $4)), $5);
rl($$, num($1)); }
@@ -857,12 +852,13 @@ litchars : LITCHAR { $$ = cons(chr($1), nil); }
static val repeat_rep_helper(val sym, val args, val main, val parts)
{
- val single_parts = nil;
- val first_parts = nil;
- val last_parts = nil;
- val empty_parts = nil;
- val mod_parts = nil;
- val modlast_parts = nil;
+ uses_or2;
+ val single_parts = nil, single_parts_p = nil;
+ val first_parts = nil, first_parts_p = nil;
+ val last_parts = nil, last_parts_p = nil;
+ 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 iter;
for (iter = parts; iter != nil; iter = cdr(iter)) {
@@ -870,25 +866,39 @@ static val repeat_rep_helper(val sym, val args, val main, val parts)
val sym = car(part);
val clauses = copy_list(cdr(part));
- if (sym == single_s)
+ if (sym == single_s) {
single_parts = nappend2(single_parts, clauses);
- else if (sym == first_s)
+ single_parts_p = t;
+ } else if (sym == first_s) {
first_parts = nappend2(first_parts, clauses);
- else if (sym == last_s)
+ first_parts_p = t;
+ } else if (sym == last_s) {
last_parts = nappend2(last_parts, clauses);
- else if (sym == empty_s)
+ last_parts_p = t;
+ } else if (sym == empty_s) {
empty_parts = nappend2(empty_parts, clauses);
- else if (sym == mod_s)
+ empty_parts_p = t;
+ } else if (sym == mod_s) {
mod_parts = cons(clauses, mod_parts);
- else if (sym == modlast_s)
+ mod_parts_p = t;
+ } else if (sym == modlast_s) {
modlast_parts = cons(clauses, modlast_parts);
- else
+ modlast_parts_p = t;
+ } else {
abort();
+ }
}
+ single_parts = or2(single_parts, single_parts_p);
+ first_parts = or2(first_parts, first_parts_p);
+ last_parts = or2(last_parts, last_parts_p);
+ empty_parts = or2(empty_parts, empty_parts_p);
+ 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,
- last_parts, empty_parts,
- nreverse(mod_parts), nreverse(modlast_parts), nao);
+ last_parts, empty_parts, nreverse(mod_parts),
+ nreverse(modlast_parts), nao);
}
static val o_elems_transform(val o_elems)
diff --git a/tests/008/empty-clauses.expected b/tests/008/empty-clauses.expected
new file mode 100644
index 00000000..b0cbdaf5
--- /dev/null
+++ b/tests/008/empty-clauses.expected
@@ -0,0 +1,6 @@
+
+b
+b
+fa
+b
+b
diff --git a/tests/008/empty-clauses.txr b/tests/008/empty-clauses.txr
new file mode 100644
index 00000000..486d42a2
--- /dev/null
+++ b/tests/008/empty-clauses.txr
@@ -0,0 +1,18 @@
+@(bind a ("a" "b"))
+@(output)
+@(repeat)
+@a
+@(first)
+
+@(end)
+@(repeat)
+@a
+@(first)
+@(end)
+@(repeat)
+@a
+@(first)
+f@a
+@(end)
+@(rep)@a@(first)@(end)
+@(end)