2 // Expression.cs: Stores references to items or properties.
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
34 using Microsoft.Build.Framework;
35 using Microsoft.Build.Utilities;
37 namespace Microsoft.Build.BuildEngine {
38 internal class Expression {
42 ItemReference parentItemReference;
44 public Expression (Project project)
46 this.objects = new ArrayList ();
47 this.project = project;
50 public Expression (Project project, string source)
56 public void ParseSource (string source)
58 // FIXME: change StringBuilder to substrings
60 throw new ArgumentNullException ("source");
63 source = source.Replace ('/', Path.DirectorySeparatorChar);
64 source = source.Replace ('\\', Path.DirectorySeparatorChar);
65 StringBuilder temp = new StringBuilder ();
66 CharEnumerator it = source.GetEnumerator ();
67 EvaluationState eState = EvaluationState.Out;
68 ParenState pState = ParenState.Out;
69 ApostropheState aState = ApostropheState.Out;
73 while (it.MoveNext ()) {
76 case EvaluationState.Out:
79 if (temp.Length > 0) {
80 objects.Add (temp.ToString ());
81 temp = new StringBuilder ();
83 eState = EvaluationState.InItem;
87 if (temp.Length > 0) {
88 objects.Add (temp.ToString ());
89 temp = new StringBuilder ();
91 eState = EvaluationState.InProperty;
95 if (temp.Length > 0) {
96 objects.Add (temp.ToString ());
97 temp = new StringBuilder ();
99 eState = EvaluationState.InMetadata;
103 temp.Append (it.Current);
104 if (current == source.Length - 1)
105 objects.Add (temp.ToString ());
109 case EvaluationState.InItem:
110 switch (it.Current) {
112 if (pState == ParenState.Out && aState == ApostropheState.Out)
113 pState = ParenState.Left;
114 else if (aState == ApostropheState.Out)
115 throw new Exception ("'(' not expected.");
118 if (pState == ParenState.Left && aState == ApostropheState.Out) {
119 objects.Add (new ItemReference (this, source.Substring (start, current - start + 1)));
120 eState = EvaluationState.Out;
121 pState = ParenState.Out;
125 if (aState == ApostropheState.In)
126 aState = ApostropheState.Out;
128 aState = ApostropheState.In;
134 case EvaluationState.InProperty:
135 switch (it.Current) {
137 if (pState == ParenState.Out)
138 pState = ParenState.Left;
140 throw new Exception ("'(' expected.");
143 if (pState == ParenState.Left) {
144 objects.Add (new PropertyReference (this, source.Substring (start, current - start + 1)));
145 eState = EvaluationState.Out;
146 pState = ParenState.Out;
153 case EvaluationState.InMetadata:
154 switch (it.Current) {
156 if (pState == ParenState.Out)
157 pState = ParenState.Left;
160 if (pState == ParenState.Left) {
161 objects.Add (new MetadataReference (this, source.Substring (start, current - start + 1)));
162 eState = EvaluationState.Out;
163 pState = ParenState.Out;
171 throw new Exception ("Invalid evaluation state.");
176 public IEnumerator GetEnumerator ()
178 foreach (object o in objects)
182 public object ToNonArray (Type type)
184 if (type.IsArray == true)
185 throw new ArgumentException ("Type specified can not be array type.");
187 return ToObject (ToString (), type);
190 public object ToArray (Type type)
192 if (type.IsArray == false)
193 throw new ArgumentException ("Type specified can not be element type.");
195 string[] rawTable = ToString ().Split (';');
198 if (type == typeof (bool[])) {
199 bool[] array = new bool [rawTable.Length];
200 foreach (string raw in rawTable)
201 array [i++] = (bool) ToObject (raw, typeof (bool));
203 } else if (type == typeof (string[])) {
204 string[] array = new string [rawTable.Length];
205 foreach (string raw in rawTable)
206 array [i++] = (string) ToObject (raw, typeof (string));
208 } else if (type == typeof (int[])) {
209 int[] array = new int [rawTable.Length];
210 foreach (string raw in rawTable)
211 array [i++] = (int) ToObject (raw, typeof (int));
213 } else if (type == typeof (uint[])) {
214 uint[] array = new uint [rawTable.Length];
215 foreach (string raw in rawTable)
216 array [i++] = (uint) ToObject (raw, typeof (uint));
218 } else if (type == typeof (DateTime[])) {
219 DateTime[] array = new DateTime [rawTable.Length];
220 foreach (string raw in rawTable)
221 array [i++] = (DateTime) ToObject (raw, typeof (DateTime));
223 } else throw new Exception ("Invalid type.");
226 private object ToObject (string raw, Type type)
228 if (type == typeof (bool)) {
229 return Boolean.Parse (raw);
230 } else if (type == typeof (string)) {
232 } else if (type == typeof (int)) {
233 return Int32.Parse (raw);
234 } else if (type == typeof (uint)) {
235 return UInt32.Parse (raw);
236 } else if (type == typeof (DateTime)) {
237 return DateTime.Parse (raw);
239 throw new Exception (String.Format ("Unknown type: {0}", type.ToString ()));
243 private new string ToString ()
245 StringBuilder sb = new StringBuilder ();
247 foreach (object o in this) {
249 sb.Append ((string) o);
250 } else if (o is ItemReference) {
251 sb.Append (((ItemReference)o).ToString ());
252 } else if (o is PropertyReference) {
253 sb.Append (((PropertyReference)o).ToString ());
254 } else if (o is MetadataReference) {
255 // FIXME: we don't handle them yet
257 throw new Exception ("Invalid type in objects collection.");
260 return sb.ToString ();
263 public ITaskItem ToITaskItem ()
268 throw new Exception ("Cannot cast empty expression to ITaskItem.");
270 if (objects [0] is ItemReference) {
271 ItemReference ir = (ItemReference) objects [0];
272 ITaskItem[] array = ir.ToITaskItemArray ();
273 if (array.Length == 1) {
276 throw new Exception ("TaskItem array too long");
279 item = new TaskItem (ToString ());
284 public ITaskItem[] ToITaskItemArray ()
286 ArrayList finalItems = new ArrayList ();
287 ArrayList tempItems = new ArrayList ();
289 ITaskItem[] finalArray;
291 foreach (object o in objects) {
292 if (o is ItemReference) {
294 } else if (o is PropertyReference) {
295 PropertyReference pr = (PropertyReference) o;
296 tempItems.Add (pr.ToString ());
297 } else if (o is MetadataReference) {
298 // FIXME: not handled yet
299 } else if (o is string) {
302 throw new Exception ("Invalid type in objects collection.");
305 foreach (object o in tempItems) {
306 if (o is ItemReference) {
307 ItemReference ir = (ItemReference) o;
308 array = ir.ToITaskItemArray ();
310 foreach (ITaskItem item in array)
311 finalItems.Add (item);
312 } else if (o is string) {
313 string s = (string) o;
314 array = ITaskItemArrayFromString (s);
315 foreach (ITaskItem item in array)
316 finalItems.Add (item);
318 throw new Exception ("Invalid type in tempItems collection.");
322 finalArray = new ITaskItem [finalItems.Count];
324 foreach (ITaskItem item in finalItems)
325 finalArray [i++] = item;
329 // FIXME: quite stupid name
330 private ITaskItem[] ITaskItemArrayFromString (string source)
332 ArrayList tempItems = new ArrayList ();
333 ITaskItem[] finalArray;
334 string[] splittedSource = source.Split (';');
335 foreach (string s in splittedSource) {
336 if (s != String.Empty) {
337 tempItems.Add (new TaskItem (s));
340 finalArray = new ITaskItem [tempItems.Count];
342 foreach (ITaskItem item in tempItems)
343 finalArray [i++] = item;
347 public Project Project {
348 get { return project; }
351 public ItemReference ParentItemReference {
352 get { return parentItemReference; }
356 internal enum EvaluationState {
363 internal enum ParenState {
368 internal enum ApostropheState {
373 internal enum ItemParsingState {