зеркало из https://github.com/mozilla/pjs.git
Fix bug #67773. sr=brendan, r=rginda. Fixes doubly nested quantifiers in
reg.exps when deeper sub-expression has to backup without failing. Some other clean-up changes, too.
This commit is contained in:
Родитель
51e609da91
Коммит
9d57bb12b9
|
@ -1379,14 +1379,13 @@ static const jschar *greedyRecurse(GreedyState *grState, const jschar *cp, const
|
|||
|
||||
kidMatch = matchRENodes(grState->state, grState->kid, grState->next, cp);
|
||||
if (kidMatch == NULL) {
|
||||
match = matchRENodes(grState->state, grState->next, NULL, cp);
|
||||
match = matchRENodes(grState->state, grState->next, grState->stop, cp);
|
||||
if (match) {
|
||||
grState->state->parenCount = num;
|
||||
if (previousKid != NULL)
|
||||
matchRENodes(grState->state, grState->kid, grState->next, previousKid);
|
||||
return cp;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
|
@ -1395,17 +1394,18 @@ static const jschar *greedyRecurse(GreedyState *grState, const jschar *cp, const
|
|||
matchRENodes(grState->state, grState->kid, grState->next, previousKid);
|
||||
return kidMatch; /* no point pursuing an empty match forever */
|
||||
}
|
||||
if ((grState->maxKid == 0) || (++grState->kidCount < grState->maxKid)) {
|
||||
if (!grState->maxKid || (++grState->kidCount < grState->maxKid)) {
|
||||
match = greedyRecurse(grState, kidMatch, cp);
|
||||
if (match) return match;
|
||||
if (match)
|
||||
return match;
|
||||
if (grState->maxKid)
|
||||
--grState->kidCount;
|
||||
}
|
||||
grState->state->parenCount = num;
|
||||
if (matchRENodes(grState->state, grState->next, NULL, kidMatch)) {
|
||||
if (matchRENodes(grState->state, grState->next, grState->stop, kidMatch)) {
|
||||
matchRENodes(grState->state, grState->kid, grState->next, cp);
|
||||
return kidMatch;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1414,12 +1414,22 @@ static const jschar *matchGreedyKid(MatchState *state, RENode *ren, RENode *stop
|
|||
int kidCount, const jschar *cp, const jschar *previousKid)
|
||||
{
|
||||
GreedyState grState;
|
||||
const jschar *match;
|
||||
grState.state = state;
|
||||
grState.kid = (RENode *)ren->kid;
|
||||
grState.next = ren->next;
|
||||
grState.stop = stop;
|
||||
grState.kidCount = kidCount;
|
||||
grState.maxKid = (ren->op == REOP_QUANT) ? ren->u.range.max : 0;
|
||||
/*
|
||||
We try to match the sub-tree to completion first, and if that
|
||||
doesn't work, match only up to the given end of the sub-tree.
|
||||
*/
|
||||
grState.stop = NULL;
|
||||
match = greedyRecurse(&grState, cp, previousKid);
|
||||
if (match || !stop)
|
||||
return match;
|
||||
grState.kidCount = kidCount;
|
||||
grState.stop = stop;
|
||||
return greedyRecurse(&grState, cp, previousKid);
|
||||
}
|
||||
|
||||
|
@ -1436,11 +1446,10 @@ static const jschar *matchNonGreedyKid(MatchState *state, RENode *ren,
|
|||
kidMatch = matchRENodes(state, (RENode *)ren->kid, ren->next, cp);
|
||||
if (kidMatch == NULL)
|
||||
return NULL;
|
||||
else {
|
||||
if (kidMatch == cp) return kidMatch; /* no point pursuing an empty match forever */
|
||||
if (kidMatch == cp)
|
||||
return kidMatch; /* no point pursuing an empty match forever */
|
||||
return matchNonGreedyKid(state, ren, kidCount, maxKid, kidMatch);
|
||||
}
|
||||
}
|
||||
|
||||
static void calcBMSize(MatchState *state, RENode *ren)
|
||||
{
|
||||
|
@ -1709,7 +1718,8 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
}
|
||||
num = state->parenCount;
|
||||
kidMatch = matchRENodes(state, (RENode *)ren->kid, stop, cp);
|
||||
if (kidMatch != NULL) return kidMatch;
|
||||
if (kidMatch != NULL)
|
||||
return kidMatch;
|
||||
for (i = num; i < state->parenCount; i++)
|
||||
state->parens[i].length = 0;
|
||||
state->parenCount = num;
|
||||
|
@ -1727,13 +1737,19 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
if (num == ren->u.range.max) break;
|
||||
if ((ren->flags & RENODE_MINIMAL) == 0) {
|
||||
cp2 = matchGreedyKid(state, ren, stop, num, cp, lastKid);
|
||||
if (cp2)
|
||||
if (cp2 == NULL) {
|
||||
if (lastKid)
|
||||
cp = matchRENodes(state, (RENode *)ren->kid, ren->next,
|
||||
lastKid);
|
||||
}
|
||||
else
|
||||
cp = cp2;
|
||||
}
|
||||
else {
|
||||
cp = matchNonGreedyKid(state, ren, num,
|
||||
ren->u.range.max, cp);
|
||||
if (cp == NULL) return NULL;
|
||||
if (cp == NULL)
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case REOP_PLUS:
|
||||
|
@ -1742,13 +1758,16 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
if (kidMatch == NULL)
|
||||
return NULL;
|
||||
if ((ren->flags & RENODE_MINIMAL) == 0) {
|
||||
cp = matchGreedyKid(state, ren, stop, 1, kidMatch, cp);
|
||||
if (cp == NULL)
|
||||
cp = kidMatch;
|
||||
cp2 = matchGreedyKid(state, ren, stop, 1, kidMatch, cp);
|
||||
if (cp2 == NULL)
|
||||
cp = matchRENodes(state, (RENode *)ren->kid, ren->next, cp);
|
||||
else
|
||||
cp = cp2;
|
||||
}
|
||||
else
|
||||
cp = matchNonGreedyKid(state, ren, 1, 0, kidMatch);
|
||||
if (cp == NULL) return NULL;
|
||||
if (cp == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
case REOP_STAR:
|
||||
if ((ren->flags & RENODE_MINIMAL) == 0) {
|
||||
|
@ -1758,7 +1777,8 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
}
|
||||
else {
|
||||
cp = matchNonGreedyKid(state, ren, 0, 0, cp);
|
||||
if (cp == NULL) return NULL;
|
||||
if (cp == NULL)
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case REOP_OPT:
|
||||
|
@ -1766,7 +1786,8 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
if (ren->flags & RENODE_MINIMAL) {
|
||||
const jschar *restMatch = matchRENodes(state, ren->next,
|
||||
stop, cp);
|
||||
if (restMatch != NULL) return restMatch;
|
||||
if (restMatch != NULL)
|
||||
return restMatch;
|
||||
}
|
||||
kidMatch = matchRENodes(state, (RENode *)ren->kid,
|
||||
ren->next, cp);
|
||||
|
@ -1807,12 +1828,14 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
case REOP_ASSERT:
|
||||
kidMatch = matchRENodes(state, (RENode *)ren->kid,
|
||||
ren->next, cp);
|
||||
if (kidMatch == NULL) return NULL;
|
||||
if (kidMatch == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
case REOP_ASSERT_NOT:
|
||||
kidMatch = matchRENodes(state, (RENode *)ren->kid,
|
||||
ren->next, cp);
|
||||
if (kidMatch != NULL) return NULL;
|
||||
if (kidMatch != NULL)
|
||||
return NULL;
|
||||
break;
|
||||
case REOP_BACKREF:
|
||||
num = ren->u.num;
|
||||
|
@ -1871,7 +1894,8 @@ static const jschar *matchRENodes(MatchState *state, RENode *ren, RENode *stop,
|
|||
case REOP_DOTSTARMIN:
|
||||
for (cp2 = cp; cp2 < cpend; cp2++) {
|
||||
const jschar *cp3 = matchRENodes(state, ren->next, stop, cp2);
|
||||
if (cp3 != NULL) return cp3;
|
||||
if (cp3 != NULL)
|
||||
return cp3;
|
||||
if (*cp2 == '\n')
|
||||
return NULL;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче