To: vim_dev@googlegroups.com Subject: Patch 7.3.1117 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.3.1117 Problem: New regexp engine: \%[abc] not supported. Solution: Implement \%[abc]. Add tests. Files: src/regexp_nfa.c, src/testdir/test64.in, src/testdir/test64.ok *** ../vim-7.3.1116/src/regexp_nfa.c 2013-06-05 11:01:59.000000000 +0200 --- src/regexp_nfa.c 2013-06-05 11:03:19.000000000 +0200 *************** *** 61,66 **** --- 61,67 ---- NFA_COMPOSING, /* Next nodes in NFA are part of the composing multibyte char */ NFA_END_COMPOSING, /* End of a composing char in the NFA */ + NFA_OPT_CHARS, /* \%[abc] */ /* The following are used only in the postfix form, not in the NFA */ NFA_PREV_ATOM_NO_WIDTH, /* Used for \@= */ *************** *** 972,979 **** #endif case '[': ! /* TODO: \%[abc] not supported yet */ ! return FAIL; default: { --- 973,993 ---- #endif case '[': ! { ! int n; ! ! /* \%[abc] */ ! for (n = 0; (c = getchr()) != ']'; ++n) ! { ! if (c == NUL) ! EMSG2_RET_FAIL(_(e_missing_sb), ! reg_magic == MAGIC_ALL); ! EMIT(c); ! } ! EMIT(NFA_OPT_CHARS); ! EMIT(n); ! break; ! } default: { *************** *** 989,995 **** } if (c == 'l' || c == 'c' || c == 'v') { - EMIT(n); if (c == 'l') /* \%{n}l \%{n}l */ EMIT(cmp == '<' ? NFA_LNUM_LT : --- 1003,1008 ---- *************** *** 1002,1015 **** /* \%{n}v \%{n}v */ EMIT(cmp == '<' ? NFA_VCOL_LT : cmp == '>' ? NFA_VCOL_GT : NFA_VCOL); break; } else if (c == '\'' && n == 0) { /* \%'m \%<'m \%>'m */ - EMIT(getchr()); EMIT(cmp == '<' ? NFA_MARK_LT : cmp == '>' ? NFA_MARK_GT : NFA_MARK); break; } } --- 1015,1029 ---- /* \%{n}v \%{n}v */ EMIT(cmp == '<' ? NFA_VCOL_LT : cmp == '>' ? NFA_VCOL_GT : NFA_VCOL); + EMIT(n); break; } else if (c == '\'' && n == 0) { /* \%'m \%<'m \%>'m */ EMIT(cmp == '<' ? NFA_MARK_LT : cmp == '>' ? NFA_MARK_GT : NFA_MARK); + EMIT(getchr()); break; } } *************** *** 1885,1890 **** --- 1899,1905 ---- case NFA_COMPOSING: STRCPY(code, "NFA_COMPOSING"); break; case NFA_END_COMPOSING: STRCPY(code, "NFA_END_COMPOSING"); break; + case NFA_OPT_CHARS: STRCPY(code, "NFA_OPT_CHARS"); break; case NFA_MOPEN: case NFA_MOPEN1: *************** *** 2558,2567 **** --- 2573,2621 ---- PUSH(frag(s, list1(&s->out))); break; + case NFA_OPT_CHARS: + { + int n; + + /* \%[abc] */ + n = *++p; /* get number of characters */ + if (nfa_calc_size == TRUE) + { + nstate += n; + break; + } + e1.out = NULL; /* stores list with out1's */ + s1 = NULL; /* previous NFA_SPLIT to connect to */ + while (n-- > 0) + { + e = POP(); /* get character */ + s = alloc_state(NFA_SPLIT, e.start, NULL); + if (s == NULL) + goto theend; + if (e1.out == NULL) + e1 = e; + patch(e.out, s1); + append(e1.out, list1(&s->out1)); + s1 = s; + } + PUSH(frag(s, e1.out)); + break; + } + case NFA_PREV_ATOM_NO_WIDTH: case NFA_PREV_ATOM_NO_WIDTH_NEG: case NFA_PREV_ATOM_JUST_BEFORE: case NFA_PREV_ATOM_JUST_BEFORE_NEG: + { + int neg = (*p == NFA_PREV_ATOM_NO_WIDTH_NEG + || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG); + int before = (*p == NFA_PREV_ATOM_JUST_BEFORE + || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG); + int n; + + if (before) + n = *++p; /* get the count */ + /* The \@= operator: match the preceding atom with zero width. * The \@! operator: no match for the preceding atom. * The \@<= operator: match for the preceding atom. *************** *** 2583,2603 **** s = alloc_state(NFA_START_INVISIBLE, e.start, s1); if (s == NULL) goto theend; ! if (*p == NFA_PREV_ATOM_NO_WIDTH_NEG ! || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG) { s->negated = TRUE; s1->negated = TRUE; } ! if (*p == NFA_PREV_ATOM_JUST_BEFORE ! || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG) { ! s->val = *++p; /* get the count */ ++s->c; /* NFA_START_INVISIBLE -> NFA_START_INVISIBLE_BEFORE */ } PUSH(frag(s, list1(&s1->out))); break; #ifdef FEAT_MBYTE case NFA_COMPOSING: /* char with composing char */ --- 2637,2656 ---- s = alloc_state(NFA_START_INVISIBLE, e.start, s1); if (s == NULL) goto theend; ! if (neg) { s->negated = TRUE; s1->negated = TRUE; } ! if (before) { ! s->val = n; /* store the count */ ++s->c; /* NFA_START_INVISIBLE -> NFA_START_INVISIBLE_BEFORE */ } PUSH(frag(s, list1(&s1->out))); break; + } #ifdef FEAT_MBYTE case NFA_COMPOSING: /* char with composing char */ *************** *** 2750,2767 **** case NFA_MARK: case NFA_MARK_GT: case NFA_MARK_LT: if (nfa_calc_size == TRUE) { nstate += 1; break; } ! e1 = POP(); ! s = alloc_state(*p, NULL, NULL); if (s == NULL) goto theend; ! s->val = e1.start->c; /* lnum, col or mark name */ PUSH(frag(s, list1(&s->out))); break; case NFA_ZSTART: case NFA_ZEND: --- 2803,2823 ---- case NFA_MARK: case NFA_MARK_GT: case NFA_MARK_LT: + { + int n = *++p; /* lnum, col or mark name */ + if (nfa_calc_size == TRUE) { nstate += 1; break; } ! s = alloc_state(p[-1], NULL, NULL); if (s == NULL) goto theend; ! s->val = n; PUSH(frag(s, list1(&s->out))); break; + } case NFA_ZSTART: case NFA_ZEND: *** ../vim-7.3.1116/src/testdir/test64.in 2013-06-04 21:27:33.000000000 +0200 --- src/testdir/test64.in 2013-06-04 23:45:44.000000000 +0200 *************** *** 352,357 **** --- 352,370 ---- :call add(tl, [2, '\%u0020', 'yes no', ' ']) :call add(tl, [2, '\%U00000020', 'yes no', ' ']) :" + :""""" \%[abc] + :call add(tl, [2, 'foo\%[bar]', 'fobar']) + :call add(tl, [2, 'foo\%[bar]', 'foobar', 'foobar']) + :call add(tl, [2, 'foo\%[bar]', 'fooxx', 'foo']) + :call add(tl, [2, 'foo\%[bar]', 'foobxx', 'foob']) + :call add(tl, [2, 'foo\%[bar]', 'foobaxx', 'fooba']) + :call add(tl, [2, 'foo\%[bar]', 'foobarxx', 'foobar']) + :call add(tl, [2, 'foo\%[bar]x', 'foobxx', 'foobx']) + :call add(tl, [2, 'foo\%[bar]x', 'foobarxx', 'foobarx']) + :call add(tl, [2, '\%[bar]x', 'barxx', 'barx']) + :call add(tl, [2, '\%[bar]x', 'bxx', 'bx']) + :call add(tl, [2, '\%[bar]x', 'xxx', 'x']) + :" :"""" Alternatives, must use first longest match :call add(tl, [2, 'goo\|go', 'google', 'goo']) :call add(tl, [2, '\