3 // namespace: System.Text.RegularExpressions
\r
6 // author: Dan Lewis (dlewis@gmx.co.uk)
\r
11 namespace System.Text.RegularExpressions {
\r
14 public class Capture {
\r
18 return 0; // capture not completed
\r
19 else if (start <= end)
\r
20 return start; // normal capture
\r
22 return end; // reverse capture
\r
30 else if (start <= end)
\r
37 public string Value {
\r
38 get { return IsDefined ? text.Substring (Index, Length) : ""; }
\r
41 public override string ToString () {
\r
47 internal Capture () { // empty capture
\r
48 this.previous = null;
\r
50 this.checkpoint = 0;
\r
56 internal Capture (Capture cap) { // copy constructor
\r
57 this.previous = cap.previous;
\r
58 this.text = cap.text;
\r
59 this.checkpoint = cap.checkpoint;
\r
61 this.start = cap.start;
\r
65 internal Capture (string text) { // first capture
\r
66 this.previous = null;
\r
68 this.checkpoint = 0;
\r
74 internal Capture (Capture previous, int checkpoint) {
\r
75 this.previous = previous;
\r
76 this.text = previous.text;
\r
77 this.checkpoint = checkpoint;
\r
83 internal Capture Previous {
\r
84 get { return previous; }
\r
87 internal string Text {
\r
88 get { return text; }
\r
91 internal int Checkpoint {
\r
92 get { return checkpoint; }
\r
95 internal bool IsDefined {
\r
96 get { return start >= 0 && end >= 0; }
\r
99 internal Capture GetLastDefined () {
\r
100 Capture cap = this;
\r
101 while (cap != null && !cap.IsDefined)
\r
102 cap = cap.Previous;
\r
107 internal void Open (int ptr) {
\r
111 internal void Close (int ptr) {
\r
117 private int start, end;
\r
118 private string text;
\r
119 private int checkpoint;
\r
120 private Capture previous;
\r
123 public class Group : Capture {
\r
124 public static Group Synchronized (Group inner) {
\r
125 return inner; // is this enough?
\r
128 public CaptureCollection Captures {
\r
129 get { return captures; }
\r
132 public bool Success {
\r
133 get { return GetLastDefined () != null; }
\r
138 internal Group () : base () {
\r
141 internal Group (Capture last) : base (last) {
\r
142 captures = new CaptureCollection (last);
\r
144 // TODO make construction of captures lazy
\r
147 private CaptureCollection captures;
\r
150 public class Match : Group {
\r
151 public static Match Empty {
\r
152 get { return empty; }
\r
155 public static Match Synchronized (Match inner) {
\r
156 return inner; // FIXME need to sync on machine access
\r
159 public GroupCollection Groups {
\r
160 get { return groups; }
\r
163 public Match NextMatch () {
\r
167 int scan_ptr = regex.RightToLeft ? Index : Index + Length;
\r
169 // next match after an empty match: make sure scan ptr makes progress
\r
172 scan_ptr += regex.RightToLeft ? -1 : +1;
\r
174 return machine.Scan (regex, Text, scan_ptr, text_length);
\r
177 public virtual string Result (string replacement) {
\r
178 return ReplacementEvaluator.Evaluate (replacement, this);
\r
183 internal Match () : base () {
\r
185 this.machine = null;
\r
186 this.text_length = 0;
\r
187 this.groups = new GroupCollection ();
\r
192 internal Match (Regex regex, IMachine machine, int text_length, Capture[] captures) : base (captures[0]) {
\r
193 this.regex = regex;
\r
194 this.machine = machine;
\r
195 this.text_length = text_length;
\r
196 this.groups = new GroupCollection ();
\r
199 for (int i = 1; i < captures.Length; ++ i)
\r
200 groups.Add (new Group (captures[i]));
\r
203 internal Regex Regex {
\r
204 get { return regex; }
\r
209 private Regex regex;
\r
210 private IMachine machine;
\r
211 private int text_length;
\r
212 private GroupCollection groups;
\r
214 private static Match empty = new Match ();
\r