summaryrefslogtreecommitdiffstats
path: root/regex.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-27 22:36:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-27 22:36:38 -0700
commit5ac2c633f7bc24daae047890c1b9383ff43b5800 (patch)
tree8c6e426e739cea995c9d22ba8bdffa00a26c00b7 /regex.c
parent7aebb0c779f9ec66da657f4196ed4115c15b359b (diff)
downloadtxr-5ac2c633f7bc24daae047890c1b9383ff43b5800.tar.gz
txr-5ac2c633f7bc24daae047890c1b9383ff43b5800.tar.bz2
txr-5ac2c633f7bc24daae047890c1b9383ff43b5800.zip
Optimize complement operator more.
* regex.c (reg_optimize): Recognize and transform several cases: ~c -> ([^c]?|..+); ~[^c] -> ([c]?|..+); and ~.*c.* -> [^c]*.
Diffstat (limited to 'regex.c')
-rw-r--r--regex.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/regex.c b/regex.c
index 9b26b342..a4ca5451 100644
--- a/regex.c
+++ b/regex.c
@@ -44,6 +44,7 @@
#include "stream.h"
#include "gc.h"
#include "eval.h"
+#include "cadr.h"
#include "regex.h"
#include "txr.h"
@@ -1781,6 +1782,33 @@ static val reg_optimize(val exp)
return t;
if (arg == nil)
return cons(oneplus_s, cons(wild_s, nil));
+ if (chrp(arg))
+ arg = list(set_s, arg, nao);
+ if (consp(arg)) {
+ val sym2 = first(arg);
+ if (sym2 == cset_s)
+ return list(or_s,
+ list(optional_s, cons(set_s, rest(arg)), nao),
+ list(compound_s, wild_s,
+ list(oneplus_s, wild_s, nao), nao), nao);
+ if (sym2 == set_s)
+ return list(or_s,
+ list(optional_s, cons(cset_s, rest(arg)), nao),
+ list(compound_s, wild_s,
+ list(oneplus_s, wild_s, nao), nao), nao);
+ if (sym2 == compound_s) {
+ val args2 = rest(arg);
+ if (cddr(args2) && !cdddr(args2)) {
+ if (reg_matches_all(first(args2)) &&
+ chrp(second(args2)) &&
+ reg_matches_all(third(args2)))
+ {
+ return cons(zeroplus_s,
+ cons(cons(cset_s, cons(second(args2), nil)), nil));
+ }
+ }
+ }
+ }
return cons(sym, cons(arg, nil));
} else if (sym == or_s) {
val arg1 = reg_optimize(pop(&args));