mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
updated for version 7.3.1153
Problem: New regexp engine: Some look-behind matches are very expensive. Solution: Pospone invisible matches further, until a match is almost found.
This commit is contained in:
250
src/regexp_nfa.c
250
src/regexp_nfa.c
@@ -3354,16 +3354,21 @@ typedef struct
|
|||||||
typedef struct nfa_pim_S nfa_pim_T;
|
typedef struct nfa_pim_S nfa_pim_T;
|
||||||
struct nfa_pim_S
|
struct nfa_pim_S
|
||||||
{
|
{
|
||||||
nfa_state_T *state;
|
int result; /* NFA_PIM_*, see below */
|
||||||
int result; /* NFA_PIM_TODO, NFA_PIM_[NO]MATCH */
|
nfa_state_T *state; /* the invisible match start state */
|
||||||
nfa_pim_T *pim; /* another PIM at the same position */
|
|
||||||
regsubs_T subs; /* submatch info, only party used */
|
regsubs_T subs; /* submatch info, only party used */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
lpos_T pos;
|
||||||
|
char_u *ptr;
|
||||||
|
} end; /* where the match must end */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Values for done in nfa_pim_T. */
|
/* Values for done in nfa_pim_T. */
|
||||||
#define NFA_PIM_TODO 0
|
#define NFA_PIM_UNUSED 0 /* pim not used */
|
||||||
#define NFA_PIM_MATCH 1
|
#define NFA_PIM_TODO 1 /* pim not done yet */
|
||||||
#define NFA_PIM_NOMATCH -1
|
#define NFA_PIM_MATCH 2 /* pim executed, matches */
|
||||||
|
#define NFA_PIM_NOMATCH 3 /* pim executed, no match */
|
||||||
|
|
||||||
|
|
||||||
/* nfa_thread_T contains execution information of a NFA state */
|
/* nfa_thread_T contains execution information of a NFA state */
|
||||||
@@ -3371,7 +3376,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
nfa_state_T *state;
|
nfa_state_T *state;
|
||||||
int count;
|
int count;
|
||||||
nfa_pim_T *pim; /* if not NULL: postponed invisible match */
|
nfa_pim_T pim; /* if pim.result != NFA_PIM_UNUSED: postponed
|
||||||
|
* invisible match */
|
||||||
regsubs_T subs; /* submatch info, only party used */
|
regsubs_T subs; /* submatch info, only party used */
|
||||||
} nfa_thread_T;
|
} nfa_thread_T;
|
||||||
|
|
||||||
@@ -3424,11 +3430,28 @@ log_subexpr(sub)
|
|||||||
e == NULL ? "NULL" : e);
|
e == NULL ? "NULL" : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
pim_info(nfa_pim_T *pim)
|
||||||
|
{
|
||||||
|
static char buf[30];
|
||||||
|
|
||||||
|
if (pim == NULL || pim->result == NFA_PIM_UNUSED)
|
||||||
|
buf[0] = NUL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(buf, " PIM col %d", REG_MULTI ? (int)pim->end.pos.col
|
||||||
|
: (int)(pim->end.ptr - reginput));
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Used during execution: whether a match has been found. */
|
/* Used during execution: whether a match has been found. */
|
||||||
static int nfa_match;
|
static int nfa_match;
|
||||||
|
|
||||||
|
static void copy_pim __ARGS((nfa_pim_T *to, nfa_pim_T *from));
|
||||||
static void clear_sub __ARGS((regsub_T *sub));
|
static void clear_sub __ARGS((regsub_T *sub));
|
||||||
static void copy_sub __ARGS((regsub_T *to, regsub_T *from));
|
static void copy_sub __ARGS((regsub_T *to, regsub_T *from));
|
||||||
static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
|
static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
|
||||||
@@ -3436,9 +3459,27 @@ static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
|
|||||||
static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
|
static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
|
||||||
static int match_follows __ARGS((nfa_state_T *startstate, int depth));
|
static int match_follows __ARGS((nfa_state_T *startstate, int depth));
|
||||||
static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
|
static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
|
||||||
static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int off));
|
static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int off));
|
||||||
static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip));
|
static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy postponed invisible match info from "from" to "to".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
copy_pim(to, from)
|
||||||
|
nfa_pim_T *to;
|
||||||
|
nfa_pim_T *from;
|
||||||
|
{
|
||||||
|
to->result = from->result;
|
||||||
|
to->state = from->state;
|
||||||
|
copy_sub(&to->subs.norm, &from->subs.norm);
|
||||||
|
#ifdef FEAT_SYN_HL
|
||||||
|
if (nfa_has_zsubexpr)
|
||||||
|
copy_sub(&to->subs.synt, &from->subs.synt);
|
||||||
|
#endif
|
||||||
|
to->end = from->end;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_sub(sub)
|
clear_sub(sub)
|
||||||
regsub_T *sub;
|
regsub_T *sub;
|
||||||
@@ -3583,7 +3624,11 @@ sub_equal(sub1, sub2)
|
|||||||
|
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
static void
|
static void
|
||||||
report_state(char *action, regsub_T *sub, nfa_state_T *state, int lid)
|
report_state(char *action,
|
||||||
|
regsub_T *sub,
|
||||||
|
nfa_state_T *state,
|
||||||
|
int lid,
|
||||||
|
nfa_pim_T *pim)
|
||||||
{
|
{
|
||||||
int col;
|
int col;
|
||||||
|
|
||||||
@@ -3594,8 +3639,9 @@ report_state(char *action, regsub_T *sub, nfa_state_T *state, int lid)
|
|||||||
else
|
else
|
||||||
col = (int)(sub->list.line[0].start - regline);
|
col = (int)(sub->list.line[0].start - regline);
|
||||||
nfa_set_code(state->c);
|
nfa_set_code(state->c);
|
||||||
fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)\n",
|
fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n",
|
||||||
action, abs(state->id), lid, state->c, code, col);
|
action, abs(state->id), lid, state->c, code, col,
|
||||||
|
pim_info(pim));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3646,6 +3692,10 @@ match_follows(startstate, depth)
|
|||||||
switch (state->c)
|
switch (state->c)
|
||||||
{
|
{
|
||||||
case NFA_MATCH:
|
case NFA_MATCH:
|
||||||
|
case NFA_MCLOSE:
|
||||||
|
case NFA_END_INVISIBLE:
|
||||||
|
case NFA_END_INVISIBLE_NEG:
|
||||||
|
case NFA_END_PATTERN:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case NFA_SPLIT:
|
case NFA_SPLIT:
|
||||||
@@ -3727,10 +3777,11 @@ state_in_list(l, state, subs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
addstate(l, state, subs, off)
|
addstate(l, state, subs, pim, off)
|
||||||
nfa_list_T *l; /* runtime state list */
|
nfa_list_T *l; /* runtime state list */
|
||||||
nfa_state_T *state; /* state to update */
|
nfa_state_T *state; /* state to update */
|
||||||
regsubs_T *subs; /* pointers to subexpressions */
|
regsubs_T *subs; /* pointers to subexpressions */
|
||||||
|
nfa_pim_T *pim; /* postponed look-behind match */
|
||||||
int off; /* byte offset, when -1 go to next line */
|
int off; /* byte offset, when -1 go to next line */
|
||||||
{
|
{
|
||||||
int subidx;
|
int subidx;
|
||||||
@@ -3856,21 +3907,24 @@ skip_add:
|
|||||||
state->lastlist[nfa_ll_index] = l->id;
|
state->lastlist[nfa_ll_index] = l->id;
|
||||||
thread = &l->t[l->n++];
|
thread = &l->t[l->n++];
|
||||||
thread->state = state;
|
thread->state = state;
|
||||||
thread->pim = NULL;
|
if (pim == NULL)
|
||||||
|
thread->pim.result = NFA_PIM_UNUSED;
|
||||||
|
else
|
||||||
|
copy_pim(&thread->pim, pim);
|
||||||
copy_sub(&thread->subs.norm, &subs->norm);
|
copy_sub(&thread->subs.norm, &subs->norm);
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
if (nfa_has_zsubexpr)
|
if (nfa_has_zsubexpr)
|
||||||
copy_sub(&thread->subs.synt, &subs->synt);
|
copy_sub(&thread->subs.synt, &subs->synt);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
report_state("Adding", &thread->subs.norm, state, l->id);
|
report_state("Adding", &thread->subs.norm, state, l->id, pim);
|
||||||
did_print = TRUE;
|
did_print = TRUE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
if (!did_print)
|
if (!did_print)
|
||||||
report_state("Processing", &subs->norm, state, l->id);
|
report_state("Processing", &subs->norm, state, l->id, pim);
|
||||||
#endif
|
#endif
|
||||||
switch (state->c)
|
switch (state->c)
|
||||||
{
|
{
|
||||||
@@ -3880,14 +3934,14 @@ skip_add:
|
|||||||
|
|
||||||
case NFA_SPLIT:
|
case NFA_SPLIT:
|
||||||
/* order matters here */
|
/* order matters here */
|
||||||
addstate(l, state->out, subs, off);
|
addstate(l, state->out, subs, pim, off);
|
||||||
addstate(l, state->out1, subs, off);
|
addstate(l, state->out1, subs, pim, off);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NFA_SKIP_CHAR:
|
case NFA_SKIP_CHAR:
|
||||||
case NFA_NOPEN:
|
case NFA_NOPEN:
|
||||||
case NFA_NCLOSE:
|
case NFA_NCLOSE:
|
||||||
addstate(l, state->out, subs, off);
|
addstate(l, state->out, subs, pim, off);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NFA_MOPEN:
|
case NFA_MOPEN:
|
||||||
@@ -3983,7 +4037,7 @@ skip_add:
|
|||||||
sub->list.line[subidx].start = reginput + off;
|
sub->list.line[subidx].start = reginput + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
addstate(l, state->out, subs, off);
|
addstate(l, state->out, subs, pim, off);
|
||||||
|
|
||||||
if (save_in_use == -1)
|
if (save_in_use == -1)
|
||||||
{
|
{
|
||||||
@@ -4001,7 +4055,7 @@ skip_add:
|
|||||||
{
|
{
|
||||||
/* Do not overwrite the position set by \ze. If no \ze
|
/* Do not overwrite the position set by \ze. If no \ze
|
||||||
* encountered end will be set in nfa_regtry(). */
|
* encountered end will be set in nfa_regtry(). */
|
||||||
addstate(l, state->out, subs, off);
|
addstate(l, state->out, subs, pim, off);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NFA_MCLOSE1:
|
case NFA_MCLOSE1:
|
||||||
@@ -4070,7 +4124,7 @@ skip_add:
|
|||||||
sub->list.line[subidx].end = reginput + off;
|
sub->list.line[subidx].end = reginput + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
addstate(l, state->out, subs, off);
|
addstate(l, state->out, subs, pim, off);
|
||||||
|
|
||||||
if (REG_MULTI)
|
if (REG_MULTI)
|
||||||
sub->list.multi[subidx].end = save_lpos;
|
sub->list.multi[subidx].end = save_lpos;
|
||||||
@@ -4098,15 +4152,9 @@ addstate_here(l, state, subs, pim, ip)
|
|||||||
int tlen = l->n;
|
int tlen = l->n;
|
||||||
int count;
|
int count;
|
||||||
int listidx = *ip;
|
int listidx = *ip;
|
||||||
int i;
|
|
||||||
|
|
||||||
/* first add the state(s) at the end, so that we know how many there are */
|
/* first add the state(s) at the end, so that we know how many there are */
|
||||||
addstate(l, state, subs, 0);
|
addstate(l, state, subs, pim, 0);
|
||||||
|
|
||||||
/* fill in the "pim" field in the new states */
|
|
||||||
if (pim != NULL)
|
|
||||||
for (i = tlen; i < l->n; ++i)
|
|
||||||
l->t[i].pim = pim;
|
|
||||||
|
|
||||||
/* when "*ip" was at the end of the list, nothing to do */
|
/* when "*ip" was at the end of the list, nothing to do */
|
||||||
if (listidx + 1 == tlen)
|
if (listidx + 1 == tlen)
|
||||||
@@ -4355,15 +4403,18 @@ nfa_re_num_cmp(val, op, pos)
|
|||||||
return val == pos;
|
return val == pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recursive_regmatch __ARGS((nfa_state_T *state, nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, int **listids));
|
static int recursive_regmatch __ARGS((nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, int **listids));
|
||||||
static int nfa_regmatch __ARGS((nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m));
|
static int nfa_regmatch __ARGS((nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recursively call nfa_regmatch()
|
* Recursively call nfa_regmatch()
|
||||||
|
* "pim" is NULL or contains info about a Postponed Invisible Match (start
|
||||||
|
* position).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
recursive_regmatch(state, prog, submatch, m, listids)
|
recursive_regmatch(state, pim, prog, submatch, m, listids)
|
||||||
nfa_state_T *state;
|
nfa_state_T *state;
|
||||||
|
nfa_pim_T *pim;
|
||||||
nfa_regprog_T *prog;
|
nfa_regprog_T *prog;
|
||||||
regsubs_T *submatch;
|
regsubs_T *submatch;
|
||||||
regsubs_T *m;
|
regsubs_T *m;
|
||||||
@@ -4380,18 +4431,38 @@ recursive_regmatch(state, prog, submatch, m, listids)
|
|||||||
int result;
|
int result;
|
||||||
int need_restore = FALSE;
|
int need_restore = FALSE;
|
||||||
|
|
||||||
|
if (pim != NULL)
|
||||||
|
{
|
||||||
|
/* start at the position where the postponed match was */
|
||||||
|
if (REG_MULTI)
|
||||||
|
reginput = regline + pim->end.pos.col;
|
||||||
|
else
|
||||||
|
reginput = pim->end.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (state->c == NFA_START_INVISIBLE_BEFORE
|
if (state->c == NFA_START_INVISIBLE_BEFORE
|
||||||
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG)
|
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG)
|
||||||
{
|
{
|
||||||
/* The recursive match must end at the current position. */
|
/* The recursive match must end at the current position. When "pim" is
|
||||||
|
* not NULL it specifies the current position. */
|
||||||
endposp = &endpos;
|
endposp = &endpos;
|
||||||
if (REG_MULTI)
|
if (REG_MULTI)
|
||||||
{
|
{
|
||||||
endpos.se_u.pos.col = (int)(reginput - regline);
|
if (pim == NULL)
|
||||||
endpos.se_u.pos.lnum = reglnum;
|
{
|
||||||
|
endpos.se_u.pos.col = (int)(reginput - regline);
|
||||||
|
endpos.se_u.pos.lnum = reglnum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
endpos.se_u.pos = pim->end.pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
endpos.se_u.ptr = reginput;
|
{
|
||||||
|
if (pim == NULL)
|
||||||
|
endpos.se_u.ptr = reginput;
|
||||||
|
else
|
||||||
|
endpos.se_u.ptr = pim->end.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Go back the specified number of bytes, or as far as the
|
/* Go back the specified number of bytes, or as far as the
|
||||||
* start of the previous line, to try matching "\@<=" or
|
* start of the previous line, to try matching "\@<=" or
|
||||||
@@ -4784,7 +4855,6 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
int add_here;
|
int add_here;
|
||||||
int add_count;
|
int add_count;
|
||||||
int add_off;
|
int add_off;
|
||||||
garray_T pimlist;
|
|
||||||
int toplevel = start->c == NFA_MOPEN;
|
int toplevel = start->c == NFA_MOPEN;
|
||||||
#ifdef NFA_REGEXP_DEBUG_LOG
|
#ifdef NFA_REGEXP_DEBUG_LOG
|
||||||
FILE *debug = fopen(NFA_REGEXP_DEBUG_LOG, "a");
|
FILE *debug = fopen(NFA_REGEXP_DEBUG_LOG, "a");
|
||||||
@@ -4796,7 +4866,6 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
nfa_match = FALSE;
|
nfa_match = FALSE;
|
||||||
ga_init2(&pimlist, sizeof(nfa_pim_T), 5);
|
|
||||||
|
|
||||||
/* Allocate memory for the lists of nodes. */
|
/* Allocate memory for the lists of nodes. */
|
||||||
size = (nstate + 1) * sizeof(nfa_thread_T);
|
size = (nstate + 1) * sizeof(nfa_thread_T);
|
||||||
@@ -4845,10 +4914,10 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
else
|
else
|
||||||
m->norm.list.line[0].start = reginput;
|
m->norm.list.line[0].start = reginput;
|
||||||
m->norm.in_use = 1;
|
m->norm.in_use = 1;
|
||||||
addstate(thislist, start->out, m, 0);
|
addstate(thislist, start->out, m, NULL, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addstate(thislist, start, m, 0);
|
addstate(thislist, start, m, NULL, 0);
|
||||||
|
|
||||||
#define ADD_STATE_IF_MATCH(state) \
|
#define ADD_STATE_IF_MATCH(state) \
|
||||||
if (result) { \
|
if (result) { \
|
||||||
@@ -4890,8 +4959,6 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
thislist->id = nfa_listid;
|
thislist->id = nfa_listid;
|
||||||
nextlist->id = nfa_listid + 1;
|
nextlist->id = nfa_listid + 1;
|
||||||
|
|
||||||
pimlist.ga_len = 0;
|
|
||||||
|
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
fprintf(log_fd, "------------------------------------------\n");
|
fprintf(log_fd, "------------------------------------------\n");
|
||||||
fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput);
|
fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput);
|
||||||
@@ -4935,8 +5002,9 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
else
|
else
|
||||||
col = (int)(t->subs.norm.list.line[0].start - regline);
|
col = (int)(t->subs.norm.list.line[0].start - regline);
|
||||||
nfa_set_code(t->state->c);
|
nfa_set_code(t->state->c);
|
||||||
fprintf(log_fd, "(%d) char %d %s (start col %d) ... \n",
|
fprintf(log_fd, "(%d) char %d %s (start col %d)%s ... \n",
|
||||||
abs(t->state->id), (int)t->state->c, code, col);
|
abs(t->state->id), (int)t->state->c, code, col,
|
||||||
|
pim_info(&t->pim));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -5028,21 +5096,19 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
case NFA_START_INVISIBLE_BEFORE:
|
case NFA_START_INVISIBLE_BEFORE:
|
||||||
case NFA_START_INVISIBLE_BEFORE_NEG:
|
case NFA_START_INVISIBLE_BEFORE_NEG:
|
||||||
{
|
{
|
||||||
nfa_pim_T *pim;
|
|
||||||
int cout = t->state->out1->out->c;
|
int cout = t->state->out1->out->c;
|
||||||
|
|
||||||
/* Do it directly when what follows is possibly end of
|
/* Do it directly when what follows is possibly end of
|
||||||
* match (closing paren).
|
* match (closing paren).
|
||||||
|
* Do it directly if there already is a PIM.
|
||||||
* Postpone when it is \@<= or \@<!, these are expensive.
|
* Postpone when it is \@<= or \@<!, these are expensive.
|
||||||
* TODO: remove the check for t->pim and check multiple
|
|
||||||
* where it's used?
|
|
||||||
* Otherwise first do the one that has the highest chance
|
* Otherwise first do the one that has the highest chance
|
||||||
* of failing. */
|
* of failing. */
|
||||||
if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9)
|
if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9)
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
|| (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9)
|
|| (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9)
|
||||||
#endif
|
#endif
|
||||||
|| t->pim != NULL
|
|| t->pim.result != NFA_PIM_UNUSED
|
||||||
|| (t->state->c != NFA_START_INVISIBLE_BEFORE
|
|| (t->state->c != NFA_START_INVISIBLE_BEFORE
|
||||||
&& t->state->c != NFA_START_INVISIBLE_BEFORE_NEG
|
&& t->state->c != NFA_START_INVISIBLE_BEFORE_NEG
|
||||||
&& failure_chance(t->state->out1->out, 0)
|
&& failure_chance(t->state->out1->out, 0)
|
||||||
@@ -5052,7 +5118,7 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
* First try matching the invisible match, then what
|
* First try matching the invisible match, then what
|
||||||
* follows.
|
* follows.
|
||||||
*/
|
*/
|
||||||
result = recursive_regmatch(t->state, prog,
|
result = recursive_regmatch(t->state, NULL, prog,
|
||||||
submatch, m, &listids);
|
submatch, m, &listids);
|
||||||
|
|
||||||
/* for \@! and \@<! it is a match when the result is
|
/* for \@! and \@<! it is a match when the result is
|
||||||
@@ -5077,26 +5143,33 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
nfa_pim_T pim;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First try matching what follows at the current
|
* First try matching what follows. Only if a match
|
||||||
* position. Only if a match is found, before
|
* is found verify the invisible match matches. Add a
|
||||||
* addstate() is called, then verify the invisible
|
* nfa_pim_T to the following states, it contains info
|
||||||
* match matches. Add a nfa_pim_T to the following
|
* about the invisible match.
|
||||||
* states, it contains info about the invisible match.
|
|
||||||
*/
|
*/
|
||||||
if (ga_grow(&pimlist, 1) == FAIL)
|
pim.state = t->state;
|
||||||
goto theend;
|
pim.result = NFA_PIM_TODO;
|
||||||
pim = (nfa_pim_T *)pimlist.ga_data + pimlist.ga_len;
|
pim.subs.norm.in_use = 0;
|
||||||
++pimlist.ga_len;
|
#ifdef FEAT_SYN_HL
|
||||||
pim->state = t->state;
|
pim.subs.synt.in_use = 0;
|
||||||
pim->pim = NULL;
|
#endif
|
||||||
pim->result = NFA_PIM_TODO;
|
if (REG_MULTI)
|
||||||
|
{
|
||||||
|
pim.end.pos.col = (int)(reginput - regline);
|
||||||
|
pim.end.pos.lnum = reglnum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pim.end.ptr = reginput;
|
||||||
|
|
||||||
/* t->state->out1 is the corresponding END_INVISIBLE
|
/* t->state->out1 is the corresponding END_INVISIBLE
|
||||||
* node; Add its out to the current list (zero-width
|
* node; Add its out to the current list (zero-width
|
||||||
* match). */
|
* match). */
|
||||||
addstate_here(thislist, t->state->out1->out, &t->subs,
|
addstate_here(thislist, t->state->out1->out, &t->subs,
|
||||||
pim, &listidx);
|
&pim, &listidx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -5144,7 +5217,7 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* First try matching the pattern. */
|
/* First try matching the pattern. */
|
||||||
result = recursive_regmatch(t->state, prog,
|
result = recursive_regmatch(t->state, NULL, prog,
|
||||||
submatch, m, &listids);
|
submatch, m, &listids);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@@ -5798,12 +5871,18 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
|
|
||||||
if (add_state != NULL)
|
if (add_state != NULL)
|
||||||
{
|
{
|
||||||
/* Handle the postponed invisible match before advancing to
|
nfa_pim_T *pim;
|
||||||
* the next character and for a zero-width match if the match
|
|
||||||
* might end without advancing. */
|
if (t->pim.result == NFA_PIM_UNUSED)
|
||||||
if (t->pim != NULL && (!add_here || match_follows(add_state, 0)))
|
pim = NULL;
|
||||||
|
else
|
||||||
|
pim = &t->pim;
|
||||||
|
|
||||||
|
/* Handle the postponed invisible match if the match might end
|
||||||
|
* without advancing and before the end of the line. */
|
||||||
|
if (pim != NULL && (clen == 0 || match_follows(add_state, 0)))
|
||||||
{
|
{
|
||||||
if (t->pim->result == NFA_PIM_TODO)
|
if (pim->result == NFA_PIM_TODO)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
fprintf(log_fd, "\n");
|
fprintf(log_fd, "\n");
|
||||||
@@ -5811,58 +5890,60 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
fprintf(log_fd, "Postponed recursive nfa_regmatch()\n");
|
fprintf(log_fd, "Postponed recursive nfa_regmatch()\n");
|
||||||
fprintf(log_fd, "\n");
|
fprintf(log_fd, "\n");
|
||||||
#endif
|
#endif
|
||||||
result = recursive_regmatch(t->pim->state,
|
result = recursive_regmatch(pim->state, pim,
|
||||||
prog, submatch, m, &listids);
|
prog, submatch, m, &listids);
|
||||||
t->pim->result = result ? NFA_PIM_MATCH
|
pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH;
|
||||||
: NFA_PIM_NOMATCH;
|
|
||||||
/* for \@! and \@<! it is a match when the result is
|
/* for \@! and \@<! it is a match when the result is
|
||||||
* FALSE */
|
* FALSE */
|
||||||
if (result != (t->pim->state->c
|
if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
|
||||||
== NFA_START_INVISIBLE_NEG
|
|| pim->state->c
|
||||||
|| t->pim->state->c
|
|
||||||
== NFA_START_INVISIBLE_BEFORE_NEG))
|
== NFA_START_INVISIBLE_BEFORE_NEG))
|
||||||
{
|
{
|
||||||
/* Copy submatch info from the recursive call */
|
/* Copy submatch info from the recursive call */
|
||||||
copy_sub_off(&t->pim->subs.norm, &m->norm);
|
copy_sub_off(&pim->subs.norm, &m->norm);
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
if (nfa_has_zsubexpr)
|
if (nfa_has_zsubexpr)
|
||||||
copy_sub_off(&t->pim->subs.synt, &m->synt);
|
copy_sub_off(&pim->subs.synt, &m->synt);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = (t->pim->result == NFA_PIM_MATCH);
|
result = (pim->result == NFA_PIM_MATCH);
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
fprintf(log_fd, "\n");
|
fprintf(log_fd, "\n");
|
||||||
fprintf(log_fd, "Using previous recursive nfa_regmatch() result, result == %d\n", t->pim->result);
|
fprintf(log_fd, "Using previous recursive nfa_regmatch() result, result == %d\n", pim->result);
|
||||||
fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
|
fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
|
||||||
fprintf(log_fd, "\n");
|
fprintf(log_fd, "\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for \@! and \@<! it is a match when result is FALSE */
|
/* for \@! and \@<! it is a match when result is FALSE */
|
||||||
if (result != (t->pim->state->c == NFA_START_INVISIBLE_NEG
|
if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
|
||||||
|| t->pim->state->c
|
|| pim->state->c
|
||||||
== NFA_START_INVISIBLE_BEFORE_NEG))
|
== NFA_START_INVISIBLE_BEFORE_NEG))
|
||||||
{
|
{
|
||||||
/* Copy submatch info from the recursive call */
|
/* Copy submatch info from the recursive call */
|
||||||
copy_sub_off(&t->subs.norm, &t->pim->subs.norm);
|
copy_sub_off(&t->subs.norm, &pim->subs.norm);
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
if (nfa_has_zsubexpr)
|
if (nfa_has_zsubexpr)
|
||||||
copy_sub_off(&t->subs.synt, &t->pim->subs.synt);
|
copy_sub_off(&t->subs.synt, &pim->subs.synt);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* look-behind match failed, don't add the state */
|
/* look-behind match failed, don't add the state */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Postponed invisible match was handled, don't add it to
|
||||||
|
* following states. */
|
||||||
|
pim = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_here)
|
if (add_here)
|
||||||
addstate_here(thislist, add_state, &t->subs, t->pim, &listidx);
|
addstate_here(thislist, add_state, &t->subs, pim, &listidx);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addstate(nextlist, add_state, &t->subs, add_off);
|
addstate(nextlist, add_state, &t->subs, pim, add_off);
|
||||||
if (add_count > 0)
|
if (add_count > 0)
|
||||||
nextlist->t[nextlist->n - 1].count = add_count;
|
nextlist->t[nextlist->n - 1].count = add_count;
|
||||||
}
|
}
|
||||||
@@ -5941,11 +6022,11 @@ nfa_regmatch(prog, start, submatch, m)
|
|||||||
(colnr_T)(reginput - regline) + clen;
|
(colnr_T)(reginput - regline) + clen;
|
||||||
else
|
else
|
||||||
m->norm.list.line[0].start = reginput + clen;
|
m->norm.list.line[0].start = reginput + clen;
|
||||||
addstate(nextlist, start->out, m, clen);
|
addstate(nextlist, start->out, m, NULL, clen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addstate(nextlist, start, m, clen);
|
addstate(nextlist, start, m, NULL, clen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_LOG
|
#ifdef ENABLE_LOG
|
||||||
@@ -5982,7 +6063,6 @@ theend:
|
|||||||
vim_free(list[0].t);
|
vim_free(list[0].t);
|
||||||
vim_free(list[1].t);
|
vim_free(list[1].t);
|
||||||
vim_free(listids);
|
vim_free(listids);
|
||||||
ga_clear(&pimlist);
|
|
||||||
#undef ADD_STATE_IF_MATCH
|
#undef ADD_STATE_IF_MATCH
|
||||||
#ifdef NFA_REGEXP_DEBUG_LOG
|
#ifdef NFA_REGEXP_DEBUG_LOG
|
||||||
fclose(debug);
|
fclose(debug);
|
||||||
|
@@ -728,6 +728,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1153,
|
||||||
/**/
|
/**/
|
||||||
1152,
|
1152,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user