예제 #1
0
		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;
		}
예제 #2
0
		internal REBackTrackData(REGlobalData gData, int op, int pc, int cp, int continuationOp, int continuationPc)
		{
			previous = gData.backTrackStackTop;
			this.op = op;
			this.pc = pc;
			this.cp = cp;
			this.continuationOp = continuationOp;
			this.continuationPc = continuationPc;
			parens = gData.parens;
			stateStackTop = gData.stateStackTop;
		}
예제 #3
0
		private static bool ExecuteREBytecode(REGlobalData gData, string input, int end)
		{
			int pc = 0;
			byte[] program = gData.regexp.program;
			int continuationOp = REOP_END;
			int continuationPc = 0;
			bool result = false;
			int op = program[pc++];
			if (gData.regexp.anchorCh < 0 && ReopIsSimple(op))
			{
				bool anchor = false;
				while (gData.cp <= end)
				{
					int match = SimpleMatch(gData, input, op, program, pc, end, true);
					if (match >= 0)
					{
						anchor = true;
						pc = match;
						op = program[pc++];
						break;
					}
					gData.skipped++;
					gData.cp++;
				}
				if (!anchor)
				{
					return false;
				}
			}
			for (; ; )
			{
				if (ReopIsSimple(op))
				{
					int match = SimpleMatch(gData, input, op, program, pc, end, true);
					result = match >= 0;
					if (result)
					{
						pc = match;
					}
				}
				else
				{
					switch (op)
					{
						case REOP_ALTPREREQ:
						case REOP_ALTPREREQi:
						case REOP_ALTPREREQ2:
						{
							char matchCh1 = (char)GetIndex(program, pc);
							pc += INDEX_LEN;
							char matchCh2 = (char)GetIndex(program, pc);
							pc += INDEX_LEN;
							if (gData.cp == end)
							{
								result = false;
								break;
							}
							char c = input[gData.cp];
							if (op == REOP_ALTPREREQ2)
							{
								if (c != matchCh1 && !ClassMatcher(gData, gData.regexp.classList[matchCh2], c))
								{
									result = false;
									break;
								}
							}
							else
							{
								if (op == REOP_ALTPREREQi)
								{
									c = Upcase(c);
								}
								if (c != matchCh1 && c != matchCh2)
								{
									result = false;
									break;
								}
							}
							goto case REOP_ALT;
						}

						case REOP_ALT:
						{
							int nextpc = pc + GetOffset(program, pc);
							pc += INDEX_LEN;
							op = program[pc++];
							int startcp = gData.cp;
							if (ReopIsSimple(op))
							{
								int match = SimpleMatch(gData, input, op, program, pc, end, true);
								if (match < 0)
								{
									op = program[nextpc++];
									pc = nextpc;
									continue;
								}
								result = true;
								pc = match;
								op = program[pc++];
							}
							byte nextop = program[nextpc++];
							PushBackTrackState(gData, nextop, nextpc, startcp, continuationOp, continuationPc);
							continue;
						}

						case REOP_JUMP:
						{
							int offset = GetOffset(program, pc);
							pc += offset;
							op = program[pc++];
							continue;
						}

						case REOP_LPAREN:
						{
							int parenIndex = GetIndex(program, pc);
							pc += INDEX_LEN;
							gData.SetParens(parenIndex, gData.cp, 0);
							op = program[pc++];
							continue;
						}

						case REOP_RPAREN:
						{
							int parenIndex = GetIndex(program, pc);
							pc += INDEX_LEN;
							int cap_index = gData.ParensIndex(parenIndex);
							gData.SetParens(parenIndex, cap_index, gData.cp - cap_index);
							op = program[pc++];
							continue;
						}

						case REOP_ASSERT:
						{
							int nextpc = pc + GetIndex(program, pc);
							pc += INDEX_LEN;
							op = program[pc++];
							if (ReopIsSimple(op) && SimpleMatch(gData, input, op, program, pc, end, false) < 0)
							{
								result = false;
								break;
							}
							PushProgState(gData, 0, 0, gData.cp, gData.backTrackStackTop, continuationOp, continuationPc);
							PushBackTrackState(gData, REOP_ASSERTTEST, nextpc);
							continue;
						}

						case REOP_ASSERT_NOT:
						{
							int nextpc = pc + GetIndex(program, pc);
							pc += INDEX_LEN;
							op = program[pc++];
							if (ReopIsSimple(op))
							{
								int match = SimpleMatch(gData, input, op, program, pc, end, false);
								if (match >= 0 && program[match] == REOP_ASSERTNOTTEST)
								{
									result = false;
									break;
								}
							}
							PushProgState(gData, 0, 0, gData.cp, gData.backTrackStackTop, continuationOp, continuationPc);
							PushBackTrackState(gData, REOP_ASSERTNOTTEST, nextpc);
							continue;
						}

						case REOP_ASSERTTEST:
						case REOP_ASSERTNOTTEST:
						{
							REProgState state = PopProgState(gData);
							gData.cp = state.index;
							gData.backTrackStackTop = state.backTrack;
							continuationPc = state.continuationPc;
							continuationOp = state.continuationOp;
							if (op == REOP_ASSERTNOTTEST)
							{
								result = !result;
							}
							break;
						}

						case REOP_STAR:
						case REOP_PLUS:
						case REOP_OPT:
						case REOP_QUANT:
						case REOP_MINIMALSTAR:
						case REOP_MINIMALPLUS:
						case REOP_MINIMALOPT:
						case REOP_MINIMALQUANT:
						{
							int min;
							int max;
							bool greedy = false;
							switch (op)
							{
								case REOP_STAR:
								{
									greedy = true;
									goto case REOP_MINIMALSTAR;
								}

								case REOP_MINIMALSTAR:
								{
									// fallthrough
									min = 0;
									max = -1;
									break;
								}

								case REOP_PLUS:
								{
									greedy = true;
									goto case REOP_MINIMALPLUS;
								}

								case REOP_MINIMALPLUS:
								{
									// fallthrough
									min = 1;
									max = -1;
									break;
								}

								case REOP_OPT:
								{
									greedy = true;
									goto case REOP_MINIMALOPT;
								}

								case REOP_MINIMALOPT:
								{
									// fallthrough
									min = 0;
									max = 1;
									break;
								}

								case REOP_QUANT:
								{
									greedy = true;
									goto case REOP_MINIMALQUANT;
								}

								case REOP_MINIMALQUANT:
								{
									// fallthrough
									min = GetOffset(program, pc);
									pc += INDEX_LEN;
									// See comments in emitREBytecode for " - 1" reason
									max = GetOffset(program, pc) - 1;
									pc += INDEX_LEN;
									break;
								}

								default:
								{
									throw Kit.CodeBug();
								}
							}
							PushProgState(gData, min, max, gData.cp, null, continuationOp, continuationPc);
							if (greedy)
							{
								PushBackTrackState(gData, REOP_REPEAT, pc);
								continuationOp = REOP_REPEAT;
								continuationPc = pc;
								pc += 3 * INDEX_LEN;
								op = program[pc++];
							}
							else
							{
								if (min != 0)
								{
									continuationOp = REOP_MINIMALREPEAT;
									continuationPc = pc;
									pc += 3 * INDEX_LEN;
									op = program[pc++];
								}
								else
								{
									PushBackTrackState(gData, REOP_MINIMALREPEAT, pc);
									PopProgState(gData);
									pc += 2 * INDEX_LEN;
									// <parencount> & <parenindex>
									pc = pc + GetOffset(program, pc);
									op = program[pc++];
								}
							}
							continue;
						}

						case REOP_ENDCHILD:
						{
							// If we have not gotten a result here, it is because of an
							// empty match.  Do the same thing REOP_EMPTY would do.
							result = true;
							// Use the current continuation.
							pc = continuationPc;
							op = continuationOp;
							continue;
						}

						case REOP_REPEAT:
						{
							int nextpc;
							int nextop;
							do
							{
								REProgState state = PopProgState(gData);
								if (!result)
								{
									// Failed, see if we have enough children.
									if (state.min == 0)
									{
										result = true;
									}
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									pc += 2 * INDEX_LEN;
									pc += GetOffset(program, pc);
									goto switchStatement_break;
								}
								if (state.min == 0 && gData.cp == state.index)
								{
									// matched an empty string, that'll get us nowhere
									result = false;
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									pc += 2 * INDEX_LEN;
									pc += GetOffset(program, pc);
									goto switchStatement_break;
								}
								int new_min = state.min;
								int new_max = state.max;
								if (new_min != 0)
								{
									new_min--;
								}
								if (new_max != -1)
								{
									new_max--;
								}
								if (new_max == 0)
								{
									result = true;
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									pc += 2 * INDEX_LEN;
									pc += GetOffset(program, pc);
									goto switchStatement_break;
								}
								nextpc = pc + 3 * INDEX_LEN;
								nextop = program[nextpc];
								int startcp = gData.cp;
								if (ReopIsSimple(nextop))
								{
									nextpc++;
									int match = SimpleMatch(gData, input, nextop, program, nextpc, end, true);
									if (match < 0)
									{
										result = (new_min == 0);
										continuationPc = state.continuationPc;
										continuationOp = state.continuationOp;
										pc += 2 * INDEX_LEN;
										pc += GetOffset(program, pc);
										goto switchStatement_break;
									}
									result = true;
									nextpc = match;
								}
								continuationOp = REOP_REPEAT;
								continuationPc = pc;
								PushProgState(gData, new_min, new_max, startcp, null, state.continuationOp, state.continuationPc);
								if (new_min == 0)
								{
									PushBackTrackState(gData, REOP_REPEAT, pc, startcp, state.continuationOp, state.continuationPc);
									int parenCount = GetIndex(program, pc);
									int parenIndex = GetIndex(program, pc + INDEX_LEN);
									for (int k = 0; k < parenCount; k++)
									{
										gData.SetParens(parenIndex + k, -1, 0);
									}
								}
							}
							while (program[nextpc] == REOP_ENDCHILD);
							pc = nextpc;
							op = program[pc++];
							continue;
						}

						case REOP_MINIMALREPEAT:
						{
							REProgState state = PopProgState(gData);
							if (!result)
							{
								//
								// Non-greedy failure - try to consume another child.
								//
								if (state.max == -1 || state.max > 0)
								{
									PushProgState(gData, state.min, state.max, gData.cp, null, state.continuationOp, state.continuationPc);
									continuationOp = REOP_MINIMALREPEAT;
									continuationPc = pc;
									int parenCount = GetIndex(program, pc);
									pc += INDEX_LEN;
									int parenIndex = GetIndex(program, pc);
									pc += 2 * INDEX_LEN;
									for (int k = 0; k < parenCount; k++)
									{
										gData.SetParens(parenIndex + k, -1, 0);
									}
									op = program[pc++];
									continue;
								}
								else
								{
									// Don't need to adjust pc since we're going to pop.
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									break;
								}
							}
							else
							{
								if (state.min == 0 && gData.cp == state.index)
								{
									// Matched an empty string, that'll get us nowhere.
									result = false;
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									break;
								}
								int new_min = state.min;
								int new_max = state.max;
								if (new_min != 0)
								{
									new_min--;
								}
								if (new_max != -1)
								{
									new_max--;
								}
								PushProgState(gData, new_min, new_max, gData.cp, null, state.continuationOp, state.continuationPc);
								if (new_min != 0)
								{
									continuationOp = REOP_MINIMALREPEAT;
									continuationPc = pc;
									int parenCount = GetIndex(program, pc);
									pc += INDEX_LEN;
									int parenIndex = GetIndex(program, pc);
									pc += 2 * INDEX_LEN;
									for (int k = 0; k < parenCount; k++)
									{
										gData.SetParens(parenIndex + k, -1, 0);
									}
									op = program[pc++];
								}
								else
								{
									continuationPc = state.continuationPc;
									continuationOp = state.continuationOp;
									PushBackTrackState(gData, REOP_MINIMALREPEAT, pc);
									PopProgState(gData);
									pc += 2 * INDEX_LEN;
									pc = pc + GetOffset(program, pc);
									op = program[pc++];
								}
								continue;
							}
							goto case REOP_END;
						}

						case REOP_END:
						{
							return true;
						}

						default:
						{
							throw Kit.CodeBug("invalid bytecode");
						}
					}
switchStatement_break: ;
				}
				if (!result)
				{
					REBackTrackData backTrackData = gData.backTrackStackTop;
					if (backTrackData != null)
					{
						gData.backTrackStackTop = backTrackData.previous;
						gData.parens = backTrackData.parens;
						gData.cp = backTrackData.cp;
						gData.stateStackTop = backTrackData.stateStackTop;
						continuationOp = backTrackData.continuationOp;
						continuationPc = backTrackData.continuationPc;
						pc = backTrackData.pc;
						op = backTrackData.op;
						continue;
					}
					else
					{
						return false;
					}
				}
				op = program[pc++];
			}
		}
예제 #4
0
		private static bool MatchRegExp(REGlobalData gData, RECompiled re, string input, int start, int end, bool multiline)
		{
			if (re.parenCount != 0)
			{
				gData.parens = new long[re.parenCount];
			}
			else
			{
				gData.parens = null;
			}
			gData.backTrackStackTop = null;
			gData.stateStackTop = null;
			gData.multiline = multiline || (re.flags & JSREG_MULTILINE) != 0;
			gData.regexp = re;
			int anchorCh = gData.regexp.anchorCh;
			//
			// have to include the position beyond the last character
			//  in order to detect end-of-input/line condition
			//
			for (int i = start; i <= end; ++i)
			{
				//
				// If the first node is a literal match, step the index into
				// the string until that match is made, or fail if it can't be
				// found at all.
				//
				if (anchorCh >= 0)
				{
					for (; ; )
					{
						if (i == end)
						{
							return false;
						}
						char matchCh = input[i];
						if (matchCh == anchorCh || ((gData.regexp.flags & JSREG_FOLD) != 0 && Upcase(matchCh) == Upcase((char)anchorCh)))
						{
							break;
						}
						++i;
					}
				}
				gData.cp = i;
				gData.skipped = i - start;
				for (int j = 0; j < re.parenCount; j++)
				{
					gData.parens[j] = -1l;
				}
				bool result = ExecuteREBytecode(gData, input, end);
				gData.backTrackStackTop = null;
				gData.stateStackTop = null;
				if (result)
				{
					return true;
				}
				if (anchorCh == ANCHOR_BOL && !gData.multiline)
				{
					gData.skipped = end;
					return false;
				}
				i = start + gData.skipped;
			}
			return false;
		}
예제 #5
0
		private static bool ClassMatcher(REGlobalData gData, RECharSet charSet, char ch)
		{
			if (!charSet.converted)
			{
				ProcessCharSet(gData, charSet);
			}
			int byteIndex = ch >> 3;
			return (charSet.length == 0 || ch >= charSet.length || (charSet.bits[byteIndex] & (1 << (ch & unchecked((int)(0x7))))) == 0) ^ charSet.sense;
		}
예제 #6
0
		private static int SimpleMatch(REGlobalData gData, string input, int op, byte[] program, int pc, int end, bool updatecp)
		{
			bool result = false;
			char matchCh;
			int parenIndex;
			int offset;
			int length;
			int index;
			int startcp = gData.cp;
			switch (op)
			{
				case REOP_EMPTY:
				{
					result = true;
					break;
				}

				case REOP_BOL:
				{
					if (gData.cp != 0)
					{
						if (!gData.multiline || !IsLineTerm(input[gData.cp - 1]))
						{
							break;
						}
					}
					result = true;
					break;
				}

				case REOP_EOL:
				{
					if (gData.cp != end)
					{
						if (!gData.multiline || !IsLineTerm(input[gData.cp]))
						{
							break;
						}
					}
					result = true;
					break;
				}

				case REOP_WBDRY:
				{
					result = ((gData.cp == 0 || !IsWord(input[gData.cp - 1])) ^ !((gData.cp < end) && IsWord(input[gData.cp])));
					break;
				}

				case REOP_WNONBDRY:
				{
					result = ((gData.cp == 0 || !IsWord(input[gData.cp - 1])) ^ ((gData.cp < end) && IsWord(input[gData.cp])));
					break;
				}

				case REOP_DOT:
				{
					if (gData.cp != end && !IsLineTerm(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_DIGIT:
				{
					if (gData.cp != end && IsDigit(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_NONDIGIT:
				{
					if (gData.cp != end && !IsDigit(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_ALNUM:
				{
					if (gData.cp != end && IsWord(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_NONALNUM:
				{
					if (gData.cp != end && !IsWord(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_SPACE:
				{
					if (gData.cp != end && IsREWhiteSpace(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_NONSPACE:
				{
					if (gData.cp != end && !IsREWhiteSpace(input[gData.cp]))
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_BACKREF:
				{
					parenIndex = GetIndex(program, pc);
					pc += INDEX_LEN;
					result = BackrefMatcher(gData, parenIndex, input, end);
					break;
				}

				case REOP_FLAT:
				{
					offset = GetIndex(program, pc);
					pc += INDEX_LEN;
					length = GetIndex(program, pc);
					pc += INDEX_LEN;
					result = FlatNMatcher(gData, offset, length, input, end);
					break;
				}

				case REOP_FLAT1:
				{
					matchCh = (char)(program[pc++] & unchecked((int)(0xFF)));
					if (gData.cp != end && input[gData.cp] == matchCh)
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_FLATi:
				{
					offset = GetIndex(program, pc);
					pc += INDEX_LEN;
					length = GetIndex(program, pc);
					pc += INDEX_LEN;
					result = FlatNIMatcher(gData, offset, length, input, end);
					break;
				}

				case REOP_FLAT1i:
				{
					matchCh = (char)(program[pc++] & unchecked((int)(0xFF)));
					if (gData.cp != end)
					{
						char c = input[gData.cp];
						if (matchCh == c || Upcase(matchCh) == Upcase(c))
						{
							result = true;
							gData.cp++;
						}
					}
					break;
				}

				case REOP_UCFLAT1:
				{
					matchCh = (char)GetIndex(program, pc);
					pc += INDEX_LEN;
					if (gData.cp != end && input[gData.cp] == matchCh)
					{
						result = true;
						gData.cp++;
					}
					break;
				}

				case REOP_UCFLAT1i:
				{
					matchCh = (char)GetIndex(program, pc);
					pc += INDEX_LEN;
					if (gData.cp != end)
					{
						char c = input[gData.cp];
						if (matchCh == c || Upcase(matchCh) == Upcase(c))
						{
							result = true;
							gData.cp++;
						}
					}
					break;
				}

				case REOP_CLASS:
				case REOP_NCLASS:
				{
					index = GetIndex(program, pc);
					pc += INDEX_LEN;
					if (gData.cp != end)
					{
						if (ClassMatcher(gData, gData.regexp.classList[index], input[gData.cp]))
						{
							gData.cp++;
							result = true;
							break;
						}
					}
					break;
				}

				default:
				{
					throw Kit.CodeBug();
				}
			}
			if (result)
			{
				if (!updatecp)
				{
					gData.cp = startcp;
				}
				return pc;
			}
			gData.cp = startcp;
			return -1;
		}
예제 #7
0
		private static void ProcessCharSet(REGlobalData gData, RECharSet charSet)
		{
			lock (charSet)
			{
				if (!charSet.converted)
				{
					ProcessCharSetImpl(gData, charSet);
					charSet.converted = true;
				}
			}
		}
예제 #8
0
		private static void ProcessCharSetImpl(REGlobalData gData, RECharSet charSet)
		{
			int src = charSet.startIndex;
			int end = src + charSet.strlength;
			char rangeStart = 0;
			char thisCh;
			int byteLength;
			char c;
			int n;
			int nDigits;
			int i;
			bool inRange = false;
			byteLength = (charSet.length + 7) / 8;
			charSet.bits = new byte[byteLength];
			if (src == end)
			{
				return;
			}
			if (gData.regexp.source[src] == '^')
			{
				System.Diagnostics.Debug.Assert((!charSet.sense));
				++src;
			}
			else
			{
				System.Diagnostics.Debug.Assert((charSet.sense));
			}
			while (src != end)
			{
				nDigits = 2;
				switch (gData.regexp.source[src])
				{
					case '\\':
					{
						++src;
						c = gData.regexp.source[src++];
						switch (c)
						{
							case 'b':
							{
								thisCh = (char)unchecked((int)(0x8));
								break;
							}

							case 'f':
							{
								thisCh = (char)unchecked((int)(0xC));
								break;
							}

							case 'n':
							{
								thisCh = (char)unchecked((int)(0xA));
								break;
							}

							case 'r':
							{
								thisCh = (char)unchecked((int)(0xD));
								break;
							}

							case 't':
							{
								thisCh = (char)unchecked((int)(0x9));
								break;
							}

							case 'v':
							{
								thisCh = (char)unchecked((int)(0xB));
								break;
							}

							case 'c':
							{
								if ((src < end) && IsControlLetter(gData.regexp.source[src]))
								{
									thisCh = (char)(gData.regexp.source[src++] & unchecked((int)(0x1F)));
								}
								else
								{
									--src;
									thisCh = '\\';
								}
								break;
							}

							case 'u':
							{
								nDigits += 2;
								goto case 'x';
							}

							case 'x':
							{
								// fall thru
								n = 0;
								for (i = 0; (i < nDigits) && (src < end); i++)
								{
									c = gData.regexp.source[src++];
									int digit = ToASCIIHexDigit(c);
									if (digit < 0)
									{
										src -= (i + 1);
										n = '\\';
										break;
									}
									n = (n << 4) | digit;
								}
								thisCh = (char)(n);
								break;
							}

							case '0':
							case '1':
							case '2':
							case '3':
							case '4':
							case '5':
							case '6':
							case '7':
							{
								n = (c - '0');
								c = gData.regexp.source[src];
								if ('0' <= c && c <= '7')
								{
									src++;
									n = 8 * n + (c - '0');
									c = gData.regexp.source[src];
									if ('0' <= c && c <= '7')
									{
										src++;
										i = 8 * n + (c - '0');
										if (i <= 0xff)
										{
											n = i;
										}
										else
										{
											src--;
										}
									}
								}
								thisCh = (char)(n);
								break;
							}

							case 'd':
							{
								AddCharacterRangeToCharSet(charSet, '0', '9');
								continue;
							}

							case 'D':
							{
								AddCharacterRangeToCharSet(charSet, (char)0, (char)('0' - 1));
								AddCharacterRangeToCharSet(charSet, (char)('9' + 1), (char)(charSet.length - 1));
								continue;
							}

							case 's':
							{
								for (i = (charSet.length - 1); i >= 0; i--)
								{
									if (IsREWhiteSpace(i))
									{
										AddCharacterToCharSet(charSet, (char)(i));
									}
								}
								continue;
							}

							case 'S':
							{
								for (i = (charSet.length - 1); i >= 0; i--)
								{
									if (!IsREWhiteSpace(i))
									{
										AddCharacterToCharSet(charSet, (char)(i));
									}
								}
								continue;
							}

							case 'w':
							{
								for (i = (charSet.length - 1); i >= 0; i--)
								{
									if (IsWord((char)i))
									{
										AddCharacterToCharSet(charSet, (char)(i));
									}
								}
								continue;
							}

							case 'W':
							{
								for (i = (charSet.length - 1); i >= 0; i--)
								{
									if (!IsWord((char)i))
									{
										AddCharacterToCharSet(charSet, (char)(i));
									}
								}
								continue;
							}

							default:
							{
								thisCh = c;
								break;
							}
						}
						break;
					}

					default:
					{
						thisCh = gData.regexp.source[src++];
						break;
					}
				}
				if (inRange)
				{
					if ((gData.regexp.flags & JSREG_FOLD) != 0)
					{
						System.Diagnostics.Debug.Assert((rangeStart <= thisCh));
						for (c = rangeStart; c <= thisCh; )
						{
							AddCharacterToCharSet(charSet, c);
							char uch = Upcase(c);
							char dch = Downcase(c);
							if (c != uch)
							{
								AddCharacterToCharSet(charSet, uch);
							}
							if (c != dch)
							{
								AddCharacterToCharSet(charSet, dch);
							}
							if (++c == 0)
							{
								break;
							}
						}
					}
					else
					{
						// overflow
						AddCharacterRangeToCharSet(charSet, rangeStart, thisCh);
					}
					inRange = false;
				}
				else
				{
					if ((gData.regexp.flags & JSREG_FOLD) != 0)
					{
						AddCharacterToCharSet(charSet, Upcase(thisCh));
						AddCharacterToCharSet(charSet, Downcase(thisCh));
					}
					else
					{
						AddCharacterToCharSet(charSet, thisCh);
					}
					if (src < (end - 1))
					{
						if (gData.regexp.source[src] == '-')
						{
							++src;
							inRange = true;
							rangeStart = thisCh;
						}
					}
				}
			}
		}
예제 #9
0
		private static bool FlatNIMatcher(REGlobalData gData, int matchChars, int length, string input, int end)
		{
			if ((gData.cp + length) > end)
			{
				return false;
			}
			char[] source = gData.regexp.source;
			for (int i = 0; i < length; i++)
			{
				char c1 = source[matchChars + i];
				char c2 = input[gData.cp + i];
				if (c1 != c2 && Upcase(c1) != Upcase(c2))
				{
					return false;
				}
			}
			gData.cp += length;
			return true;
		}
예제 #10
0
		private static bool BackrefMatcher(REGlobalData gData, int parenIndex, string input, int end)
		{
			int len;
			int i;
			if (gData.parens == null || parenIndex >= gData.parens.Length)
			{
				return false;
			}
			int parenContent = gData.ParensIndex(parenIndex);
			if (parenContent == -1)
			{
				return true;
			}
			len = gData.ParensLength(parenIndex);
			if ((gData.cp + len) > end)
			{
				return false;
			}
			if ((gData.regexp.flags & JSREG_FOLD) != 0)
			{
				for (i = 0; i < len; i++)
				{
					char c1 = input[parenContent + i];
					char c2 = input[gData.cp + i];
					if (c1 != c2 && Upcase(c1) != Upcase(c2))
					{
						return false;
					}
				}
			}
			else
			{
				if (!input.RegionMatches(parenContent, input, gData.cp, len))
				{
					return false;
				}
			}
			gData.cp += len;
			return true;
		}
예제 #11
0
		private static bool FlatNMatcher(REGlobalData gData, int matchChars, int length, string input, int end)
		{
			if ((gData.cp + length) > end)
			{
				return false;
			}
			for (int i = 0; i < length; i++)
			{
				if (gData.regexp.source[matchChars + i] != input[gData.cp + i])
				{
					return false;
				}
			}
			gData.cp += length;
			return true;
		}
예제 #12
0
		private static void PushBackTrackState(REGlobalData gData, byte op, int pc, int cp, int continuationOp, int continuationPc)
		{
			gData.backTrackStackTop = new REBackTrackData(gData, op, pc, cp, continuationOp, continuationPc);
		}
예제 #13
0
		private static void PushBackTrackState(REGlobalData gData, byte op, int pc)
		{
			REProgState state = gData.stateStackTop;
			gData.backTrackStackTop = new REBackTrackData(gData, op, pc, gData.cp, state.continuationOp, state.continuationPc);
		}
예제 #14
0
		private static REProgState PopProgState(REGlobalData gData)
		{
			REProgState state = gData.stateStackTop;
			gData.stateStackTop = state.previous;
			return state;
		}
예제 #15
0
		private static void PushProgState(REGlobalData gData, int min, int max, int cp, REBackTrackData backTrackLastToSave, int continuationOp, int continuationPc)
		{
			gData.stateStackTop = new REProgState(gData.stateStackTop, min, max, cp, backTrackLastToSave, continuationOp, continuationPc);
		}