Ejemplo n.º 1
0
		/// <summary>
		/// 返回表示单个不区分大小写的字符的正则表达式。
		/// </summary>
		/// <param name="ch">要表示的字符。</param>
		/// <param name="culture">转换大小写使用的区域性信息。</param>
		/// <returns>表示单个字符的正则表达式。</returns>
		public static Regex SymbolIgnoreCase(char ch, CultureInfo culture)
		{
			char upperCase = char.ToUpper(ch, culture);
			char lowerCase = char.ToLower(ch, culture);
			RegexCharClass cc = new RegexCharClass();
			if (upperCase == lowerCase)
			{
				// 大小写相同。
				cc.AddChar(upperCase);
			}
			else
			{
				// 大小写不用。
				cc.AddChar(upperCase);
				cc.AddChar(lowerCase);
			}
			return new CharClassExp(cc.ToStringClass());
		}
Ejemplo n.º 2
0
		/// <summary>
		/// 返回表示字符类的正则表达式。
		/// </summary>
		/// <param name="cc">正则表达式表示的字符类。</param>
		/// <returns>表示字符类的正则表达式。</returns>
		public static Regex CharClass(RegexCharClass cc)
		{
			if (cc == null)
			{
				throw CommonExceptions.ArgumentNull("cc");
			}
			return new CharClassExp(cc.ToStringClass());
		}
Ejemplo n.º 3
0
		/// <summary>
		/// 扫描 '\'(不包含 '\' 本身)之后的字符,并返回相应的正则表达式。
		/// </summary>
		/// <returns>相应的正则表达式。</returns>
		private Regex ScanBackslash()
		{
			RegexCharClass cc;
			int ich;
			switch (ich = reader.Read())
			{
				case 'w':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.EcmaWordClass : RegexCharClass.WordClass);
				case 'W':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.NotEcmaWordClass : RegexCharClass.NotWordClass);
				case 's':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.EcmaSpaceClass : RegexCharClass.SpaceClass);
				case 'S':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.NotEcmaSpaceClass : RegexCharClass.NotSpaceClass);
				case 'd':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.EcmaDigitClass : RegexCharClass.DigitClass);
				case 'D':
					return Regex.CharClass(
						UseOptionEcma ? RegexCharClass.NotEcmaDigitClass : RegexCharClass.NotDigitClass);
				case 'p':
				case 'P':
					cc = new RegexCharClass();
					cc.AddCategoryFromName(ScanProperty(), ich != 'p', UseOptionIgnoreCase, pattern);
					if (UseOptionIgnoreCase)
					{
						cc.AddLowercase(culture);
					}
					return Regex.CharClass(cc.ToStringClass());
				case -1:
					ThrowIllegalEndEscape();
					return null;
				default:
					reader.Unget();
					char ch = ScanCharEscape();
					if (UseOptionIgnoreCase)
					{
						return Regex.SymbolIgnoreCase(ch, culture);
					}
					else
					{
						return Regex.Symbol(ch);
					}
			}
		}
Ejemplo n.º 4
0
		/// <summary>
		/// 返回表示单个字符的正则表达式。
		/// </summary>
		/// <param name="ch">要表示的字符。</param>
		/// <returns>表示单个字符的正则表达式。</returns>
		public static Regex Symbol(char ch)
		{
			RegexCharClass cc = new RegexCharClass();
			cc.AddChar(ch);
			return new CharClassExp(cc.ToStringClass());
		}
Ejemplo n.º 5
0
		private RegexCharClass ScanCharClass(bool closeBracket)
		{
			RegexCharClass rcc = new RegexCharClass();
			// 是否正在定义字符范围。
			bool inRange = false;
			// 是否是首字符。
			bool firstChar = true;
			// [] 集合是否闭合。
			bool closed = false;
			// 否定的字符类。
			if (reader.Peek() == '^')
			{
				reader.Read();
				rcc.Negate = true;
			}
			int ich = '\0';
			char chPrev = '\0';
			for (; (ich = reader.Read()) >= 0; firstChar = false)
			{
				// 当前字符时候是由转义得到的。
				bool escapedChar = false;
				if (ich == ']')
				{
					// [ 之后的第一个 ] 认为是字符 ]。
					if (!firstChar)
					{
						// 闭合字符类。
						closed = true;
						break;
					}
				}
				else if (ich == '\\' && reader.Peek() >= 0)
				{
					// 判断 '\' 字符的转义。
					ich = ScanBackslash(rcc, inRange);
					if (ich == -1)
					{
						continue;
					}
				}
				if (inRange)
				{
					inRange = false;
					if (ich == '[' && !escapedChar && !firstChar)
					{
						// 本来认为在定义字符范围,但实际在定义一个减去范围。
						// 所以,需要将 chPrev 添加到字符类中,跳过 [ 符号,并递归的扫描新的字符类。
						rcc.AddChar(chPrev);
						rcc.AddSubtraction(ScanCharClass(true));
						if (reader.Peek() >= 0 && reader.Peek() != ']')
						{
							ThrowSubtractionMustBeLast();
						}
					}
					else
					{
						// 规则的字符范围,类似于 a-z。
						if (chPrev > ich)
						{
							ThrowReversedCharRange();
						}
						rcc.AddRange(chPrev, (char)ich);
					}
				}
				else
				{
					if (reader.Peek() == '-')
					{
						reader.Read();
						if (reader.Peek() >= 0 && reader.Peek() != ']')
						{
							// -] 中的,'-' 会按连字符处理。
							// 否则的话,认为是字符范围的起始。
							chPrev = (char)ich;
							inRange = true;
						}
						else
						{
							reader.Unget();
						}
					}
					if (!inRange)
					{
						if (ich == '-' && reader.Peek() == '[' && !escapedChar && !firstChar)
						{
							// 不在字符范围中,并且开始一个减去范围的定义,
							// 一般是由于减去范围紧跟着一个字符范围,例如 [a-z-[b]]。
							reader.Read();
							rcc.AddSubtraction(ScanCharClass(true));
							if (reader.Peek() >= 0 && reader.Peek() != ']')
							{
								ThrowSubtractionMustBeLast();
							}
						}
						else
						{
							rcc.AddRange((char)ich, (char)ich);
						}
					}
				}
			}
			reader.Drop();
			// 模式字符串已到达结尾也按闭合处理。
			if (!closed && closeBracket)
			{
				ThrowUnterminatedBracket();
			}
			if (UseOptionIgnoreCase)
			{
				rcc.AddLowercase(culture);
				rcc.AddUppercase(culture);
			}
			return rcc;
		}
Ejemplo n.º 6
0
		/// <summary>
		/// 扫描 '\'(不包含 '\' 本身)之后的字符,并返回相应的字符。
		/// </summary>
		/// <param name="rcc">要添加到的字符类。</param>
		/// <param name="inRange">当前是否正在定义字符范围。</param>
		/// <returns>相应的字符,如果不是字符,则为 <c>-1</c>。</returns>
		private int ScanBackslash(RegexCharClass rcc, bool inRange)
		{
			// 判断 '\' 字符的转义。
			int ich = reader.Read();
			switch (ich)
			{
				case 'D':
				case 'd':
					if (inRange)
					{
						ThrowBadClassInCharRange((char)ich);
					}
					rcc.AddDigit(UseOptionEcma, ich == 'D', pattern);
					return -1;
				case 'S':
				case 's':
					if (inRange)
					{
						ThrowBadClassInCharRange((char)ich);
					}
					rcc.AddSpace(UseOptionEcma, ich == 'S');
					return -1;
				case 'W':
				case 'w':
					if (inRange)
					{
						ThrowBadClassInCharRange((char)ich);
					}
					rcc.AddWord(UseOptionEcma, ich == 'W');
					return -1;
				case 'p':
				case 'P':
					if (inRange)
					{
						ThrowBadClassInCharRange((char)ich);
					}
					rcc.AddCategoryFromName(ScanProperty(), (ich != 'p'), UseOptionIgnoreCase, pattern);
					return -1;
				default:
					reader.Unget();
					// 读入转义字符。
					return ScanCharEscape();
			}
		}
Ejemplo n.º 7
0
		/// <summary>
		/// 添加要排除的字符类。
		/// </summary>
		/// <param name="subCharClass">要排除的字符类。</param>
		public void AddSubtraction(RegexCharClass subCharClass)
		{
			RccAddSubtraction.Value(charClass, subCharClass.charClass);
		}
Ejemplo n.º 8
0
		/// <summary>
		/// 添加指定字符类。
		/// </summary>
		/// <param name="cc">要添加的字符类。</param>
		public void AddCharClass(RegexCharClass cc)
		{
			// 这个方法的原版实现会直接将 cc 中的字符范围添加到当前类中,
			// 而不是复制副本,有时会导致出错。
			if (!(cc.CanMerge && this.CanMerge))
			{
				CompilerCommonExceptions.RegexCharClassCannotMerge("charClass");
			}
			int ccRangeCount = RccRangeCount.Value(cc.charClass);
			int thisRangeCount = RccRangeCount.Value(this.charClass);
			if (!RccGetCanonical.Value(cc.charClass))
			{
				// 如果要合并的字符类并不规范,则自己也不规范。
				RccSetCanonical.Value(this.charClass, false);
			}
			else if (RccGetCanonical.Value(this.charClass) && thisRangeCount > 0 && ccRangeCount > 0 &&
				RccSRGetFirst.Value(RccGetRangeAt.Value(cc.charClass, 0)) <=
					RccSRGetLast.Value(RccGetRangeAt.Value(this, thisRangeCount - 1)))
			{
				// Range 不能恰好接起来,那么也会导致不规范。
				RccSetCanonical.Value(this.charClass, false);
			}
			IList list = RccGetRangelist.Value(this.charClass);
			for (int i = 0; i < ccRangeCount; i += 1)
			{
				object range = RccGetRangeAt.Value(cc.charClass, i);
				// 这里创建一个新的字符范围。
				list.Add(RccSRConstructor.Value(RccSRGetFirst.Value(range), RccSRGetLast.Value(range)));
			}
			RccGetCategories.Value(this.charClass).Append(RccGetCategories.Value(cc.charClass).ToString());
		}
Ejemplo n.º 9
0
 /// <summary>
 /// 添加要排除的字符类。
 /// </summary>
 /// <param name="subCharClass">要排除的字符类。</param>
 public void AddSubtraction(RegexCharClass subCharClass)
 {
     RccAddSubtraction.Value(charClass, subCharClass.charClass);
 }
Ejemplo n.º 10
0
		/// <summary>
		/// 根据当前的正则表达式构造 NFA。
		/// </summary>
		/// <param name="nfa">要构造的 NFA。</param>
		internal override void BuildNfa(Nfa nfa)
		{
			string str = literal;
			if (ignoreCase)
			{
				str = literal.ToUpper(culture);
			}
			nfa.HeadState = nfa.NewState();
			nfa.TailState = nfa.HeadState;
			for (int i = 0; i < literal.Length; i++)
			{
				NfaState state = nfa.NewState();
				if (culture == null)
				{
					// 区分大小写。
					nfa.TailState.Add(state, str[i]);
				}
				else
				{
					// 不区分大小写。
					RegexCharClass cc = new RegexCharClass();
					cc.AddChar(str[i]);
					cc.AddChar(char.ToLower(str[i], culture));
					nfa.TailState.Add(state, cc.ToStringClass());
				}
				nfa.TailState = state;
			}
		}
Ejemplo n.º 11
0
		/// <summary>
		/// 返回表示字符类的正则表达式。
		/// </summary>
		/// <param name="cc">正则表达式表示的字符类。</param>
		/// <returns>表示字符类的正则表达式。</returns>
		public static Regex CharClass(RegexCharClass cc)
		{
			ExceptionHelper.CheckArgumentNull(cc, "cc");
			return new CharClassExp(cc.ToStringClass());
		}