summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2013-05-29 21:14:42 +0200
committerBram Moolenaar <Bram@vim.org>2013-05-29 21:14:42 +0200
commit423532e10d7335750afbace57ba65c0b6f138756 (patch)
tree2192ae232cc2e3abd065d26bb8a8d7a4436e7e58
parent28c21919499319d26077aec1d40e54f5b8fbd367 (diff)
updated for version 7.3.1039v7.3.1039
Problem: New regexp engine does not support \%23c, \%<23c and the like. Solution: Implement them. (partly by Yasuhiro Matsumoto)
-rw-r--r--src/regexp.h1
-rw-r--r--src/regexp_nfa.c139
-rw-r--r--src/testdir/test64.in29
-rw-r--r--src/testdir/test64.ok30
-rw-r--r--src/version.c2
5 files changed, 180 insertions, 21 deletions
diff --git a/src/regexp.h b/src/regexp.h
index f8ff0962aa..69075b5f58 100644
--- a/src/regexp.h
+++ b/src/regexp.h
@@ -72,6 +72,7 @@ struct nfa_state
int id;
int lastlist;
int negated;
+ int val;
};
/*
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 88c813d2e2..bb8c982fe7 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -117,6 +117,18 @@ enum
NFA_NLOWER, /* Match non-lowercase char */
NFA_UPPER, /* Match uppercase char */
NFA_NUPPER, /* Match non-uppercase char */
+
+ NFA_CURSOR, /* Match cursor pos */
+ NFA_LNUM, /* Match line number */
+ NFA_LNUM_GT, /* Match > line number */
+ NFA_LNUM_LT, /* Match < line number */
+ NFA_COL, /* Match cursor column */
+ NFA_COL_GT, /* Match > cursor column */
+ NFA_COL_LT, /* Match < cursor column */
+ NFA_VCOL, /* Match cursor virtual column */
+ NFA_VCOL_GT, /* Match > cursor virtual column */
+ NFA_VCOL_LT, /* Match < cursor virtual column */
+
NFA_FIRST_NL = NFA_ANY + ADD_NL,
NFA_LAST_NL = NFA_NUPPER + ADD_NL,
@@ -205,10 +217,11 @@ static nfa_state_T *new_state __ARGS((int c, nfa_state_T *out, nfa_state_T *out1
static nfa_state_T *post2nfa __ARGS((int *postfix, int *end, int nfa_calc_size));
static int check_char_class __ARGS((int class, int c));
static void st_error __ARGS((int *postfix, int *end, int *p));
+static void nfa_set_neg_listids __ARGS((nfa_state_T *start));
+static void nfa_set_null_listids __ARGS((nfa_state_T *start));
static void nfa_save_listids __ARGS((nfa_state_T *start, int *list));
static void nfa_restore_listids __ARGS((nfa_state_T *start, int *list));
-static void nfa_set_null_listids __ARGS((nfa_state_T *start));
-static void nfa_set_neg_listids __ARGS((nfa_state_T *start));
+static int nfa_re_num_cmp __ARGS((long_u val, int op, long_u pos));
static long nfa_regtry __ARGS((nfa_state_T *start, colnr_T col));
static long nfa_regexec_both __ARGS((char_u *line, colnr_T col));
static regprog_T *nfa_regcomp __ARGS((char_u *expr, int re_flags));
@@ -831,8 +844,7 @@ nfa_regatom()
break;
case '#':
- /* TODO: not supported yet */
- return FAIL;
+ EMIT(NFA_CURSOR);
break;
case 'V':
@@ -844,23 +856,36 @@ nfa_regatom()
/* TODO: \%[abc] not supported yet */
return FAIL;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '<':
- case '>':
- case '\'':
- /* TODO: not supported yet */
- return FAIL;
-
default:
+ {
+ long_u n = 0;
+ int cmp = c;
+
+ if (c == '<' || c == '>')
+ c = getchr();
+ while (VIM_ISDIGIT(c))
+ {
+ n = n * 10 + (c - '0');
+ c = getchr();
+ }
+ if (c == 'l' || c == 'c' || c == 'v')
+ {
+ EMIT(n);
+ if (c == 'l')
+ EMIT(cmp == '<' ? NFA_LNUM_LT :
+ cmp == '>' ? NFA_LNUM_GT : NFA_LNUM);
+ else if (c == 'c')
+ EMIT(cmp == '<' ? NFA_COL_LT :
+ cmp == '>' ? NFA_COL_GT : NFA_COL);
+ else
+ EMIT(cmp == '<' ? NFA_VCOL_LT :
+ cmp == '>' ? NFA_VCOL_GT : NFA_VCOL);
+ break;
+ }
+ else if (c == '\'')
+ /* TODO: \%'m not supported yet */
+ return FAIL;
+ }
syntax_error = TRUE;
EMSGN(_("E867: (NFA) Unknown operator '\\%%%c'"),
no_Magic(c));
@@ -1679,6 +1704,8 @@ nfa_set_code(c)
case NFA_PREV_ATOM_NO_WIDTH:
STRCPY(code, "NFA_PREV_ATOM_NO_WIDTH"); break;
+ case NFA_PREV_ATOM_NO_WIDTH_NEG:
+ STRCPY(code, "NFA_PREV_ATOM_NO_WIDTH_NEG"); break;
case NFA_NOPEN: STRCPY(code, "NFA_MOPEN_INVISIBLE"); break;
case NFA_NCLOSE: STRCPY(code, "NFA_MCLOSE_INVISIBLE"); break;
case NFA_START_INVISIBLE: STRCPY(code, "NFA_START_INVISIBLE"); break;
@@ -2444,6 +2471,28 @@ post2nfa(postfix, end, nfa_calc_size)
PUSH(frag(s, list1(&s1->out)));
break;
+ case NFA_LNUM:
+ case NFA_LNUM_GT:
+ case NFA_LNUM_LT:
+ case NFA_VCOL:
+ case NFA_VCOL_GT:
+ case NFA_VCOL_LT:
+ case NFA_COL:
+ case NFA_COL_GT:
+ case NFA_COL_LT:
+ if (nfa_calc_size == TRUE)
+ {
+ nstate += 1;
+ break;
+ }
+ e1 = POP();
+ s = new_state(*p, NULL, NULL);
+ if (s == NULL)
+ goto theend;
+ s->val = e1.start->c;
+ PUSH(frag(s, list1(&s->out)));
+ break;
+
case NFA_ZSTART:
case NFA_ZEND:
default:
@@ -3076,6 +3125,17 @@ nfa_restore_listids(start, list)
}
}
+ static int
+nfa_re_num_cmp(val, op, pos)
+ long_u val;
+ int op;
+ long_u pos;
+{
+ if (op == 1) return pos > val;
+ if (op == 2) return pos < val;
+ return val == pos;
+}
+
static int nfa_regmatch __ARGS((nfa_state_T *start, regsub_T *submatch, regsub_T *m));
/*
@@ -3791,6 +3851,45 @@ nfa_regmatch(start, submatch, m)
/* TODO: should not happen? */
break;
+ case NFA_LNUM:
+ case NFA_LNUM_GT:
+ case NFA_LNUM_LT:
+ result = (REG_MULTI &&
+ nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
+ (long_u)(reglnum + reg_firstlnum)));
+ if (result)
+ addstate_here(thislist, t->state->out, &t->sub, &listidx);
+ break;
+
+ case NFA_COL:
+ case NFA_COL_GT:
+ case NFA_COL_LT:
+ result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL,
+ (long_u)(reginput - regline) + 1);
+ if (result)
+ addstate_here(thislist, t->state->out, &t->sub, &listidx);
+ break;
+
+ case NFA_VCOL:
+ case NFA_VCOL_GT:
+ case NFA_VCOL_LT:
+ result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_VCOL,
+ (long_u)win_linetabsize(
+ reg_win == NULL ? curwin : reg_win,
+ regline, (colnr_T)(reginput - regline)) + 1);
+ if (result)
+ addstate_here(thislist, t->state->out, &t->sub, &listidx);
+ break;
+
+ case NFA_CURSOR:
+ result = (reg_win != NULL
+ && (reglnum + reg_firstlnum == reg_win->w_cursor.lnum)
+ && ((colnr_T)(reginput - regline)
+ == reg_win->w_cursor.col));
+ if (result)
+ addstate_here(thislist, t->state->out, &t->sub, &listidx);
+ break;
+
default: /* regular character */
{
int c = t->state->c;
diff --git a/src/testdir/test64.in b/src/testdir/test64.in
index 667e194e16..192d456725 100644
--- a/src/testdir/test64.in
+++ b/src/testdir/test64.in
@@ -413,13 +413,40 @@ Gop:"
:.yank
y$Gop:"
:"
-:"
:" Check a pattern with a look beind crossing a line boundary
/^Behind:
/\(<\_[xy]\+\)\@3<=start
:.yank
Gop:"
:"
+:" Check patterns matching cursor position.
+:func! Postest()
+ new
+ call setline(1, ['ffooooo', 'boboooo', 'zoooooo', 'koooooo', 'moooooo', "\t\t\tfoo", 'abababababababfoo', 'bababababababafoo', '********_'])
+ call setpos('.', [0, 1, 0, 0])
+ s/\%>3c.//g
+ call setpos('.', [0, 2, 4, 0])
+ s/\%#.*$//g
+ call setpos('.', [0, 3, 0, 0])
+ s/\%<3c./_/g
+ %s/\%4l\%>5c./_/g
+ %s/\%6l\%>25v./_/g
+ %s/\%>6l\%3c./!/g
+ %s/\%>7l\%12c./?/g
+ %s/\%>7l\%<9l\%>5v\%<8v./#/g
+ 1,$yank
+ quit!
+endfunc
+Go-0-:set re=0
+:call Postest()
+:put
+o-1-:set re=1
+:call Postest()
+:put
+o-2-:set re=2
+:call Postest()
+:put
+:"
:/\%#=1^Results/,$wq! test.out
ENDTEST
diff --git a/src/testdir/test64.ok b/src/testdir/test64.ok
index 3b53d2451e..74db0bd09b 100644
--- a/src/testdir/test64.ok
+++ b/src/testdir/test64.ok
@@ -740,3 +740,33 @@ OK 1 - \(<<\)\@2<=span.
ghi
xxxstart3
+-0-
+ffo
+bob
+__ooooo
+koooo__
+moooooo
+ f__
+ab!babababababfoo
+ba!ab##abab?bafoo
+**!*****_
+-1-
+ffo
+bob
+__ooooo
+koooo__
+moooooo
+ f__
+ab!babababababfoo
+ba!ab##abab?bafoo
+**!*****_
+-2-
+ffo
+bob
+__ooooo
+koooo__
+moooooo
+ f__
+ab!babababababfoo
+ba!ab##abab?bafoo
+**!*****_
diff --git a/src/version.c b/src/version.c
index d51c249d8a..b9db33d255 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 */
/**/
+ 1039,
+/**/
1038,
/**/
1037,