(r'^a*?$', 'foo', FAIL),
# bug 470582: nested groups problem
(r'^((a)c)?(ab)$', 'ab', SUCCEED, 'g1+"-"+g2+"-"+g3', 'None-None-ab'),
+ # another minimizing repeat problem (capturing groups in assertions)
+ ('^([ab]*?)(?=(b)?)c', 'abc', SUCCEED, 'g1+"-"+g2', 'ab-None'),
+ ('^([ab]*?)(?!(b))c', 'abc', SUCCEED, 'g1+"-"+g2', 'ab-None'),
+ ('^([ab]*?)(?<!(a))c', 'abc', SUCCEED, 'g1+"-"+g2', 'ab-None'),
]
try:
test(r"""sre.match(r'(a)|(b)', 'b').end(1)""", -1)
test(r"""sre.match(r'(a)|(b)', 'b').span(1)""", (-1, -1))
-# bug described in patch 527371
+# bug described in patches 527371/672491
test(r"""sre.match(r'(a)?a','a').lastindex""", None)
test(r"""sre.match(r'(a)(b)?b','ab').lastindex""", 1)
test(r"""sre.match(r'(?P<a>a)(?P<b>b)?b','ab').lastgroup""", 'a')
+test(r"""sre.match("(?P<a>a(b))", "ab").lastgroup""", 'a')
+test(r"""sre.match("((a))", "a").lastindex""", 1)
# bug 545855 -- This pattern failed to cause a compile error as it
# should, instead provoking a TypeError.
return 0;
}
-static void
-lastmark_restore(SRE_STATE *state, int lastmark)
-{
- if (state->lastmark > lastmark) {
- memset(
- state->mark + lastmark + 1, 0,
- (state->lastmark - lastmark) * sizeof(void*)
- );
- state->lastmark = lastmark;
- state->lastindex = (lastmark == 0) ? -1 : (lastmark-1)/2+1;
- }
-}
-
/* generate 8-bit version */
#define SRE_CHAR unsigned char
}
#endif
+/* macros to preserve lastmark in case of backtracking */
+#define LASTMARK_SAVE() \
+ do { \
+ lastmark = state->lastmark; \
+ lastindex = state->lastindex; \
+ } while (0)
+#define LASTMARK_RESTORE() \
+ do { \
+ if (state->lastmark > lastmark) { \
+ memset(state->mark + lastmark + 1, 0, \
+ (state->lastmark - lastmark) * sizeof(void*)); \
+ state->lastmark = lastmark; \
+ state->lastindex = lastindex; \
+ } \
+ } while (0)
+
LOCAL(int)
SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
{
SRE_CHAR* ptr = state->ptr;
int i, count;
SRE_REPEAT* rp;
- int lastmark;
+ int lastmark, lastindex;
SRE_CODE chr;
SRE_REPEAT rep; /* FIXME: <fl> allocate in STATE instead */
/* alternation */
/* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
TRACE(("|%p|%p|BRANCH\n", pattern, ptr));
- lastmark = state->lastmark;
+ LASTMARK_SAVE();
for (; pattern[0]; pattern += pattern[0]) {
if (pattern[1] == SRE_OP_LITERAL &&
(ptr >= end || (SRE_CODE) *ptr != pattern[2]))
i = SRE_MATCH(state, pattern + 1, level + 1);
if (i)
return i;
- lastmark_restore(state, lastmark);
+ LASTMARK_RESTORE();
}
return 0;
/* tail is empty. we're finished */
state->ptr = ptr;
return 1;
+ }
+
+ LASTMARK_SAVE();
- } else if (pattern[pattern[0]] == SRE_OP_LITERAL) {
+ if (pattern[pattern[0]] == SRE_OP_LITERAL) {
/* tail starts with a literal. skip positions where
the rest of the pattern cannot possibly match */
chr = pattern[pattern[0]+1];
return i;
ptr--;
count--;
+ LASTMARK_RESTORE();
}
} else {
/* general case */
- lastmark = state->lastmark;
while (count >= (int) pattern[1]) {
state->ptr = ptr;
i = SRE_MATCH(state, pattern + pattern[0], level + 1);
return i;
ptr--;
count--;
- lastmark_restore(state, lastmark);
+ LASTMARK_RESTORE();
}
}
return 0;
/* general case */
int matchmax = ((int)pattern[2] == 65535);
int c;
- lastmark = state->lastmark;
+ LASTMARK_SAVE();
while (matchmax || count <= (int) pattern[2]) {
state->ptr = ptr;
i = SRE_MATCH(state, pattern + pattern[0], level + 1);
c = SRE_COUNT(state, pattern+3, 1, level+1);
if (c < 0)
return c;
+ LASTMARK_RESTORE();
if (c == 0)
break;
assert(c == 1);
ptr++;
count++;
}
- lastmark_restore(state, lastmark);
}
return 0;
TRACE(("|%p|%p|MAX_UNTIL %d\n", pattern, ptr, count));
+ LASTMARK_SAVE();
+
if (count < rp->pattern[1]) {
/* not enough matches */
rp->count = count;
return i;
rp->count = count - 1;
state->ptr = ptr;
+ LASTMARK_RESTORE();
return 0;
}
/* we may have enough matches, but if we can
match another item, do so */
rp->count = count;
- lastmark = state->lastmark;
i = mark_save(state, 0, lastmark);
if (i < 0)
return i;
if (i)
return i;
i = mark_restore(state, 0, lastmark);
- state->lastmark = lastmark;
+ LASTMARK_RESTORE();
if (i < 0)
return i;
rp->count = count - 1;
return 0;
}
+ LASTMARK_SAVE();
+
/* see if the tail matches */
state->repeat = rp->prev;
i = SRE_MATCH(state, pattern, level + 1);
state->ptr = ptr;
state->repeat = rp;
+ LASTMARK_RESTORE();
+
if (count >= rp->pattern[2] && rp->pattern[2] != 65535)
return 0;
}
#endif /* !defined(SRE_RECURSIVE) */
+
+/* vim:ts=4:sw=4:et
+*/