regex.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //
  2. // assembly: System
  3. // namespace: System.Text.RegularExpressions
  4. // file: regex.cs
  5. //
  6. // author: Dan Lewis ([email protected])
  7. // (c) 2002
  8. using System;
  9. using System.Text;
  10. using System.Collections;
  11. using System.Reflection;
  12. using System.Reflection.Emit;
  13. using System.Runtime.Serialization;
  14. using RegularExpression = System.Text.RegularExpressions.Syntax.RegularExpression;
  15. using Parser = System.Text.RegularExpressions.Syntax.Parser;
  16. namespace System.Text.RegularExpressions {
  17. public delegate string MatchEvaluator (Match match);
  18. [Flags]
  19. public enum RegexOptions {
  20. None = 0x000,
  21. IgnoreCase = 0x001,
  22. Multiline = 0x002,
  23. ExplicitCapture = 0x004,
  24. Compiled = 0x008,
  25. Singleline = 0x010,
  26. IgnorePatternWhitespace = 0x020,
  27. RightToLeft = 0x040,
  28. ECMAScript = 0x100
  29. }
  30. [Serializable]
  31. public class Regex : ISerializable {
  32. public static void CompileToAssembly
  33. (RegexCompilationInfo[] regexes, AssemblyName aname)
  34. {
  35. throw new Exception ("Not implemented.");
  36. }
  37. public static void CompileToAssembly
  38. (RegexCompilationInfo[] regexes, AssemblyName aname,
  39. CustomAttributeBuilder[] attribs)
  40. {
  41. throw new Exception ("Not implemented.");
  42. }
  43. public static void CompileToAssembly
  44. (RegexCompilationInfo[] regexes, AssemblyName aname,
  45. CustomAttributeBuilder[] attribs, string resourceFile)
  46. {
  47. throw new Exception ("Not implemented.");
  48. }
  49. public static string Escape (string str) {
  50. return Parser.Escape (str);
  51. }
  52. public static string Unescape (string str) {
  53. return Parser.Unescape (str);
  54. }
  55. public static bool IsMatch (string input, string pattern) {
  56. return IsMatch (input, pattern, RegexOptions.None);
  57. }
  58. public static bool IsMatch (string input, string pattern, RegexOptions options) {
  59. Regex re = new Regex (pattern, options);
  60. return re.IsMatch (input);
  61. }
  62. public static Match Match (string input, string pattern) {
  63. return Regex.Match (input, pattern, RegexOptions.None);
  64. }
  65. public static Match Match (string input, string pattern, RegexOptions options) {
  66. Regex re = new Regex (pattern, options);
  67. return re.Match (input);
  68. }
  69. public static MatchCollection Matches (string input, string pattern) {
  70. return Matches (input, pattern, RegexOptions.None);
  71. }
  72. public static MatchCollection Matches (string input, string pattern, RegexOptions options) {
  73. Regex re = new Regex (pattern, options);
  74. return re.Matches (input);
  75. }
  76. public static string Replace
  77. (string input, string pattern, MatchEvaluator evaluator)
  78. {
  79. return Regex.Replace (input, pattern, evaluator, RegexOptions.None);
  80. }
  81. public static string Replace
  82. (string input, string pattern, MatchEvaluator evaluator,
  83. RegexOptions options)
  84. {
  85. Regex re = new Regex (pattern, options);
  86. return re.Replace (input, evaluator);
  87. }
  88. public static string Replace
  89. (string input, string pattern, string replacement)
  90. {
  91. return Regex.Replace (input, pattern, replacement, RegexOptions.None);
  92. }
  93. public static string Replace
  94. (string input, string pattern, string replacement,
  95. RegexOptions options)
  96. {
  97. Regex re = new Regex (pattern, options);
  98. return re.Replace (input, replacement);
  99. }
  100. public static string[] Split (string input, string pattern) {
  101. return Regex.Split (input, pattern, RegexOptions.None);
  102. }
  103. public static string[] Split (string input, string pattern, RegexOptions options) {
  104. Regex re = new Regex (pattern, options);
  105. return re.Split (input);
  106. }
  107. // private
  108. private static FactoryCache cache = new FactoryCache (200); // TODO put some meaningful number here
  109. // constructors
  110. protected Regex () {
  111. // XXX what's this constructor for?
  112. }
  113. public Regex (string pattern) : this (pattern, RegexOptions.None) {
  114. }
  115. public Regex (string pattern, RegexOptions options) {
  116. this.pattern = pattern;
  117. this.options = options;
  118. this.factory = cache.Lookup (pattern, options);
  119. if (this.factory == null) {
  120. // parse and install group mapping
  121. Parser psr = new Parser ();
  122. RegularExpression re = psr.ParseRegularExpression (pattern, options);
  123. this.group_count = re.GroupCount;
  124. this.mapping = psr.GetMapping ();
  125. // compile
  126. ICompiler cmp;
  127. //if ((options & RegexOptions.Compiled) != 0)
  128. // throw new Exception ("Not implemented.");
  129. //cmp = new CILCompiler ();
  130. //else
  131. cmp = new PatternCompiler ();
  132. re.Compile (cmp, RightToLeft);
  133. // install machine factory and add to pattern cache
  134. this.factory = cmp.GetMachineFactory ();
  135. this.factory.Mapping = mapping;
  136. cache.Add (pattern, options, this.factory);
  137. } else {
  138. this.group_count = this.factory.GroupCount;
  139. this.mapping = this.factory.Mapping;
  140. }
  141. }
  142. protected Regex (SerializationInfo info, StreamingContext context) :
  143. this (info.GetString ("pattern"),
  144. (RegexOptions) info.GetValue ("options", typeof (RegexOptions))) {
  145. }
  146. // public instance properties
  147. public RegexOptions Options {
  148. get { return options; }
  149. }
  150. public bool RightToLeft {
  151. get { return (options & RegexOptions.RightToLeft) != 0; }
  152. }
  153. // public instance methods
  154. public string[] GetGroupNames () {
  155. string[] names = new string[mapping.Count];
  156. mapping.Keys.CopyTo (names, 0);
  157. return names;
  158. }
  159. public int[] GetGroupNumbers () {
  160. int[] numbers = new int[mapping.Count];
  161. mapping.Values.CopyTo (numbers, 0);
  162. return numbers;
  163. }
  164. public string GroupNameFromNumber (int i) {
  165. if (i >= group_count)
  166. return "";
  167. foreach (string name in mapping.Keys) {
  168. if ((int)mapping[name] == i)
  169. return name;
  170. }
  171. return "";
  172. }
  173. public int GroupNumberFromName (string name) {
  174. if (mapping.Contains (name))
  175. return (int)mapping[name];
  176. return -1;
  177. }
  178. // match methods
  179. public bool IsMatch (string input) {
  180. return IsMatch (input, 0);
  181. }
  182. public bool IsMatch (string input, int startat) {
  183. return Match (input, startat).Success;
  184. }
  185. public Match Match (string input) {
  186. return Match (input, 0);
  187. }
  188. public Match Match (string input, int startat) {
  189. return CreateMachine ().Scan (this, input, startat, input.Length);
  190. }
  191. public Match Match (string input, int startat, int length) {
  192. return CreateMachine ().Scan (this, input, startat, startat + length);
  193. }
  194. public MatchCollection Matches (string input) {
  195. return Matches (input, 0);
  196. }
  197. public MatchCollection Matches (string input, int startat) {
  198. MatchCollection ms = new MatchCollection ();
  199. Match m = Match (input, startat);
  200. while (m.Success) {
  201. ms.Add (m);
  202. m = m.NextMatch ();
  203. }
  204. return ms;
  205. }
  206. // replace methods
  207. public string Replace (string input, MatchEvaluator evaluator) {
  208. return Replace (input, evaluator, Int32.MaxValue, 0);
  209. }
  210. public string Replace (string input, MatchEvaluator evaluator, int count) {
  211. return Replace (input, evaluator, count, 0);
  212. }
  213. public string Replace (string input, MatchEvaluator evaluator, int count, int startat)
  214. {
  215. StringBuilder result = new StringBuilder ();
  216. int ptr = startat;
  217. Match m = Match (input, startat);
  218. while (m.Success && count -- > 0) {
  219. result.Append (input.Substring (ptr, m.Index - ptr));
  220. result.Append (evaluator (m));
  221. ptr = m.Index + m.Length;
  222. m = m.NextMatch ();
  223. }
  224. result.Append (input.Substring (ptr));
  225. return result.ToString ();
  226. }
  227. public string Replace (string input, string replacement) {
  228. return Replace (input, replacement, Int32.MaxValue, 0);
  229. }
  230. public string Replace (string input, string replacement, int count) {
  231. return Replace (input, replacement, count, 0);
  232. }
  233. public string Replace (string input, string replacement, int count, int startat) {
  234. ReplacementEvaluator ev = new ReplacementEvaluator (this, replacement);
  235. return Replace (input, new MatchEvaluator (ev.Evaluate), count, startat);
  236. }
  237. // split methods
  238. public string[] Split (string input) {
  239. return Split (input, Int32.MaxValue, 0);
  240. }
  241. public string[] Split (string input, int count) {
  242. return Split (input, count, 0);
  243. }
  244. public string[] Split (string input, int count, int startat) {
  245. ArrayList splits = new ArrayList ();
  246. if (count == 0)
  247. count = Int32.MaxValue;
  248. int ptr = startat;
  249. while (count -- > 0) {
  250. Match m = Match (input, ptr);
  251. if (!m.Success)
  252. break;
  253. splits.Add (input.Substring (ptr, m.Index - ptr));
  254. ptr = m.Index + m.Length;
  255. }
  256. if (count > 0)
  257. splits.Add (input.Substring (ptr));
  258. string[] result = new string[splits.Count];
  259. splits.CopyTo (result);
  260. return result;
  261. }
  262. // object methods
  263. public override string ToString () {
  264. return pattern;
  265. }
  266. // ISerializable interface
  267. public virtual void GetObjectData (SerializationInfo info, StreamingContext context) {
  268. info.AddValue ("pattern", this.ToString (), typeof (string));
  269. info.AddValue ("options", this.Options, typeof (RegexOptions));
  270. }
  271. // internal
  272. internal int GroupCount {
  273. get { return group_count; }
  274. }
  275. // private
  276. private IMachine CreateMachine () {
  277. return factory.NewInstance ();
  278. }
  279. protected internal string pattern;
  280. private RegexOptions options;
  281. private IMachineFactory factory;
  282. private IDictionary mapping;
  283. private int group_count;
  284. }
  285. [Serializable]
  286. public class RegexCompilationInfo {
  287. public RegexCompilationInfo (string pattern, RegexOptions options, string name, string full_namespace, bool is_public) {
  288. this.pattern = pattern;
  289. this.options = options;
  290. this.name = name;
  291. this.full_namespace = full_namespace;
  292. this.is_public = is_public;
  293. }
  294. public bool IsPublic {
  295. get { return is_public; }
  296. set { is_public = value; }
  297. }
  298. public string Name {
  299. get { return name; }
  300. set { name = value; }
  301. }
  302. public string Namespace {
  303. get { return full_namespace; }
  304. set { full_namespace = value; }
  305. }
  306. public RegexOptions Options {
  307. get { return options; }
  308. set { options = value; }
  309. }
  310. public string Pattern {
  311. get { return pattern; }
  312. set { pattern = value; }
  313. }
  314. // private
  315. private string pattern, name, full_namespace;
  316. private RegexOptions options;
  317. private bool is_public;
  318. }
  319. }