Inheritance: RegExpProxy
コード例 #1
0
ファイル: RegExpImpl.cs プロジェクト: hazzik/Rhino.Net
		/// <summary>Analog of C match_or_replace.</summary>
		/// <remarks>Analog of C match_or_replace.</remarks>
		private static object MatchOrReplace(Context cx, Scriptable scope, Scriptable thisObj, object[] args, RegExpImpl reImpl, GlobData data, bool forceFlat)
		{
			NativeRegExp re;
			string str = ScriptRuntime.ToString(thisObj);
			data.str = str;
			Scriptable topScope = ScriptableObject.GetTopLevelScope(scope);
			if (args.Length == 0)
			{
				RECompiled compiled = NativeRegExp.CompileRE(cx, string.Empty, string.Empty, false);
				re = new NativeRegExp(topScope, compiled);
			}
			else
			{
				if (args[0] is 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;
					}
					RECompiled compiled = NativeRegExp.CompileRE(cx, src, opt, forceFlat);
					re = new NativeRegExp(topScope, compiled);
				}
			}
			data.global = (re.GetFlags() & NativeRegExp.JSREG_GLOB) != 0;
			int[] indexp = new int[] { 0 };
			object result = null;
			if (data.mode == RegExpProxyConstants.RA_SEARCH)
			{
				result = re.ExecuteRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
				if (result != null && result.Equals(true))
				{
					result = Sharpen.Extensions.ValueOf(reImpl.leftContext.length);
				}
				else
				{
					result = Sharpen.Extensions.ValueOf(-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(true))
						{
							break;
						}
						if (data.mode == RegExpProxyConstants.RA_MATCH)
						{
							Match_glob(data, cx, scope, count, reImpl);
						}
						else
						{
							if (data.mode != RegExpProxyConstants.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 == RegExpProxyConstants.RA_REPLACE) ? NativeRegExp.TEST : NativeRegExp.MATCH));
				}
			}
			return result;
		}
コード例 #2
0
ファイル: RegExpImpl.cs プロジェクト: hazzik/Rhino.Net
		/// <summary>Analog of do_replace in jsstr.c</summary>
		private static void Do_replace(GlobData rdata, Context cx, RegExpImpl regExpImpl)
		{
			StringBuilder 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(Sharpen.Runtime.Substring(da, cp, dp));
					cp = dp;
					SubString sub = InterpretDollar(cx, regExpImpl, da, dp, skip);
					if (sub != null)
					{
						len = sub.length;
						if (len > 0)
						{
							charBuf.AppendRange(sub.str, sub.index, 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(Sharpen.Runtime.Substring(da, cp, daL));
			}
		}
コード例 #3
0
ファイル: RegExpImpl.cs プロジェクト: hazzik/Rhino.Net
		private static SubString InterpretDollar(Context cx, RegExpImpl res, string da, int dp, int[] skip)
		{
			char dc;
			int num;
			int tmp;
			if (da[dp] != '$')
			{
				Kit.CodeBug();
			}
			int version = cx.GetLanguageVersion();
			if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4)
			{
				if (dp > 0 && da[dp - 1] == '\\')
				{
					return null;
				}
			}
			int daL = da.Length;
			if (dp + 1 >= daL)
			{
				return null;
			}
			dc = da[dp + 1];
			if (NativeRegExp.IsDigit(dc))
			{
				int cp;
				if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4)
				{
					if (dc == '0')
					{
						return null;
					}
					num = 0;
					cp = dp;
					while (++cp < daL && NativeRegExp.IsDigit(dc = da[cp]))
					{
						tmp = 10 * num + (dc - '0');
						if (tmp < num)
						{
							break;
						}
						num = tmp;
					}
				}
				else
				{
					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[dp + 2];
						if (NativeRegExp.IsDigit(dc))
						{
							tmp = 10 * num + (dc - '0');
							if (tmp <= parenCount)
							{
								cp++;
								num = tmp;
							}
						}
					}
					if (num == 0)
					{
						return null;
					}
				}
				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)
					{
						res.leftContext.index = 0;
						res.leftContext.length = res.lastMatch.index;
					}
					return res.leftContext;
				}

				case '\'':
				{
					return res.rightContext;
				}
			}
			return null;
		}
コード例 #4
0
ファイル: RegExpImpl.cs プロジェクト: hazzik/Rhino.Net
		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] = Sharpen.Extensions.ValueOf(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;
			StringBuilder charBuf = rdata.charBuf;
			if (charBuf == null)
			{
				charBuf = new StringBuilder(growth);
				rdata.charBuf = charBuf;
			}
			else
			{
				charBuf.EnsureCapacity(rdata.charBuf.Length + growth);
			}
			charBuf.AppendRange(reImpl.leftContext.str, leftIndex, leftIndex + leftlen);
			if (rdata.lambda != null)
			{
				charBuf.Append(lambdaStr);
			}
			else
			{
				Do_replace(rdata, cx, reImpl);
			}
		}
コード例 #5
0
ファイル: RegExpImpl.cs プロジェクト: hazzik/Rhino.Net
		private static void Match_glob(GlobData mdata, Context cx, Scriptable scope, int count, RegExpImpl reImpl)
		{
			if (mdata.arrayobj == null)
			{
				mdata.arrayobj = cx.NewArray(scope, 0);
			}
			SubString matchsub = reImpl.lastMatch;
			string matchstr = matchsub.ToString();
			mdata.arrayobj.Put(count, mdata.arrayobj, matchstr);
		}
コード例 #6
0
ファイル: NativeRegExp.cs プロジェクト: hazzik/Rhino.Net
		internal virtual object ExecuteRegExp(Context cx, Scriptable scope, RegExpImpl res, string str, int[] indexp, int matchType)
		{
			REGlobalData gData = new REGlobalData();
			int start = indexp[0];
			int end = str.Length;
			if (start > end)
			{
				start = end;
			}
			//
			// Call the recursive matcher to do the real work.
			//
			bool matches = MatchRegExp(gData, re, str, start, end, res.multiline);
			if (!matches)
			{
				if (matchType != PREFIX)
				{
					return null;
				}
				return Undefined.instance;
			}
			int index = gData.cp;
			int ep = indexp[0] = index;
			int matchlen = ep - (start + gData.skipped);
			index -= matchlen;
			object result;
			Scriptable obj;
			if (matchType == TEST)
			{
				result = true;
				obj = null;
			}
			else
			{
				result = cx.NewArray(scope, 0);
				obj = (Scriptable)result;
				string matchstr = Sharpen.Runtime.Substring(str, index, index + matchlen);
				obj.Put(0, obj, matchstr);
			}
			if (re.parenCount == 0)
			{
				res.parens = null;
				res.lastParen = SubString.emptySubString;
			}
			else
			{
				SubString parsub = null;
				int num;
				res.parens = new SubString[re.parenCount];
				for (num = 0; num < re.parenCount; num++)
				{
					int cap_index = gData.ParensIndex(num);
					string parstr;
					if (cap_index != -1)
					{
						int cap_length = gData.ParensLength(num);
						parsub = new SubString(str, cap_index, cap_length);
						res.parens[num] = parsub;
						if (matchType != TEST)
						{
							obj.Put(num + 1, obj, parsub.ToString());
						}
					}
					else
					{
						if (matchType != TEST)
						{
							obj.Put(num + 1, obj, Undefined.instance);
						}
					}
				}
				res.lastParen = parsub;
			}
			if (!(matchType == TEST))
			{
				obj.Put("index", obj, Sharpen.Extensions.ValueOf(start + gData.skipped));
				obj.Put("input", obj, str);
			}
			if (res.lastMatch == null)
			{
				res.lastMatch = new SubString();
				res.leftContext = new SubString();
				res.rightContext = new SubString();
			}
			res.lastMatch.str = str;
			res.lastMatch.index = index;
			res.lastMatch.length = matchlen;
			res.leftContext.str = str;
			if (cx.GetLanguageVersion() == Context.VERSION_1_2)
			{
				res.leftContext.index = start;
				res.leftContext.length = gData.skipped;
			}
			else
			{
				res.leftContext.index = 0;
				res.leftContext.length = start + gData.skipped;
			}
			res.rightContext.str = str;
			res.rightContext.index = ep;
			res.rightContext.length = end - ep;
			return result;
		}