summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-09-15 21:37:26 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-09-15 21:37:26 -0700
commit2fea7e5998e4e757d62146e67491ee09f6d1738b (patch)
treecf80f6727085746aa49b0060bf2fe8baf65f3ea1
parent5a09b244c77dbf498a4bdf7a9381d2741ce87055 (diff)
downloadtxr-2fea7e5998e4e757d62146e67491ee09f6d1738b.tar.gz
txr-2fea7e5998e4e757d62146e67491ee09f6d1738b.tar.bz2
txr-2fea7e5998e4e757d62146e67491ee09f6d1738b.zip
regex: fix broken complement operator.
The form (match-regex "xy" #/~ab/) should return 2 (full match) because "xy" is in the complement of the set { "ab" }. It wrongly returns 1. * regex.c (reg_derivative): Handle the case when the derivative of the complement's constituent expression yields nil. This means that the complemented regex matches the input. In this case, the complement must lapse to the .+ regex: match one or more characters. That is to say, if the input has at least one more character, there is a match, which covers all such characters. Otherwise there is no match: the input matches the complemented regex. In the t case, the return value is also wrong. If the complemented regex hits a brick wall (matches nothing, not even the empty string), the correct complement is "match everything": the .* regex. Not the match empty string regex!
-rw-r--r--regex.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/regex.c b/regex.c
index c5f5e4aa..61416fb0 100644
--- a/regex.c
+++ b/regex.c
@@ -1713,8 +1713,10 @@ static val reg_derivative(val exp, val ch)
val d_arg = reg_derivative(first(args), ch);
if (reg_matches_all(d_arg))
return t;
+ if (d_arg == nil)
+ return cons(oneplus_s, cons(wild_s, nil));
if (d_arg == t)
- return nil;
+ return cons(zeroplus_s, cons(wild_s, nil));
return cons(sym, cons(d_arg, nil));
} else if (sym == or_s) {
val d_arg1 = reg_derivative(first(args), ch);