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