static const char *match (lua_State *L, const char *s, const char *p,
                          struct Capture *cap) {
init: /* using goto's to optimize tail recursion */
    switch (*p) {
    case '(':  /* start capture */
        return start_capture(L, s, p, cap);
    case ')':  /* end capture */
        return end_capture(L, s, p, cap);
    case ESC:  /* may be %[0-9] or %b */
        if (isdigit((unsigned char)(*(p+1)))) {  /* capture? */
            s = match_capture(L, s, *(p+1), cap);
            if (s == NULL) return NULL;
            p+=2;
            goto init;  /* else return match(L, s, p+2, cap) */
        }
        else if (*(p+1) == 'b') {  /* balanced string? */
            s = matchbalance(L, s, p+2, cap);
            if (s == NULL) return NULL;
            p+=4;
            goto init;  /* else return match(L, s, p+4, cap); */
        }
        else goto dflt;  /* case default */
    case '\0':  /* end of pattern */
        return s;  /* match succeeded */
    case '$':
        if (*(p+1) == '\0')  /* is the '$' the last char in pattern? */
            return (s == cap->src_end) ? s : NULL;  /* check end of string */
        else goto dflt;
    default:
dflt: {  /* it is a pattern item */
            const char *ep = luaI_classend(L, p);  /* points to what is next */
            int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep);
            switch (*ep) {
            case '?': {  /* optional */
                const char *res;
                if (m && ((res=match(L, s+1, ep+1, cap)) != NULL))
                    return res;
                p=ep+1;
                goto init;  /* else return match(L, s, ep+1, cap); */
            }
            case '*':  /* 0 or more repetitions */
                return max_expand(L, s, p, ep, cap);
            case '+':  /* 1 or more repetitions */
                return (m ? max_expand(L, s+1, p, ep, cap) : NULL);
            case '-':  /* 0 or more repetitions (minimum) */
                return min_expand(L, s, p, ep, cap);
            default:
                if (!m) return NULL;
                s++;
                p=ep;
                goto init;  /* else return match(L, s+1, ep, cap); */
            }
        }
    }
}
Exemple #2
0
static const lua_WChar *match (MatchState *ms, const lua_WChar *s, const lua_WChar *p) {
  init: /* using goto's to optimize tail recursion */
  switch (*p) {
    case '(':  /* start capture */
      if (*(p+1) == ')')  /* position capture? */
        return start_capture(ms, s, p+2, CAP_POSITION);
      else
        return start_capture(ms, s, p+1, CAP_UNFINISHED);
    case ')':  /* end capture */
      return end_capture(ms, s, p+1);
    case ESC:  /* may be %[0-9] or %b */
      if (iswdigit(*(p+1))) {  /* capture? */
        s = match_capture(ms, s, *(p+1));
        if (s == NULL) return NULL;
        p+=2; goto init;  /* else return match(ms, s, p+2) */
      }
      else if (*(p+1) == 'b') {  /* balanced string? */
        s = matchbalance(ms, s, p+2);
        if (s == NULL) return NULL;
        p+=4; goto init;  /* else return match(ms, s, p+4); */
      }
      else goto dflt;  /* case default */
    case '\0':  /* end of pattern */
      return s;  /* match succeeded */
    case '$':
      if (*(p+1) == '\0')  /* is the `$' the last char in pattern? */
        return (s == ms->src_end) ? s : NULL;  /* check end of string */
      else goto dflt;
    default: dflt: {  /* it is a pattern item */
      const lua_WChar *ep = luaI_classend(ms, p);  /* points to what is next */
      int m = s<ms->src_end && luaI_singlematch(*s, p, ep);
      switch (*ep) {
        case '?': {  /* optional */
          const lua_WChar *res;
          if (m && ((res=match(ms, s+1, ep+1)) != NULL))
            return res;
          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */
        }
        case '*':  /* 0 or more repetitions */
          return max_expand(ms, s, p, ep);
        case '+':  /* 1 or more repetitions */
          return (m ? max_expand(ms, s+1, p, ep) : NULL);
        case '-':  /* 0 or more repetitions (minimum) */
          return min_expand(ms, s, p, ep);
        default:
          if (!m) return NULL;
          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */
      }
    }
  }
}
Exemple #3
0
static int read_pattern (lua_State *L, FILE *f, const char *p) {
  int inskip = 0;  /* {skip} level */
  int c = NEED_OTHER;
  luaL_Buffer b;
  luaL_buffinit(L, &b);
  while (*p != '\0') {
    switch (*p) {
      case '{':
        inskip++;
        p++;
        continue;
      case '}':
        if (!inskip) lua_error(L, "unbalanced braces in read pattern");
        inskip--;
        p++;
        continue;
      default: {
        const char *ep = luaI_classend(L, p);  /* get what is next */
        int m;  /* match result */
        if (c == NEED_OTHER) c = getc(f);
        m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
        if (m) {
          if (!inskip) luaL_putchar(&b, c);
          c = NEED_OTHER;
        }
        switch (*ep) {
          case '+':  /* repetition (1 or more) */
            if (!m) goto break_while;  /* pattern fails? */
            /* else go through */
          case '*':  /* repetition (0 or more) */
            while (m) {  /* reads the same item until it fails */
              c = getc(f);
              m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
              if (m && !inskip) luaL_putchar(&b, c);
            }
            /* go through to continue reading the pattern */
          case '?':  /* optional */
            p = ep+1;  /* continues reading the pattern */
            continue;
          default:
            if (!m) goto break_while;  /* pattern fails? */
            p = ep;  /* else continues reading the pattern */
        }
      }
    }
  } break_while:
  if (c != NEED_OTHER) ungetc(c, f);
  luaL_pushresult(&b);  /* close buffer */
  return (*p == '\0');
}
static const char *match (MatchState *ms, const char *s, const char *p) {
  init: /* using goto's to optimize tail recursion */
  switch (*p) {
    case '(': {  /* start capture */
      if (*(p+1) == ')')  /* position capture? */
        return start_capture(ms, s, p+2, CAP_POSITION);
      else
        return start_capture(ms, s, p+1, CAP_UNFINISHED);
    }
    case ')': {  /* end capture */
      return end_capture(ms, s, p+1);
    }
    case ESC: {
      switch (*(p+1)) {
        case 'b': {  /* balanced string? */
          s = matchbalance(ms, s, p+2);
          if (s == NULL) return NULL;
          p+=4; goto init;  /* else return match(ms, s, p+4); */
        }
        case 'f': {  /* frontier? */
          const char *ep; char previous;
          p += 2;
          if (*p != '[')
            luaL_error(ms->L, "missing `[' after `%%f' in pattern");
          ep = luaI_classend(ms, p);  /* points to what is next */
          previous = (s == ms->src_init) ? '\0' : *(s-1);
          if (matchbracketclass(uchar(previous), p, ep-1) ||
             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
          p=ep; goto init;  /* else return match(ms, s, ep); */
        }
        default: {
          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */
            s = match_capture(ms, s, *(p+1));
            if (s == NULL) return NULL;
            p+=2; goto init;  /* else return match(ms, s, p+2) */
          }
          goto dflt;  /* case default */
        }
      }
    }
    case '\0': {  /* end of pattern */
      return s;  /* match succeeded */
    }
    case '$': {
      if (*(p+1) == '\0')  /* is the `$' the last char in pattern? */
        return (s == ms->src_end) ? s : NULL;  /* check end of string */
      else goto dflt;
    }
    default: dflt: {  /* it is a pattern item */
      const char *ep = luaI_classend(ms, p);  /* points to what is next */
      int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
      switch (*ep) {
        case '?': {  /* optional */
          const char *res;
          if (m && ((res=match(ms, s+1, ep+1)) != NULL))
            return res;
          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */
        }
        case '*': {  /* 0 or more repetitions */
          return max_expand(ms, s, p, ep);
        }
        case '+': {  /* 1 or more repetitions */
          return (m ? max_expand(ms, s+1, p, ep) : NULL);
        }
        case '-': {  /* 0 or more repetitions (minimum) */
          return min_expand(ms, s, p, ep);
        }
        default: {
          if (!m) return NULL;
          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */
        }
      }
    }
  }
}