# HG changeset patch # User Bram Moolenaar # Date 1370874918 -7200 # Node ID 2f1ee97f5f23a5f9e1c572ed4afb50fb79ce7a35 # Parent 198cf88374c8385ce8aac017e9d68b81e80b6b95 updated for version 7.3.1157 Problem: New regexp engine fails on "\(\state->out1->out->c; - - /* Do it directly when what follows is possibly end of - * match (closing paren). + int directly = FALSE; + +#ifdef ENABLE_LOG + fprintf(log_fd, "Failure chance invisible: %d, what follows: %d\n", + failure_chance(t->state->out, 0), + failure_chance(t->state->out1->out, 0)); +#endif + /* Do it directly when what follows is possibly the end of + * the match. * Do it directly if there already is a PIM. - * Postpone when it is \@<= or \@= NFA_MCLOSE && cout <= NFA_MCLOSE9) -#ifdef FEAT_SYN_HL - || (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9) -#endif - || t->pim.result != NFA_PIM_UNUSED - || (t->state->c != NFA_START_INVISIBLE_BEFORE - && t->state->c != NFA_START_INVISIBLE_BEFORE_NEG - && failure_chance(t->state->out1->out, 0) - < failure_chance(t->state->out, 0))) + * Postpone when the invisible match is expensive or has a + * lower chance of failing. */ + if (match_follows(t->state->out1->out, 0) + || t->pim.result != NFA_PIM_UNUSED) + directly = TRUE; + else + { + int ch_invisible = failure_chance(t->state->out, 0); + int ch_follows = failure_chance(t->state->out1->out, 0); + + if (t->state->c == NFA_START_INVISIBLE_BEFORE + || t->state->c == NFA_START_INVISIBLE_BEFORE_NEG) + { + /* "before" matches are very expensive when + * unbounded, always prefer what follows then, + * unless what follows will always match. + * Otherwise strongly prefer what follows. */ + if (t->state->val <= 0 && ch_follows > 0) + directly = FALSE; + else + directly = ch_follows * 10 < ch_invisible; + } + else + { + /* normal invisible, first do the one with the + * highest failure chance */ + directly = ch_follows < ch_invisible; + } + } + if (directly) { /* * First try matching the invisible match, then what diff --git a/src/testdir/test64.in b/src/testdir/test64.in --- a/src/testdir/test64.in +++ b/src/testdir/test64.in @@ -392,6 +392,7 @@ STARTTEST :call add(tl, [2, '\v\C%(', 'foobar']) :call add(tl, [2, '\(foo\)\@<=\>', 'barfoo', '', 'foo']) +:call add(tl, [2, '\(foo\)\@<=.*', 'foobar', 'bar', 'foo']) :" :""""" \@> :call add(tl, [2, '\(a*\)\@>a', 'aaaa']) diff --git a/src/testdir/test64.ok b/src/testdir/test64.ok --- a/src/testdir/test64.ok +++ b/src/testdir/test64.ok @@ -890,6 +890,9 @@ OK 2 - \(foo\)\@<=\> OK 0 - \(foo\)\@<=\> OK 1 - \(foo\)\@<=\> OK 2 - \(foo\)\@<=\> +OK 0 - \(foo\)\@<=.* +OK 1 - \(foo\)\@<=.* +OK 2 - \(foo\)\@<=.* OK 0 - \(a*\)\@>a OK 1 - \(a*\)\@>a OK 2 - \(a*\)\@>a diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1157, +/**/ 1156, /**/ 1155,