📄 regexp.c
字号:
else if (OP(next) >= BRACE_COMPLEX &&
OP(next) < BRACE_COMPLEX + 10)
{
no = OP(next) - BRACE_COMPLEX;
brace_min[no] = OPERAND_MIN(scan);
brace_max[no] = OPERAND_MAX(scan);
brace_count[no] = 0;
}
else
{
emsg(e_internal); /* Shouldn't happen */
return 0;
}
}
break;
case BRACE_COMPLEX + 0:
case BRACE_COMPLEX + 1:
case BRACE_COMPLEX + 2:
case BRACE_COMPLEX + 3:
case BRACE_COMPLEX + 4:
case BRACE_COMPLEX + 5:
case BRACE_COMPLEX + 6:
case BRACE_COMPLEX + 7:
case BRACE_COMPLEX + 8:
case BRACE_COMPLEX + 9:
{
int no;
char_u *save;
no = OP(scan) - BRACE_COMPLEX;
++brace_count[no];
/* If not matched enough times yet, try one more */
if (brace_count[no] <= (brace_min[no] <= brace_max[no]
? brace_min[no] : brace_max[no]))
{
save = reginput;
if (regmatch(OPERAND(scan)))
return 1;
reginput = save;
--brace_count[no]; /* failed, decrement match count */
return 0;
}
/* If matched enough times, may try matching some more */
if (brace_min[no] <= brace_max[no])
{
/* Range is the normal way around, use longest match */
if (brace_count[no] <= brace_max[no])
{
save = reginput;
if (regmatch(OPERAND(scan)))
return 1; /* matched some more times */
reginput = save;
--brace_count[no]; /* matched just enough times */
/* continue with the items after \{} */
}
}
else
{
/* Range is backwards, use shortest match first */
if (brace_count[no] <= brace_min[no])
{
save = reginput;
if (regmatch(next))
return 1;
reginput = save;
next = OPERAND(scan);
/* must try to match one more item */
}
}
}
break;
case BRACE_SIMPLE:
case STAR:
case PLUS:
{
int nextch;
int nextch_ic;
int no;
char_u *save;
/*
* Lookahead to avoid useless match attempts when we know
* what character comes next.
*/
if (OP(next) == EXACTLY)
{
nextch = *OPERAND(next);
if (reg_ic)
{
if (isupper(nextch))
nextch_ic = TO_LOWER(nextch);
else
nextch_ic = TO_UPPER(nextch);
}
else
nextch_ic = nextch;
}
else
{
nextch = '\0';
nextch_ic = '\0';
}
if (OP(scan) != BRACE_SIMPLE)
{
minval = (OP(scan) == STAR) ? 0 : 1;
maxval = MAX_LIMIT;
}
save = reginput;
no = regrepeat(OPERAND(scan));
if (minval <= maxval)
{
/* Range is the normal way around, use longest match */
if (no > maxval)
{
no = maxval;
reginput = save + no;
}
while (no >= minval)
{
/* If it could work, try it. */
if (nextch == '\0' || *reginput == nextch
|| *reginput == nextch_ic)
if (regmatch(next))
return 1;
/* Couldn't or didn't -- back up. */
no--;
reginput = save + no;
}
}
else
{
/* Range is backwards, use shortest match first */
if (no < maxval)
return 0;
if (minval > no)
minval = no; /* Actually maximum value */
no = maxval;
reginput = save + no;
while (no <= minval)
{
/* If it could work, try it. */
if (nextch == '\0' || *reginput == nextch
|| *reginput == nextch_ic)
if (regmatch(next))
return 1;
/* Couldn't or didn't -- try longer match. */
no++;
reginput = save + no;
}
}
return 0;
}
/* break; Not Reached */
case END:
return 1; /* Success! */
/* break; Not Reached */
default:
emsg(e_re_corr);
#ifdef DEBUG
printf("Illegal op code %d\n", OP(scan));
#endif
return 0;
/* break; Not Reached */
}
scan = next;
}
/*
* We get here only if there's trouble -- normally "case END" is the
* terminating point.
*/
emsg(e_re_corr);
#ifdef DEBUG
printf("Premature EOL\n");
#endif
return 0;
}
/*
* regrepeat - repeatedly match something simple, report how many
*/
static int
regrepeat(p)
char_u *p;
{
int count = 0;
char_u *scan;
char_u *opnd;
int mask;
scan = reginput;
opnd = OPERAND(p);
switch (OP(p))
{
case ANY:
count = STRLEN(scan);
scan += count;
break;
case IDENT:
for (count = 0; vim_isIDc(*scan); ++count)
++scan;
break;
case KWORD:
for (count = 0; vim_iswordc(*scan); ++count)
++scan;
break;
case FNAME:
for (count = 0; vim_isfilec(*scan); ++count)
++scan;
break;
case PRINT:
for (count = 0; charsize(*scan) == 1; ++count)
++scan;
break;
case SIDENT:
for (count = 0; !isdigit(*scan) && vim_isIDc(*scan); ++count)
++scan;
break;
case SWORD:
for (count = 0; !isdigit(*scan) && vim_iswordc(*scan); ++count)
++scan;
break;
case SFNAME:
for (count = 0; !isdigit(*scan) && vim_isfilec(*scan); ++count)
++scan;
break;
case SPRINT:
for (count = 0; !isdigit(*scan) && charsize(*scan) == 1; ++count)
++scan;
break;
case WHITE:
for (count = 0; vim_iswhite(*scan); ++count)
++scan;
break;
case NWHITE:
for (count = 0; *scan != NUL && !vim_iswhite(*scan); ++count)
++scan;
break;
case DIGIT:
mask = RI_DIGIT;
do_class:
for (count = 0; class_tab[*scan] & mask; ++count)
++scan;
break;
case NDIGIT:
mask = RI_DIGIT;
do_nclass:
for (count = 0; *scan != NUL && !(class_tab[*scan] & mask); ++count)
++scan;
break;
case HEX:
mask = RI_HEX;
goto do_class;
case NHEX:
mask = RI_HEX;
goto do_nclass;
case OCTAL:
mask = RI_OCTAL;
goto do_class;
case NOCTAL:
mask = RI_OCTAL;
goto do_nclass;
case WORD:
mask = RI_WORD;
goto do_class;
case NWORD:
mask = RI_WORD;
goto do_nclass;
case HEAD:
mask = RI_HEAD;
goto do_class;
case NHEAD:
mask = RI_HEAD;
goto do_nclass;
case ALPHA:
mask = RI_ALPHA;
goto do_class;
case NALPHA:
mask = RI_ALPHA;
goto do_nclass;
case LOWER:
mask = RI_LOWER;
goto do_class;
case NLOWER:
mask = RI_LOWER;
goto do_nclass;
case UPPER:
mask = RI_UPPER;
goto do_class;
case NUPPER:
mask = RI_UPPER;
goto do_nclass;
case EXACTLY:
{
int cu, cl;
if (reg_ic)
{
cu = TO_UPPER(*opnd);
cl = TO_LOWER(*opnd);
while (*scan == cu || *scan == cl)
{
count++;
scan++;
}
}
else
{
cu = *opnd;
while (*scan == cu)
{
count++;
scan++;
}
}
break;
}
case ANYOF:
while (*scan != '\0' && cstrchr(opnd, *scan) != NULL)
{
count++;
scan++;
}
break;
case ANYBUT:
while (*scan != '\0' && cstrchr(opnd, *scan) == NULL)
{
count++;
scan++;
}
break;
default: /* Oh dear. Called inappropriately. */
emsg(e_re_corr);
#ifdef DEBUG
printf("Called regrepeat with op code %d\n", OP(p));
#endif
count = 0; /* Best compromise. */
break;
}
reginput = scan;
return count;
}
/*
* regnext - dig the "next" pointer out of a node
*/
static char_u *
regnext(p)
char_u *p;
{
int offset;
if (p == JUST_CALC_SIZE)
return NULL;
offset = NEXT(p);
if (offset == 0)
return NULL;
if (OP(p) == BACK)
return p - offset;
else
return p + offset;
}
#ifdef DEBUG
/*
* regdump - dump a regexp onto stdout in vaguely comprehensible form
*/
static void
regdump(pattern, r)
char_u *pattern;
vim_regexp *r;
{
char_u *s;
int op = EXACTLY; /* Arbitrary non-END op. */
char_u *next;
printf("\nregcomp(%s):\n", pattern);
s = r->program + 1;
while (op != END) /* While that wasn't END last time... */
{
op = OP(s);
printf("%2d%s", (int)(s - r->program), regprop(s)); /* Where, what. */
next = regnext(s);
if (next == NULL) /* Next ptr. */
printf("(0)");
else
printf("(%d)", (int)((s - r->program) + (next - s)));
if (op == BRACE_LIMITS)
{
/* Two short ints */
printf(" minval %d, maxval %d", OPERAND_MIN(s), OPERAND_MAX(s));
s += 4;
}
s += 3;
if (op == ANYOF || op == ANYBUT || op == EXACTLY)
{
/* Literal string, where present. */
while (*s != '\0')
printf("%c", *s++);
s++;
}
printf("\n");
}
/* Header fields of interest. */
if (r->regstart != '\0')
printf("start `%c' ", r->regstart);
if (r->reganch)
printf("anchored ");
if (r->regmust != NULL)
printf("must have \"%s\"", r->regmust);
printf("\n");
}
/*
* regprop - printable representation of opcode
*/
static char_u *
regprop(op)
char_u *op;
{
char_u *p;
static char_u buf[50];
(void) strcpy(buf, ":");
switch (OP(op))
{
case BOL:
p = "BOL";
break;
case EOL:
p = "EOL";
break;
case BOW:
p = "BOW";
break;
case EOW:
p = "EOW";
break;
case ANY:
p = "ANY";
break;
case IDENT:
p = "IDENT";
break;
case KWORD:
p = "KWORD";
break;
case FNAME:
p = "FNAME";
break;
case PRINT:
p = "PRINT";
break;
case SIDENT:
p = "SIDENT";
break;
case SWORD:
p = "SWORD";
break;
case SFNAME:
p = "SFNAME";
break;
case SPRINT:
p = "SPRINT";
break;
case WHITE:
p = "WHITE";
break;
case NWHITE:
p = "NWHITE";
break;
case DIGIT:
p = "DIGIT";
break;
case NDIGIT:
p = "NDIGIT";
break;
case HEX:
p = "HEX";
break;
case NHEX:
p = "NHEX";
break;
case OCTAL:
p = "OCTAL";
break;
case NOCTAL:
p = "NOCTAL";
break;
case WORD:
p = "WORD";
break;
case NWORD:
p = "NWORD";
break;
case HEAD:
p = "HEAD";
break;
case NHEAD:
p = "NHEAD";
break;
case ALPHA:
p = "ALPHA";
break;
case NALPHA:
p = "NALPHA";
break;
case LOWER:
p = "LOWER";
break;
case NLOWER:
p = "NLOWER";
break;
case UPPER:
p = "UPPER";
break;
case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -