public Object compileRegExp(Context cx, String source, String flags) { return NativeRegExp.compileRE(cx, source, flags, false); }
public int find_split( Context cx, Scriptable scope, String target, String separator, Scriptable reObj, int[] ip, int[] matchlen, boolean[] matched, String[][] parensp) { int i = ip[0]; int length = target.length(); int result; int version = cx.getLanguageVersion(); NativeRegExp re = (NativeRegExp) reObj; again: while (true) { // imitating C label /* JS1.2 deviated from Perl by never matching at end of string. */ int ipsave = ip[0]; // reuse ip to save object creation ip[0] = i; Object ret = re.executeRegExp(cx, scope, this, target, ip, NativeRegExp.TEST); if (ret != Boolean.TRUE) { // Mismatch: ensure our caller advances i past end of string. ip[0] = ipsave; matchlen[0] = 1; matched[0] = false; return length; } i = ip[0]; ip[0] = ipsave; matched[0] = true; SubString sep = this.lastMatch; matchlen[0] = sep.length; if (matchlen[0] == 0) { /* * Empty string match: never split on an empty * match at the start of a find_split cycle. Same * rule as for an empty global match in * match_or_replace. */ if (i == ip[0]) { /* * "Bump-along" to avoid sticking at an empty * match, but don't bump past end of string -- * our caller must do that by adding * sep->length to our return value. */ if (i == length) { if (version == Context.VERSION_1_2) { matchlen[0] = 1; result = i; } else result = -1; break; } i++; continue again; // imitating C goto } } // PR_ASSERT((size_t)i >= sep->length); result = i - matchlen[0]; break; } int size = (parens == null) ? 0 : parens.length; parensp[0] = new String[size]; for (int num = 0; num < size; num++) { SubString parsub = getParenSubString(num); parensp[0][num] = parsub.toString(); } return result; }
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 C match_or_replace. */ private static Object matchOrReplace( Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RegExpImpl reImpl, GlobData data, boolean forceFlat) { NativeRegExp re; String str = ScriptRuntime.toString(thisObj); data.str = str; Scriptable topScope = ScriptableObject.getTopLevelScope(scope); if (args.length == 0) { Object compiled = NativeRegExp.compileRE(cx, "", "", false); re = new NativeRegExp(topScope, compiled); } else if (args[0] instanceof NativeRegExp) { re = (NativeRegExp) args[0]; } else { String src = ScriptRuntime.toString(args[0]); String opt; if (data.optarg < args.length) { args[0] = src; opt = ScriptRuntime.toString(args[data.optarg]); } else { opt = null; } Object compiled = NativeRegExp.compileRE(cx, src, opt, forceFlat); re = new NativeRegExp(topScope, compiled); } data.regexp = re; data.global = (re.getFlags() & NativeRegExp.JSREG_GLOB) != 0; int[] indexp = {0}; Object result = null; if (data.mode == RA_SEARCH) { result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST); if (result != null && result.equals(Boolean.TRUE)) result = new Integer(reImpl.leftContext.length); else result = new Integer(-1); } else if (data.global) { re.lastIndex = 0; for (int count = 0; indexp[0] <= str.length(); count++) { result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST); if (result == null || !result.equals(Boolean.TRUE)) break; if (data.mode == RA_MATCH) { match_glob(data, cx, scope, count, reImpl); } else { if (data.mode != RA_REPLACE) Kit.codeBug(); SubString lastMatch = reImpl.lastMatch; int leftIndex = data.leftIndex; int leftlen = lastMatch.index - leftIndex; data.leftIndex = lastMatch.index + lastMatch.length; replace_glob(data, cx, scope, reImpl, leftIndex, leftlen); } if (reImpl.lastMatch.length == 0) { if (indexp[0] == str.length()) break; indexp[0]++; } } } else { result = re.executeRegExp( cx, scope, reImpl, str, indexp, ((data.mode == RA_REPLACE) ? NativeRegExp.TEST : NativeRegExp.MATCH)); } return result; }