6 |
// author: Dan Lewis (dlewis@gmx.co.uk) |
// author: Dan Lewis (dlewis@gmx.co.uk) |
7 |
// (c) 2002 |
// (c) 2002 |
8 |
|
|
9 |
|
// |
10 |
|
// Permission is hereby granted, free of charge, to any person obtaining |
11 |
|
// a copy of this software and associated documentation files (the |
12 |
|
// "Software"), to deal in the Software without restriction, including |
13 |
|
// without limitation the rights to use, copy, modify, merge, publish, |
14 |
|
// distribute, sublicense, and/or sell copies of the Software, and to |
15 |
|
// permit persons to whom the Software is furnished to do so, subject to |
16 |
|
// the following conditions: |
17 |
|
// |
18 |
|
// The above copyright notice and this permission notice shall be |
19 |
|
// included in all copies or substantial portions of the Software. |
20 |
|
// |
21 |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
22 |
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
23 |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
24 |
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
25 |
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
26 |
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
27 |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
28 |
|
// |
29 |
|
|
30 |
using System; |
using System; |
31 |
using System.Collections; |
using System.Collections; |
32 |
using System.Globalization; |
using System.Globalization; |
115 |
} |
} |
116 |
|
|
117 |
public static string Unescape (string str) { |
public static string Unescape (string str) { |
118 |
|
if (str.IndexOf ('\\') == -1) |
119 |
|
return str; |
120 |
return new Parser ().ParseString (str); |
return new Parser ().ParseString (str); |
121 |
} |
} |
122 |
|
|
289 |
|
|
290 |
if (ptr < pattern.Length) { |
if (ptr < pattern.Length) { |
291 |
char k = pattern[ptr]; |
char k = pattern[ptr]; |
292 |
|
int min = 0, max = 0; |
293 |
|
bool lazy = false; |
294 |
|
bool haveRep = false; |
295 |
|
|
|
if (k == '?' || k == '*' || k == '+' || k == '{') { |
|
|
++ ptr; |
|
296 |
|
|
297 |
int min = 0, max = 0; |
if (k == '?' || k == '*' || k == '+') { |
298 |
bool lazy = false; |
++ ptr; |
299 |
|
haveRep = true; |
300 |
|
|
301 |
switch (k) { |
switch (k) { |
302 |
case '?': min = 0; max = 1; break; |
case '?': min = 0; max = 1; break; |
303 |
case '*': min = 0; max = 0xffff; break; |
case '*': min = 0; max = 0xffff; break; |
304 |
case '+': min = 1; max = 0xffff; break; |
case '+': min = 1; max = 0xffff; break; |
|
case '{': ParseRepetitionBounds (out min, out max, options); break; |
|
305 |
} |
} |
306 |
|
} else if (k == '{' && ptr + 1 < pattern.Length) { |
307 |
|
int saved_ptr = ptr; |
308 |
|
++ptr; |
309 |
|
haveRep = ParseRepetitionBounds (out min, out max, options); |
310 |
|
if (!haveRep) |
311 |
|
ptr = saved_ptr; |
312 |
|
} |
313 |
|
|
314 |
|
if (haveRep) { |
315 |
ConsumeWhitespace (IsIgnorePatternWhitespace (options)); |
ConsumeWhitespace (IsIgnorePatternWhitespace (options)); |
316 |
if (ptr < pattern.Length && pattern[ptr] == '?') { |
if (ptr < pattern.Length && pattern[ptr] == '?') { |
317 |
++ ptr; |
++ ptr; |
749 |
return cls; |
return cls; |
750 |
} |
} |
751 |
|
|
752 |
private void ParseRepetitionBounds (out int min, out int max, RegexOptions options) { |
private bool ParseRepetitionBounds (out int min, out int max, RegexOptions options) { |
753 |
int n, m; |
int n, m; |
754 |
|
min = max = 0; |
755 |
|
|
756 |
/* check syntax */ |
/* check syntax */ |
757 |
|
|
773 |
m = ParseNumber (10, 1, 0); |
m = ParseNumber (10, 1, 0); |
774 |
ConsumeWhitespace (IsIgnorePatternWhitespace (options)); |
ConsumeWhitespace (IsIgnorePatternWhitespace (options)); |
775 |
if (pattern[ptr ++] != '}') |
if (pattern[ptr ++] != '}') |
776 |
throw NewParseException ("Illegal {x,y} - bad value of y."); |
return false; |
777 |
break; |
break; |
778 |
default: |
default: |
779 |
throw NewParseException ("Illegal {x,y}"); |
return false; |
780 |
} |
} |
781 |
|
|
782 |
/* check bounds and ordering */ |
/* check bounds and ordering */ |
793 |
max = m; |
max = m; |
794 |
else |
else |
795 |
max = 0xffff; |
max = 0xffff; |
796 |
|
|
797 |
|
return true; |
798 |
} |
} |
799 |
|
|
800 |
private Category ParseUnicodeCategory () { |
private Category ParseUnicodeCategory () { |
944 |
// character codes |
// character codes |
945 |
|
|
946 |
case '0': |
case '0': |
947 |
|
// |
948 |
|
// Turns out that octal values can be specified |
949 |
|
// without a leading zero. But also the limit |
950 |
|
// of three character should include this first |
951 |
|
// one. |
952 |
|
// |
953 |
|
ptr--; |
954 |
int prevptr = ptr; |
int prevptr = ptr; |
955 |
int result = ParseOctal (pattern, ref ptr); |
int result = ParseOctal (pattern, ref ptr); |
956 |
if (result == -1 && prevptr == ptr) |
if (result == -1 && prevptr == ptr) |
1006 |
return Parser.ParseNumber (pattern, ref ptr, b, min, max); |
return Parser.ParseNumber (pattern, ref ptr, b, min, max); |
1007 |
} |
} |
1008 |
|
|
|
private int ParseDecimal () { |
|
|
return Parser.ParseDecimal (pattern, ref ptr); |
|
|
} |
|
|
|
|
1009 |
private static int ParseDigit (char c, int b, int n) { |
private static int ParseDigit (char c, int b, int n) { |
1010 |
switch (b) { |
switch (b) { |
1011 |
case 8: |
case 8: |
1033 |
} |
} |
1034 |
|
|
1035 |
private void ConsumeWhitespace (bool ignore) { |
private void ConsumeWhitespace (bool ignore) { |
1036 |
while (true) { |
while (ptr < pattern.Length) { |
|
if (ptr >= pattern.Length) |
|
|
break; |
|
|
|
|
1037 |
if (pattern[ptr] == '(') { |
if (pattern[ptr] == '(') { |
1038 |
if (ptr + 3 >= pattern.Length) |
if (ptr + 3 >= pattern.Length) |
1039 |
return; |
return; |
1042 |
return; |
return; |
1043 |
|
|
1044 |
ptr += 3; |
ptr += 3; |
1045 |
while (pattern[ptr ++] != ')') |
while (ptr < pattern.Length && pattern[ptr ++] != ')') |
1046 |
/* ignore */ ; |
/* ignore */ ; |
1047 |
} |
} |
1048 |
else if (ignore && pattern[ptr] == '#') { |
else if (ignore && pattern[ptr] == '#') { |
1062 |
this.pattern = pattern; |
this.pattern = pattern; |
1063 |
this.ptr = 0; |
this.ptr = 0; |
1064 |
|
|
1065 |
string result = ""; |
StringBuilder result = new StringBuilder (pattern.Length); |
1066 |
while (ptr < pattern.Length) { |
while (ptr < pattern.Length) { |
1067 |
int c = pattern[ptr ++]; |
int c = pattern[ptr ++]; |
1068 |
if (c == '\\') { |
if (c == '\\') { |
1074 |
c = '\b'; |
c = '\b'; |
1075 |
} |
} |
1076 |
} |
} |
1077 |
result += (char)c; |
result.Append ((char) c); |
1078 |
} |
} |
1079 |
|
|
1080 |
return result; |
return result.ToString (); |
1081 |
} |
} |
1082 |
|
|
1083 |
private void ResolveReferences () { |
private void ResolveReferences () { |
1154 |
return (options & RegexOptions.IgnorePatternWhitespace) != 0; |
return (options & RegexOptions.IgnorePatternWhitespace) != 0; |
1155 |
} |
} |
1156 |
|
|
|
private static bool IsRightToLeft (RegexOptions options) { |
|
|
return (options & RegexOptions.RightToLeft) != 0; |
|
|
} |
|
|
|
|
1157 |
private static bool IsECMAScript (RegexOptions options) { |
private static bool IsECMAScript (RegexOptions options) { |
1158 |
return (options & RegexOptions.ECMAScript) != 0; |
return (options & RegexOptions.ECMAScript) != 0; |
1159 |
} |
} |