summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--match.c52
-rw-r--r--parser.y21
3 files changed, 80 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 3d0554d2..166adc68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2011-09-29 Kaz Kylheku <kaz@kylheku.com>
+ * match.c (match_line): Implemented horizontal all, some,
+ none, maybe and cases directives.
+ (match_files): Recognize horizontal version of these directives
+ by the presence of the extra symbol t and do not process.
+ Also, bugfix in the all directive: not resetting the
+ all_match flag when short circuiting out.
+ * parser.y (clause_parts_h, additional_parts_h): New nonterminals.
+ (elem): New clauses added.
+
+2011-09-29 Kaz Kylheku <kaz@kylheku.com>
+
* match.c (chars_k): New variable.
(match_line): Keyword arguments in coll implemented.
(match_init): chars_k variable initialized.
diff --git a/match.c b/match.c
index 68f05600..0ed7daed 100644
--- a/match.c
+++ b/match.c
@@ -562,6 +562,52 @@ next_coll:
val rev = cons(car(pair), nreverse(cdr(pair)));
bindings = cons(rev, bindings);
}
+ } else if (directive == all_s || directive == some_s ||
+ directive == none_s || directive == maybe_s ||
+ directive == cases_s)
+ {
+ val specs;
+ val all_match = t;
+ val some_match = nil;
+ val max_pos = pos;
+
+ for (specs = rest(rest(elem)); specs != nil; specs = cdr(specs)) {
+ val nested_spec = first(specs);
+ cons_bind (new_bindings, new_pos,
+ match_line(bindings, nested_spec, dataline, pos,
+ spec_lineno, data_lineno, file));
+ if (new_pos) {
+ bindings = new_bindings;
+ some_match = t;
+ if (gt(new_pos, max_pos))
+ max_pos = new_pos;
+ if (directive == cases_s || directive == none_s)
+ break;
+ } else {
+ all_match = nil;
+ if (directive == all_s)
+ break;
+ }
+ }
+
+ if (directive == all_s && !all_match) {
+ debuglf(spec_lineno, lit("all: some clauses didn't match"), nao);
+ return nil;
+ }
+
+ if ((directive == some_s || directive == cases_s) && !some_match) {
+ debuglf(spec_lineno, lit("some/cases: no clauses matched"), nao);
+ return nil;
+ }
+
+ if (directive == none_s && some_match) {
+ debuglf(spec_lineno, lit("none: some clauses matched"), nao);
+ return nil;
+ }
+
+ /* No check for maybe, since it always succeeds. */
+
+ pos = max_pos;
} else if (consp(directive) || stringp(directive)) {
cons_bind (find, len, search_str_tree(dataline, elem, pos, nil));
val newpos;
@@ -1268,8 +1314,8 @@ repeat_spec_same_data:
if3(data, cons(data, num(data_lineno)), t));
return nil;
}
- } else if (sym == some_s || sym == all_s || sym == none_s ||
- sym == maybe_s || sym == cases_s)
+ } else if ((sym == some_s || sym == all_s || sym == none_s ||
+ sym == maybe_s || sym == cases_s) && second(first_spec) != t)
{
val specs;
val all_match = t;
@@ -1302,9 +1348,9 @@ repeat_spec_same_data:
if (sym == cases_s || sym == none_s)
break;
} else {
+ all_match = nil;
if (sym == all_s)
break;
- all_match = nil;
}
}
diff --git a/parser.y b/parser.y
index 17ad883a..cc66a96f 100644
--- a/parser.y
+++ b/parser.y
@@ -67,7 +67,8 @@ static val parsed_spec;
%type <val> all_clause some_clause none_clause maybe_clause
%type <val> cases_clause collect_clause clause_parts additional_parts
%type <val> output_clause define_clause try_clause catch_clauses_opt
-%type <val> line elems_opt elems elem var var_op
+%type <val> line elems_opt elems clause_parts_h additional_parts_h
+%type <val> elem var var_op
%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 rep_elem rep_parts_opt
@@ -206,8 +207,26 @@ elem : TEXT { $$ = string_own($1); }
UNTIL elems END { $$ = list(coll_s, $4, $6, $2, nao); }
| COLL error { $$ = nil;
yybadtoken(yychar, lit("coll clause")); }
+ | ALL clause_parts_h { $$ = cons(all_s, cons(t, $2)); }
+ | ALL END { yyerror("empty all clause"); }
+ | SOME clause_parts_h { $$ = cons(some_s, cons(t, $2)); }
+ | SOME END { yyerror("empty some clause"); }
+ | NONE clause_parts_h { $$ = cons(none_s, cons(t, $2)); }
+ | NONE END { yyerror("empty none clause"); }
+ | MAYBE clause_parts_h { $$ = cons(maybe_s, cons(t, $2)); }
+ | MAYBE END { yyerror("empty maybe clause"); }
+ | CASES clause_parts_h { $$ = cons(cases_s, cons(t, $2)); }
+ | CASES END { yyerror("empty cases clause"); }
;
+clause_parts_h : elems additional_parts_h { $$ = cons($1, $2); }
+ ;
+
+additional_parts_h : END { $$ = nil; }
+ | AND elems additional_parts_h { $$ = cons($2, $3); }
+ | OR elems additional_parts_h { $$ = cons($2, $3); }
+ ;
+
define_clause : DEFINE exprs ')' newl
clauses_opt
END newl { $$ = list(define_s, $2, $5, nao); }