3 // namespace: System.Text.RegularExpressions
\r
6 // author: Dan Lewis (dlewis@gmx.co.uk)
\r
11 using System.Collections;
\r
12 using System.Reflection;
\r
13 using System.Reflection.Emit;
\r
14 using System.Runtime.Serialization;
\r
16 using RegularExpression = System.Text.RegularExpressions.Syntax.RegularExpression;
\r
17 using Parser = System.Text.RegularExpressions.Syntax.Parser;
\r
19 namespace System.Text.RegularExpressions {
\r
21 public delegate string MatchEvaluator (Match match);
\r
24 public enum RegexOptions {
\r
28 ExplicitCapture = 0x004,
\r
31 IgnorePatternWhitespace = 0x020,
\r
32 RightToLeft = 0x040,
\r
37 public class Regex : ISerializable {
\r
38 public static void CompileToAssembly
\r
39 (RegexCompilationInfo[] regexes, AssemblyName aname)
\r
41 throw new Exception ("Not implemented.");
\r
44 public static void CompileToAssembly
\r
45 (RegexCompilationInfo[] regexes, AssemblyName aname,
\r
46 CustomAttributeBuilder[] attribs)
\r
48 throw new Exception ("Not implemented.");
\r
51 public static void CompileToAssembly
\r
52 (RegexCompilationInfo[] regexes, AssemblyName aname,
\r
53 CustomAttributeBuilder[] attribs, string resourceFile)
\r
55 throw new Exception ("Not implemented.");
\r
58 public static string Escape (string str) {
\r
59 return Parser.Escape (str);
\r
62 public static string Unescape (string str) {
\r
63 return Parser.Unescape (str);
\r
66 public static bool IsMatch (string input, string pattern) {
\r
67 return IsMatch (input, pattern, RegexOptions.None);
\r
70 public static bool IsMatch (string input, string pattern, RegexOptions options) {
\r
71 Regex re = new Regex (pattern, options);
\r
72 return re.IsMatch (input);
\r
75 public static Match Match (string input, string pattern) {
\r
76 return Regex.Match (input, pattern, RegexOptions.None);
\r
79 public static Match Match (string input, string pattern, RegexOptions options) {
\r
80 Regex re = new Regex (pattern, options);
\r
81 return re.Match (input);
\r
84 public static MatchCollection Matches (string input, string pattern) {
\r
85 return Matches (input, pattern, RegexOptions.None);
\r
88 public static MatchCollection Matches (string input, string pattern, RegexOptions options) {
\r
89 Regex re = new Regex (pattern, options);
\r
90 return re.Matches (input);
\r
93 public static string Replace
\r
94 (string input, string pattern, MatchEvaluator evaluator)
\r
96 return Regex.Replace (input, pattern, evaluator, RegexOptions.None);
\r
99 public static string Replace
\r
100 (string input, string pattern, MatchEvaluator evaluator,
\r
101 RegexOptions options)
\r
103 Regex re = new Regex (pattern, options);
\r
104 return re.Replace (input, evaluator);
\r
107 public static string Replace
\r
108 (string input, string pattern, string replacement)
\r
110 return Regex.Replace (input, pattern, replacement, RegexOptions.None);
\r
113 public static string Replace
\r
114 (string input, string pattern, string replacement,
\r
115 RegexOptions options)
\r
117 Regex re = new Regex (pattern, options);
\r
118 return re.Replace (input, replacement);
\r
121 public static string[] Split (string input, string pattern) {
\r
122 return Regex.Split (input, pattern, RegexOptions.None);
\r
125 public static string[] Split (string input, string pattern, RegexOptions options) {
\r
126 Regex re = new Regex (pattern, options);
\r
127 return re.Split (input);
\r
132 private static FactoryCache cache = new FactoryCache (200); // TODO put some meaningful number here
\r
136 protected Regex () {
\r
137 // XXX what's this constructor for?
\r
140 public Regex (string pattern) : this (pattern, RegexOptions.None) {
\r
143 public Regex (string pattern, RegexOptions options) {
\r
144 this.pattern = pattern;
\r
145 this.options = options;
\r
147 this.factory = cache.Lookup (pattern, options);
\r
149 if (this.factory == null) {
\r
150 // parse and install group mapping
\r
152 Parser psr = new Parser ();
\r
153 RegularExpression re = psr.ParseRegularExpression (pattern, options);
\r
154 this.group_count = re.GroupCount;
\r
155 this.mapping = psr.GetMapping ();
\r
160 //if ((options & RegexOptions.Compiled) != 0)
\r
161 // throw new Exception ("Not implemented.");
\r
162 //cmp = new CILCompiler ();
\r
164 cmp = new PatternCompiler ();
\r
166 re.Compile (cmp, RightToLeft);
\r
168 // install machine factory and add to pattern cache
\r
170 this.factory = cmp.GetMachineFactory ();
\r
171 this.factory.Mapping = mapping;
\r
172 cache.Add (pattern, options, this.factory);
\r
174 this.group_count = this.factory.GroupCount;
\r
175 this.mapping = this.factory.Mapping;
\r
179 protected Regex (SerializationInfo info, StreamingContext context) :
\r
180 this (info.GetString ("pattern"),
\r
181 (RegexOptions) info.GetValue ("options", typeof (RegexOptions))) {
\r
185 // public instance properties
\r
187 public RegexOptions Options {
\r
188 get { return options; }
\r
191 public bool RightToLeft {
\r
192 get { return (options & RegexOptions.RightToLeft) != 0; }
\r
195 // public instance methods
\r
197 public string[] GetGroupNames () {
\r
198 string[] names = new string[mapping.Count];
\r
199 mapping.Keys.CopyTo (names, 0);
\r
204 public int[] GetGroupNumbers () {
\r
205 int[] numbers = new int[mapping.Count];
\r
206 mapping.Values.CopyTo (numbers, 0);
\r
211 public string GroupNameFromNumber (int i) {
\r
212 if (i >= group_count)
\r
215 foreach (string name in mapping.Keys) {
\r
216 if ((int)mapping[name] == i)
\r
223 public int GroupNumberFromName (string name) {
\r
224 if (mapping.Contains (name))
\r
225 return (int)mapping[name];
\r
232 public bool IsMatch (string input) {
\r
233 return IsMatch (input, 0);
\r
236 public bool IsMatch (string input, int startat) {
\r
237 return Match (input, startat).Success;
\r
240 public Match Match (string input) {
\r
241 return Match (input, 0);
\r
244 public Match Match (string input, int startat) {
\r
245 return CreateMachine ().Scan (this, input, startat, input.Length);
\r
248 public Match Match (string input, int startat, int length) {
\r
249 return CreateMachine ().Scan (this, input, startat, startat + length);
\r
252 public MatchCollection Matches (string input) {
\r
253 return Matches (input, 0);
\r
256 public MatchCollection Matches (string input, int startat) {
\r
257 MatchCollection ms = new MatchCollection ();
\r
258 Match m = Match (input, startat);
\r
259 while (m.Success) {
\r
261 m = m.NextMatch ();
\r
269 public string Replace (string input, MatchEvaluator evaluator) {
\r
270 return Replace (input, evaluator, Int32.MaxValue, 0);
\r
273 public string Replace (string input, MatchEvaluator evaluator, int count) {
\r
274 return Replace (input, evaluator, count, 0);
\r
277 public string Replace (string input, MatchEvaluator evaluator, int count, int startat)
\r
279 StringBuilder result = new StringBuilder ();
\r
282 Match m = Match (input, startat);
\r
283 while (m.Success && count -- > 0) {
\r
284 result.Append (input.Substring (ptr, m.Index - ptr));
\r
285 result.Append (evaluator (m));
\r
287 ptr = m.Index + m.Length;
\r
288 m = m.NextMatch ();
\r
290 result.Append (input.Substring (ptr));
\r
292 return result.ToString ();
\r
295 public string Replace (string input, string replacement) {
\r
296 return Replace (input, replacement, Int32.MaxValue, 0);
\r
299 public string Replace (string input, string replacement, int count) {
\r
300 return Replace (input, replacement, count, 0);
\r
303 public string Replace (string input, string replacement, int count, int startat) {
\r
304 ReplacementEvaluator ev = new ReplacementEvaluator (this, replacement);
\r
305 return Replace (input, new MatchEvaluator (ev.Evaluate), count, startat);
\r
310 public string[] Split (string input) {
\r
311 return Split (input, Int32.MaxValue, 0);
\r
314 public string[] Split (string input, int count) {
\r
315 return Split (input, count, 0);
\r
318 public string[] Split (string input, int count, int startat) {
\r
319 ArrayList splits = new ArrayList ();
\r
321 count = Int32.MaxValue;
\r
324 while (--count > 0) {
\r
325 Match m = Match (input, ptr);
\r
329 splits.Add (input.Substring (ptr, m.Index - ptr));
\r
330 int gcount = m.Groups.Count;
\r
331 for (int gindex = 1; gindex < gcount; gindex++) {
\r
332 Group grp = m.Groups [gindex];
\r
333 splits.Add (input.Substring (grp.Index, grp.Length));
\r
336 ptr = m.Index + m.Length;
\r
339 if (ptr < input.Length) {
\r
340 splits.Add (input.Substring (ptr));
\r
343 return (string []) splits.ToArray (typeof (string));
\r
348 public override string ToString () {
\r
352 // ISerializable interface
\r
353 public virtual void GetObjectData (SerializationInfo info, StreamingContext context) {
\r
354 info.AddValue ("pattern", this.ToString (), typeof (string));
\r
355 info.AddValue ("options", this.Options, typeof (RegexOptions));
\r
360 internal int GroupCount {
\r
361 get { return group_count; }
\r
366 private IMachine CreateMachine () {
\r
367 return factory.NewInstance ();
\r
370 protected internal string pattern;
\r
371 private RegexOptions options;
\r
373 private IMachineFactory factory;
\r
374 private IDictionary mapping;
\r
375 private int group_count;
\r
379 public class RegexCompilationInfo {
\r
380 public RegexCompilationInfo (string pattern, RegexOptions options, string name, string full_namespace, bool is_public) {
\r
381 this.pattern = pattern;
\r
382 this.options = options;
\r
384 this.full_namespace = full_namespace;
\r
385 this.is_public = is_public;
\r
388 public bool IsPublic {
\r
389 get { return is_public; }
\r
390 set { is_public = value; }
\r
393 public string Name {
\r
394 get { return name; }
\r
395 set { name = value; }
\r
398 public string Namespace {
\r
399 get { return full_namespace; }
\r
400 set { full_namespace = value; }
\r
403 public RegexOptions Options {
\r
404 get { return options; }
\r
405 set { options = value; }
\r
408 public string Pattern {
\r
409 get { return pattern; }
\r
410 set { pattern = value; }
\r
415 private string pattern, name, full_namespace;
\r
416 private RegexOptions options;
\r
417 private bool is_public;
\r