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.
31 using System.Collections;
33 using Microsoft.Build.Framework;
34 using Microsoft.Build.Utilities;
36 namespace Microsoft.Build.BuildEngine {
37 internal class Expression {
41 ItemReference parentItemReference;
43 public Expression (Project project)
45 this.objects = new ArrayList ();
46 this.project = project;
49 public Expression (Project project, string source)
55 public void ParseSource (string source)
57 // FIXME: change StringBuilder to substrings
59 throw new ArgumentNullException ("source");
61 StringBuilder temp = new StringBuilder ();
62 CharEnumerator it = source.GetEnumerator ();
63 EvaluationState eState = EvaluationState.Out;
64 ParenState pState = ParenState.Out;
65 ApostropheState aState = ApostropheState.Out;
69 while (it.MoveNext ()) {
72 case EvaluationState.Out:
75 if (temp.Length > 0) {
76 objects.Add (temp.ToString ());
77 temp = new StringBuilder ();
79 eState = EvaluationState.InItem;
83 if (temp.Length > 0) {
84 objects.Add (temp.ToString ());
85 temp = new StringBuilder ();
87 eState = EvaluationState.InProperty;
91 if (temp.Length > 0) {
92 objects.Add (temp.ToString ());
93 temp = new StringBuilder ();
95 eState = EvaluationState.InMetadata;
99 temp.Append (it.Current);
100 if (current == source.Length - 1)
101 objects.Add (temp.ToString ());
105 case EvaluationState.InItem:
106 switch (it.Current) {
108 if (pState == ParenState.Out && aState == ApostropheState.Out)
109 pState = ParenState.Left;
110 else if (aState == ApostropheState.Out)
111 throw new Exception ("'(' not expected.");
114 if (pState == ParenState.Left && aState == ApostropheState.Out) {
115 objects.Add (new ItemReference (this, source.Substring (start, current - start + 1)));
116 eState = EvaluationState.Out;
117 pState = ParenState.Out;
121 if (aState == ApostropheState.In)
122 aState = ApostropheState.Out;
124 aState = ApostropheState.In;
130 case EvaluationState.InProperty:
131 switch (it.Current) {
133 if (pState == ParenState.Out)
134 pState = ParenState.Left;
136 throw new Exception ("'(' expected.");
139 if (pState == ParenState.Left) {
140 objects.Add (new PropertyReference (this, source.Substring (start, current - start + 1)));
141 eState = EvaluationState.Out;
142 pState = ParenState.Out;
149 case EvaluationState.InMetadata:
150 switch (it.Current) {
152 if (pState == ParenState.Out)
153 pState = ParenState.Left;
156 if (pState == ParenState.Left) {
157 objects.Add (new MetadataReference (this, source.Substring (start, current - start + 1)));
158 eState = EvaluationState.Out;
159 pState = ParenState.Out;
167 throw new Exception ("Invalid evaluation state.");
172 public IEnumerator GetEnumerator ()
174 foreach (object o in objects)
178 public object ToNonArray (Type type)
180 if (type.IsArray == true)
181 throw new ArgumentException ("Type specified can not be array type.");
183 return ToObject (ToString (), type);
186 public object ToArray (Type type)
188 if (type.IsArray == false)
189 throw new ArgumentException ("Type specified can not be element type.");
191 string[] rawTable = ToString ().Split (';');
194 if (type == typeof (bool[])) {
195 bool[] array = new bool [rawTable.Length];
196 foreach (string raw in rawTable)
197 array [i++] = (bool) ToObject (raw, typeof (bool));
199 } else if (type == typeof (string[])) {
200 string[] array = new string [rawTable.Length];
201 foreach (string raw in rawTable)
202 array [i++] = (string) ToObject (raw, typeof (string));
204 } else if (type == typeof (int[])) {
205 int[] array = new int [rawTable.Length];
206 foreach (string raw in rawTable)
207 array [i++] = (int) ToObject (raw, typeof (int));
209 } else if (type == typeof (uint[])) {
210 uint[] array = new uint [rawTable.Length];
211 foreach (string raw in rawTable)
212 array [i++] = (uint) ToObject (raw, typeof (uint));
214 } else if (type == typeof (DateTime[])) {
215 DateTime[] array = new DateTime [rawTable.Length];
216 foreach (string raw in rawTable)
217 array [i++] = (DateTime) ToObject (raw, typeof (DateTime));
219 } else throw new Exception ("Invalid type.");
222 private object ToObject (string raw, Type type)
224 if (type == typeof (bool)) {
225 return Boolean.Parse (raw);
226 } else if (type == typeof (string)) {
228 } else if (type == typeof (int)) {
229 return Int32.Parse (raw);
230 } else if (type == typeof (uint)) {
231 return UInt32.Parse (raw);
232 } else if (type == typeof (DateTime)) {
233 return DateTime.Parse (raw);
235 throw new Exception (String.Format ("Unknown type: {0}", type.ToString ()));
239 private new string ToString ()
241 StringBuilder sb = new StringBuilder ();
243 foreach (object o in this) {
245 sb.Append ((string) o);
246 } else if (o is ItemReference) {
247 sb.Append (((ItemReference)o).ToString ());
248 } else if (o is PropertyReference) {
249 sb.Append (((PropertyReference)o).ToString ());
250 } else if (o is MetadataReference) {
251 // FIXME: we don't handle them yet
253 throw new Exception ("Invalid type in objects collection.");
256 return sb.ToString ();
259 public ITaskItem ToITaskItem ()
264 throw new Exception ("Cannot cast empty expression to ITaskItem.");
266 if (objects [0] is ItemReference) {
267 ItemReference ir = (ItemReference) objects [0];
268 ITaskItem[] array = ir.ToITaskItemArray ();
269 if (array.Length == 1) {
272 throw new Exception ("TaskItem array too long");
275 item = new TaskItem (ToString ());
280 public ITaskItem[] ToITaskItemArray ()
282 ArrayList finalItems = new ArrayList ();
283 ArrayList tempItems = new ArrayList ();
285 ITaskItem[] finalArray;
287 foreach (object o in objects) {
288 if (o is ItemReference) {
290 } else if (o is PropertyReference) {
291 PropertyReference pr = (PropertyReference) o;
292 tempItems.Add (pr.ToString ());
293 } else if (o is MetadataReference) {
294 // FIXME: not handled yet
295 } else if (o is string) {
298 throw new Exception ("Invalid type in objects collection.");
301 foreach (object o in tempItems) {
302 if (o is ItemReference) {
303 ItemReference ir = (ItemReference) o;
304 array = ir.ToITaskItemArray ();
306 foreach (ITaskItem item in array)
307 finalItems.Add (item);
308 } else if (o is string) {
309 string s = (string) o;
310 array = ITaskItemArrayFromString (s);
311 foreach (ITaskItem item in array)
312 finalItems.Add (item);
314 throw new Exception ("Invalid type in tempItems collection.");
318 finalArray = new ITaskItem [finalItems.Count];
320 foreach (ITaskItem item in finalItems)
321 finalArray [i++] = item;
325 // FIXME: quite stupid name
326 private ITaskItem[] ITaskItemArrayFromString (string source)
328 ArrayList tempItems = new ArrayList ();
329 ITaskItem[] finalArray;
330 string[] splittedSource = source.Split (';');
331 foreach (string s in splittedSource) {
332 if (s != String.Empty) {
333 tempItems.Add (new TaskItem (s));
336 finalArray = new ITaskItem [tempItems.Count];
338 foreach (ITaskItem item in tempItems)
339 finalArray [i++] = item;
343 public Project Project {
344 get { return project; }
347 public ItemReference ParentItemReference {
348 get { return parentItemReference; }
352 internal enum EvaluationState {
359 internal enum ParenState {
364 internal enum ApostropheState {
369 internal enum ItemParsingState {