changeset 4583:321cfbef9431 v7.3.1039

updated for version 7.3.1039 Problem: New regexp engine does not support \%23c, \%<23c and the like. Solution: Implement them. (partly by Yasuhiro Matsumoto)
author Bram Moolenaar <bram@vim.org>
date Wed, 29 May 2013 21:14:42 +0200
parents 39d830de8c09
children b29aa7bbe18b
files src/regexp.h src/regexp_nfa.c src/testdir/test64.in src/testdir/test64.ok src/version.c
diffstat 5 files changed, 180 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/regexp.h
+++ b/src/regexp.h
@@ -72,6 +72,7 @@ struct nfa_state
     int			id;
     int			lastlist;
     int			negated;
+    int			val;
 };
 
 /*
--- 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((in
 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;
--- 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
 
--- a/src/testdir/test64.ok
+++ b/src/testdir/test64.ok
@@ -740,3 +740,33 @@ 192.168.0.1
 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
+**!*****_
--- 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,