?? regexpimpl.java
字號:
* Analog of REGEXP_PAREN_SUBSTRING in C jsregexp.h. * Assumes zero-based; i.e., for $3, i==2 */ SubString getParenSubString(int i) { if (parens != null && i < parens.length) { SubString parsub = parens[i]; if (parsub != null) { return parsub; } } return SubString.emptySubString; } /* * Analog of match_glob() in jsstr.c */ private static void match_glob(GlobData mdata, Context cx, Scriptable scope, int count, RegExpImpl reImpl) { if (mdata.arrayobj == null) { Scriptable s = ScriptableObject.getTopLevelScope(scope); mdata.arrayobj = ScriptRuntime.newObject(cx, s, "Array", null); } SubString matchsub = reImpl.lastMatch; String matchstr = matchsub.toString(); mdata.arrayobj.put(count, mdata.arrayobj, matchstr); } /* * Analog of replace_glob() in jsstr.c */ private static void replace_glob(GlobData rdata, Context cx, Scriptable scope, RegExpImpl reImpl, int leftIndex, int leftlen) { int replen; String lambdaStr; if (rdata.lambda != null) { // invoke lambda function with args lastMatch, $1, $2, ... $n, // leftContext.length, whole string. SubString[] parens = reImpl.parens; int parenCount = (parens == null) ? 0 : parens.length; Object[] args = new Object[parenCount + 3]; args[0] = reImpl.lastMatch.toString(); for (int i=0; i < parenCount; i++) { SubString sub = parens[i]; if (sub != null) { args[i+1] = sub.toString(); } else { args[i+1] = Undefined.instance; } } args[parenCount+1] = new Integer(reImpl.leftContext.length); args[parenCount+2] = rdata.str; // This is a hack to prevent expose of reImpl data to // JS function which can run new regexps modifing // regexp that are used later by the engine. // TODO: redesign is necessary if (reImpl != ScriptRuntime.getRegExpProxy(cx)) Kit.codeBug(); RegExpImpl re2 = new RegExpImpl(); re2.multiline = reImpl.multiline; re2.input = reImpl.input; ScriptRuntime.setRegExpProxy(cx, re2); try { Scriptable parent = ScriptableObject.getTopLevelScope(scope); Object result = rdata.lambda.call(cx, parent, parent, args); lambdaStr = ScriptRuntime.toString(result); } finally { ScriptRuntime.setRegExpProxy(cx, reImpl); } replen = lambdaStr.length(); } else { lambdaStr = null; replen = rdata.repstr.length(); if (rdata.dollar >= 0) { int[] skip = new int[1]; int dp = rdata.dollar; do { SubString sub = interpretDollar(cx, reImpl, rdata.repstr, dp, skip); if (sub != null) { replen += sub.length - skip[0]; dp += skip[0]; } else { ++dp; } dp = rdata.repstr.indexOf('$', dp); } while (dp >= 0); } } int growth = leftlen + replen + reImpl.rightContext.length; StringBuffer charBuf = rdata.charBuf; if (charBuf == null) { charBuf = new StringBuffer(growth); rdata.charBuf = charBuf; } else { charBuf.ensureCapacity(rdata.charBuf.length() + growth); } charBuf.append(reImpl.leftContext.charArray, leftIndex, leftlen); if (rdata.lambda != null) { charBuf.append(lambdaStr); } else { do_replace(rdata, cx, reImpl); } } private static SubString interpretDollar(Context cx, RegExpImpl res, String da, int dp, int[] skip) { char dc; int num, tmp; if (da.charAt(dp) != '$') Kit.codeBug(); /* Allow a real backslash (literal "\\") to escape "$1" etc. */ int version = cx.getLanguageVersion(); if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4) { if (dp > 0 && da.charAt(dp - 1) == '\\') return null; } int daL = da.length(); if (dp + 1 >= daL) return null; /* Interpret all Perl match-induced dollar variables. */ dc = da.charAt(dp + 1); if (NativeRegExp.isDigit(dc)) { int cp; if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4) { if (dc == '0') return null; /* Check for overflow to avoid gobbling arbitrary decimal digits. */ num = 0; cp = dp; while (++cp < daL && NativeRegExp.isDigit(dc = da.charAt(cp))) { tmp = 10 * num + (dc - '0'); if (tmp < num) break; num = tmp; } } else { /* ECMA 3, 1-9 or 01-99 */ int parenCount = (res.parens == null) ? 0 : res.parens.length; num = dc - '0'; if (num > parenCount) return null; cp = dp + 2; if ((dp + 2) < daL) { dc = da.charAt(dp + 2); if (NativeRegExp.isDigit(dc)) { tmp = 10 * num + (dc - '0'); if (tmp <= parenCount) { cp++; num = tmp; } } } if (num == 0) return null; /* $0 or $00 is not valid */ } /* Adjust num from 1 $n-origin to 0 array-index-origin. */ num--; skip[0] = cp - dp; return res.getParenSubString(num); } skip[0] = 2; switch (dc) { case '$': return new SubString("$"); case '&': return res.lastMatch; case '+': return res.lastParen; case '`': if (version == Context.VERSION_1_2) { /* * JS1.2 imitated the Perl4 bug where left context at each step * in an iterative use of a global regexp started from last match, * not from the start of the target string. But Perl4 does start * $` at the beginning of the target string when it is used in a * substitution, so we emulate that special case here. */ res.leftContext.index = 0; res.leftContext.length = res.lastMatch.index; } return res.leftContext; case '\'': return res.rightContext; } return null; } /** * Analog of do_replace in jsstr.c */ private static void do_replace(GlobData rdata, Context cx, RegExpImpl regExpImpl) { StringBuffer charBuf = rdata.charBuf; int cp = 0; String da = rdata.repstr; int dp = rdata.dollar; if (dp != -1) { int[] skip = new int[1]; do { int len = dp - cp; charBuf.append(da.substring(cp, dp)); cp = dp; SubString sub = interpretDollar(cx, regExpImpl, da, dp, skip); if (sub != null) { len = sub.length; if (len > 0) { charBuf.append(sub.charArray, sub.index, len); } cp += skip[0]; dp += skip[0]; } else { ++dp; } dp = da.indexOf('$', dp); } while (dp >= 0); } int daL = da.length(); if (daL > cp) { charBuf.append(da.substring(cp, daL)); } } String input; /* input string to match (perl $_, GC root) */ boolean multiline; /* whether input contains newlines (perl $*) */ SubString[] parens; /* Vector of SubString; last set of parens matched (perl $1, $2) */ SubString lastMatch; /* last string matched (perl $&) */ SubString lastParen; /* last paren matched (perl $+) */ SubString leftContext; /* input to left of last match (perl $`) */ SubString rightContext; /* input to right of last match (perl $') */}final class GlobData{ int mode; /* input: return index, match object, or void */ int optarg; /* input: index of optional flags argument */ boolean global; /* output: whether regexp was global */ String str; /* output: 'this' parameter object as string */ NativeRegExp regexp;/* output: regexp parameter object private data */ // match-specific data Scriptable arrayobj; // replace-specific data Function lambda; /* replacement function object or null */ String repstr; /* replacement string */ int dollar = -1; /* -1 or index of first $ in repstr */ StringBuffer charBuf; /* result characters, null initially */ int leftIndex; /* leftContext index, always 0 for JS1.2 */}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -