summaryrefslogtreecommitdiff
path: root/src/regexp_nfa.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2013-06-10 16:35:18 +0200
committerBram Moolenaar <Bram@vim.org>2013-06-10 16:35:18 +0200
commitbcf4d178abef9336709b53516fbf0164ce5ebe09 (patch)
tree2dacad0dd3aeea0522cda509871f8f77683be664 /src/regexp_nfa.c
parent4380d1ea239fe7f2546b7cad4ad0c424f0f5979a (diff)
downloadvim-git-bcf4d178abef9336709b53516fbf0164ce5ebe09.tar.gz
updated for version 7.3.1157v7.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/regexp_nfa.c')
-rw-r--r--src/regexp_nfa.c57
1 files changed, 41 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