diff options
author | Bram Moolenaar <Bram@vim.org> | 2013-06-10 16:35:18 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2013-06-10 16:35:18 +0200 |
commit | bcf4d178abef9336709b53516fbf0164ce5ebe09 (patch) | |
tree | 2dacad0dd3aeea0522cda509871f8f77683be664 /src | |
parent | 4380d1ea239fe7f2546b7cad4ad0c424f0f5979a (diff) | |
download | vim-bcf4d178abef9336709b53516fbf0164ce5ebe09.zip |
updated for version 7.3.1157
Problem: New regexp engine fails on "\(\<command\)\@<=.*"
Solution: Fix rule for postponing match. Further tune estimating whether
postponing works better. Add test.
Diffstat (limited to 'src')
-rw-r--r-- | src/regexp_nfa.c | 57 | ||||
-rw-r--r-- | src/testdir/test64.in | 1 | ||||
-rw-r--r-- | src/testdir/test64.ok | 3 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 47 insertions, 16 deletions
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c index 9a89b49ec..40208d409 100644 --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -4587,6 +4587,7 @@ static long find_match_text __ARGS((colnr_T startcol, int regstart, char_u *matc /* * Estimate the chance of a match with "state" failing. + * empty match: 0 * NFA_ANY: 1 * specific character: 99 */ @@ -4616,7 +4617,9 @@ failure_chance(state, depth) case NFA_ANY: /* matches anything, unlikely to fail */ return 1; + case NFA_MATCH: + case NFA_MCLOSE: /* empty match works always */ return 0; @@ -4664,7 +4667,6 @@ failure_chance(state, depth) case NFA_ZCLOSE9: #endif case NFA_NOPEN: - case NFA_MCLOSE: case NFA_MCLOSE1: case NFA_MCLOSE2: case NFA_MCLOSE3: @@ -5095,23 +5097,46 @@ nfa_regmatch(prog, start, submatch, m) case NFA_START_INVISIBLE_BEFORE: case NFA_START_INVISIBLE_BEFORE_NEG: { - int cout = t->state->out1->out->c; + int directly = FALSE; - /* Do it directly when what follows is possibly end of - * match (closing paren). - * Do it directly if there already is a PIM. - * Postpone when it is \@<= or \@<!, these are expensive. - * Otherwise first do the one that has the highest chance - * of failing. */ - if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9) -#ifdef FEAT_SYN_HL - || (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9) +#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 - || 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))) + /* Do it directly when what follows is possibly the end of + * the match. + * Do it directly if there already is a PIM. + * 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 index 42703c2e2..8100436f1 100644 --- a/src/testdir/test64.in +++ b/src/testdir/test64.in @@ -392,6 +392,7 @@ STARTTEST :call add(tl, [2, '\v\C%(<Last Changed:\s+)@<=.*$', '" Last Changed: 1970', '1970']) :call add(tl, [2, '\(foo\)\@<=\>', '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 index 0e25737dd..8e90cb8f8 100644 --- 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 index 3b2fc8340..4ec8b3ef8 100644 --- 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, |