📄 jsregexp.c
字号:
* Consecutize FLAT's if possible. */ if (t->kid) { while (t->next && t->next->op == REOP_FLAT && (jschar*)t->kid + t->u.flat.length == (jschar*)t->next->kid) { t->u.flat.length += t->next->u.flat.length; t->next = t->next->next; } } if (t->kid && (t->u.flat.length > 1)) { if (state->flags & JSREG_FOLD) pc[-1] = REOP_FLATi; else pc[-1] = REOP_FLAT; SET_ARG(pc, (jschar *)t->kid - state->cpbegin); pc += ARG_LEN; SET_ARG(pc, t->u.flat.length); pc += ARG_LEN; } else if (t->u.flat.chr < 256) { if (state->flags & JSREG_FOLD) pc[-1] = REOP_FLAT1i; else pc[-1] = REOP_FLAT1; *pc++ = (jsbytecode) t->u.flat.chr; } else { if (state->flags & JSREG_FOLD) pc[-1] = REOP_UCFLAT1i; else pc[-1] = REOP_UCFLAT1; SET_ARG(pc, t->u.flat.chr); pc += ARG_LEN; } break; case REOP_LPAREN: JS_ASSERT(emitStateSP); SET_ARG(pc, t->u.parenIndex); pc += ARG_LEN; emitStateSP->continueNode = t; emitStateSP->continueOp = REOP_RPAREN; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); t = (RENode *) t->kid; op = t->op; continue; case REOP_RPAREN: SET_ARG(pc, t->u.parenIndex); pc += ARG_LEN; break; case REOP_BACKREF: SET_ARG(pc, t->u.parenIndex); pc += ARG_LEN; break; case REOP_ASSERT: JS_ASSERT(emitStateSP); emitStateSP->nextTermFixup = pc; pc += OFFSET_LEN; emitStateSP->continueNode = t; emitStateSP->continueOp = REOP_ASSERTTEST; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); t = (RENode *) t->kid; op = t->op; continue; case REOP_ASSERTTEST: case REOP_ASSERTNOTTEST: diff = pc - emitStateSP->nextTermFixup; CHECK_OFFSET(diff); SET_OFFSET(emitStateSP->nextTermFixup, diff); break; case REOP_ASSERT_NOT: JS_ASSERT(emitStateSP); emitStateSP->nextTermFixup = pc; pc += OFFSET_LEN; emitStateSP->continueNode = t; emitStateSP->continueOp = REOP_ASSERTNOTTEST; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); t = (RENode *) t->kid; op = t->op; continue; case REOP_QUANT: JS_ASSERT(emitStateSP); if (t->u.range.min == 0 && t->u.range.max == (uint16)-1) { pc[-1] = (t->u.range.greedy) ? REOP_STAR : REOP_MINIMALSTAR; } else if (t->u.range.min == 0 && t->u.range.max == 1) { pc[-1] = (t->u.range.greedy) ? REOP_OPT : REOP_MINIMALOPT; } else if (t->u.range.min == 1 && t->u.range.max == (uint16) -1) { pc[-1] = (t->u.range.greedy) ? REOP_PLUS : REOP_MINIMALPLUS; } else { if (!t->u.range.greedy) pc[-1] = REOP_MINIMALQUANT; SET_ARG(pc, t->u.range.min); pc += ARG_LEN; SET_ARG(pc, t->u.range.max); pc += ARG_LEN; } emitStateSP->nextTermFixup = pc; pc += OFFSET_LEN; emitStateSP->continueNode = t; emitStateSP->continueOp = REOP_ENDCHILD; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); t = (RENode *) t->kid; op = t->op; continue; case REOP_ENDCHILD: diff = pc - emitStateSP->nextTermFixup; CHECK_OFFSET(diff); SET_OFFSET(emitStateSP->nextTermFixup, diff); break; case REOP_CLASS: if (!t->u.ucclass.sense) pc[-1] = REOP_NCLASS; SET_ARG(pc, t->u.ucclass.index); pc += ARG_LEN; charSet = &re->classList[t->u.ucclass.index]; charSet->converted = JS_FALSE; charSet->length = t->u.ucclass.bmsize; charSet->u.src.startIndex = t->u.ucclass.startIndex; charSet->u.src.length = t->u.ucclass.kidlen; charSet->sense = t->u.ucclass.sense; break; default: break; } t = t->next; if (!t) { if (emitStateSP == emitStateStack) break; --emitStateSP; t = emitStateSP->continueNode; op = emitStateSP->continueOp; } else op = t->op; } if (emitStateStack) JS_free(state->context, emitStateStack); return pc;}JSRegExp *js_NewRegExp(JSContext *cx, JSTokenStream *ts, JSString *str, uintN flags, JSBool flat){ JSRegExp *re; void *mark; CompilerState state; size_t resize; jsbytecode *endPC; uint32 i; size_t len; re = NULL; mark = JS_ARENA_MARK(&cx->tempPool); state.context = cx; state.tokenStream = ts; state.cpbegin = state.cp = JSSTRING_CHARS(str); state.cpend = state.cp + JSSTRING_LENGTH(str); state.flags = flags; state.parenCount = 0; state.classCount = 0; state.progLength = 0; state.treeDepth = 0; for (i = 0; i < CLASS_CACHE_SIZE; i++) state.classCache[i].start = NULL; len = JSSTRING_LENGTH(str); if (len != 0 && flat) { state.result = NewRENode(&state, REOP_FLAT); state.result->u.flat.chr = *state.cpbegin; state.result->u.flat.length = JSSTRING_LENGTH(str); state.result->kid = (void *) state.cpbegin; state.progLength += 5; } else { if (!ParseRegExp(&state)) goto out; } resize = sizeof *re + state.progLength + 1; re = (JSRegExp *) JS_malloc(cx, JS_ROUNDUP(resize, sizeof(jsword))); if (!re) goto out; re->classCount = state.classCount; if (state.classCount) { re->classList = (RECharSet *)JS_malloc(cx, sizeof(RECharSet) * state.classCount); if (!re->classList) goto out; } else re->classList = NULL; endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result); if (!endPC) { re = NULL; goto out; } *endPC++ = REOP_END; JS_ASSERT(endPC <= (re->program + (state.progLength + 1))); re->nrefs = 1; re->parenCount = state.parenCount; re->flags = flags; re->source = str;out: JS_ARENA_RELEASE(&cx->tempPool, mark); return re;}JSRegExp *js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, JSString *str, JSString *opt, JSBool flat){ uintN flags; jschar *s; size_t i, n; char charBuf[2]; flags = 0; if (opt) { s = JSSTRING_CHARS(opt); for (i = 0, n = JSSTRING_LENGTH(opt); i < n; i++) { switch (s[i]) { case 'g': flags |= JSREG_GLOB; break; case 'i': flags |= JSREG_FOLD; break; case 'm': flags |= JSREG_MULTILINE; break; default: charBuf[0] = (char)s[i]; charBuf[1] = '\0'; js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_BAD_FLAG, charBuf); return NULL; } } } return js_NewRegExp(cx, ts, str, flags, flat);}#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs)#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re)/* * Save the current state of the match - the position in the input * text as well as the position in the bytecode. The state of any * parent expressions is also saved (preceding state). * Contents of parenCount parentheses from parenIndex are also saved. */static REBackTrackData *PushBackTrackState(REGlobalData *gData, REOp op, jsbytecode *target, REMatchState *x, const jschar *cp, uintN parenIndex, intN parenCount){ intN i; REBackTrackData *result = (REBackTrackData *) ((char *)gData->backTrackSP + gData->cursz); size_t sz = sizeof(REBackTrackData) + gData->stateStackTop * sizeof(REProgState) + parenCount * sizeof(RECapture); ptrdiff_t btsize = gData->backTrackStackSize; ptrdiff_t btincr = ((char *)result + sz) - ((char *)gData->backTrackStack + btsize); if (btincr > 0) { ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack; btincr = JS_ROUNDUP(btincr, btsize); JS_ARENA_GROW_CAST(gData->backTrackStack, REBackTrackData *, &gData->pool, btsize, btincr); if (!gData->backTrackStack) return NULL; gData->backTrackStackSize = btsize + btincr; result = (REBackTrackData *) ((char *)gData->backTrackStack + offset); } gData->backTrackSP = result; result->sz = gData->cursz; gData->cursz = sz; result->backtrack_op = op; result->backtrack_pc = target; result->cp = cp; result->parenCount = parenCount; result->saveStateStackTop = gData->stateStackTop; JS_ASSERT(gData->stateStackTop); memcpy(result + 1, gData->stateStack, sizeof(REProgState) * result->saveStateStackTop); /* FIXME: parenCount should be uintN */ JS_ASSERT(parenCount >= 0); if (parenCount > 0) { result->parenIndex = parenIndex; memcpy((char *)(result + 1) + sizeof(REProgState) * result->saveStateStackTop, &x->parens[parenIndex], sizeof(RECapture) * parenCount); for (i = 0; i < parenCount; i++) x->parens[parenIndex + i].index = -1; } return result;}/* * Consecutive literal characters. */#if 0static REMatchState *FlatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, intN length){ intN i; if (x->cp + length > gData->cpend) return NULL; for (i = 0; i < length; i++) { if (matchChars[i] != x->cp[i]) return NULL; } x->cp += length; return x;}#endifstatic REMatchState *FlatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, intN length){ intN i; if (x->cp + length > gData->cpend) return NULL; for (i = 0; i < length; i++) { if (upcase(matchChars[i]) != upcase(x->cp[i])) return NULL; } x->cp += length; return x;}/* * 1. Evaluate DecimalEscape to obtain an EscapeValue E. * 2. If E is not a character then go to step 6. * 3. Let ch be E's character. * 4. Let A be a one-element RECharSet containing the character ch. * 5. Call CharacterSetMatcher(A, false) and return its Matcher result. * 6. E must be an integer. Let n be that integer. * 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception. * 8. Return an internal Matcher closure that takes two arguments, a State x * and a Continuation c, and performs the following: * 1. Le
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -