static const char *match (const char *s, const char *p, struct Capture *cap) { init: /* using goto's to optimize tail recursion */ switch (*p) { case '(': { /* start capture */ const char *res; if (cap->level >= MAX_CAPT) lua_error("too many captures"); cap->capture[cap->level].init = s; cap->capture[cap->level].len = -1; cap->level++; if ((res=match(s, p+1, cap)) == NULL) /* match failed? */ cap->level--; /* undo capture */ return res; } case ')': { /* end capture */ int32 l = capture_to_close(cap); const char *res; cap->capture[l].len = s - cap->capture[l].init; /* close capture */ if ((res = match(s, p+1, cap)) == NULL) /* match failed? */ cap->capture[l].len = -1; /* undo capture */ return res; } case '\0': case '$': /* (possibly) end of pattern */ if (*p == 0 || (*(p+1) == 0 && s == cap->src_end)) return s; /* else go through */ default: { /* it is a pattern item */ const char *ep; /* get what is next */ const char *s1 = matchitem(s, p, cap, &ep); switch (*ep) { case '*': { /* repetition */ const char *res; if (s1 && s1>s && ((res=match(s1, p, cap)) != NULL)) return res; p=ep+1; goto init; /* else return match(s, ep+1, cap); */ } case '?': { /* optional */ const char *res; if (s1 && ((res=match(s1, ep+1, cap)) != NULL)) return res; p=ep+1; goto init; /* else return match(s, ep+1, cap); */ } case '-': { /* repetition */ const char *res; if ((res = match(s, ep+1, cap)) != NULL) return res; else if (s1 && s1>s) { s = s1; goto init; /* return match(s1, p, cap); */ } else return NULL; } default: if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, cap); */ else return NULL; } } } }
static const char *end_capture (MatchState *ms, const char *s, const char *p) { int l = capture_to_close(ms); const char *res; ms->capture[l].len = s - ms->capture[l].init; /* close capture */ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ return res; }
static const char *end_capture (lua_State *L, const char *s, const char *p, struct Capture *cap) { int l = capture_to_close(L, cap); const char *res; cap->capture[l].len = s - cap->capture[l].init; /* close capture */ if ((res = match(L, s, p+1, cap)) == NULL) /* match failed? */ cap->capture[l].len = -1; /* undo capture */ return res; }
static const char *end_capture(LuaMatchState *ms, const char *s,const char *p) { int l; const char *res; if(!capture_to_close(ms, &l)) return NULL; ms->capture[l].len = s - ms->capture[l].init; // close capture if ((res = match(ms, s, p)) == NULL) // match failed? ms->capture[l].len = CAP_UNFINISHED; // undo capture return res; }
static const char * end_capture(struct match_state *ms, const char *s, const char *p) { int l = capture_to_close(ms); const char *res; if (l == -1) return NULL; /* close capture */ ms->capture[l].len = s - ms->capture[l].init; /* undo capture if match failed */ if ((res = match(ms, s, p)) == NULL) ms->capture[l].len = CAP_UNFINISHED; return res; }
static char *match (char *s, char *p, int level) { init: /* using goto's to optimize tail recursion */ switch (*p) { case '(': /* start capture */ if (level >= MAX_CAPT) lua_error("too many captures"); capture[level].init = s; capture[level].len = -1; level++; p++; goto init; /* return match(s, p+1, level); */ case ')': { /* end capture */ int l = capture_to_close(level); char *res; capture[l].len = s - capture[l].init; /* close capture */ if ((res = match(s, p+1, level)) == NULL) /* match failed? */ capture[l].len = -1; /* undo capture */ return res; } case ESC: if (isdigit((unsigned char)(*(p+1)))) { /* capture */ int l = check_cap(*(p+1), level); if (strncmp(capture[l].init, s, capture[l].len) == 0) { /* return match(p+2, s+capture[l].len, level); */ p+=2; s+=capture[l].len; goto init; } else return NULL; } else if (*(p+1) == 'b') { /* balanced string */ if (*(p+2) == 0 || *(p+3) == 0) lua_error("bad balanced pattern specification"); s = matchbalance(s, *(p+2), *(p+3)); if (s == NULL) return NULL; else { /* return match(p+4, s, level); */ p+=4; goto init; } } else goto dflt; case '\0': case '$': /* (possibly) end of pattern */ if (*p == 0 || (*(p+1) == 0 && *s == 0)) { num_captures = level; return s; } else goto dflt; default: dflt: { /* it is a pattern item */ int m = luaL_singlematch(*s, p); char *ep = luaL_item_end(p); /* get what is next */ switch (*ep) { case '*': { /* repetition */ char *res; if (m && (res = match(s+1, p, level))) return res; p=ep+1; goto init; /* else return match(s, ep+1, level); */ } case '-': { /* repetition */ char *res; if ((res = match(s, ep+1, level)) != 0) return res; else if (m) { s++; goto init; /* return match(s+1, p, level); */ } else return NULL; } case '?': { /* optional */ char *res; if (m && (res = match(s+1, ep+1, level))) return res; p=ep+1; goto init; /* else return match(s, ep+1, level); */ } default: if (m) { s++; p=ep; goto init; } /* return match(s+1, ep, level); */ else return NULL; } } } }