/// <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; } }
/// <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())); }
/// <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())); }
/// <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()); }
/// <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()); }
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; }