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;
33 using System.Collections.Generic;
35 using System.Text.RegularExpressions;
37 namespace Microsoft.Build.BuildEngine {
38 internal class Expression {
40 ExpressionCollection expressionCollection;
42 static Regex item_regex;
43 static Regex property_regex;
44 static Regex metadata_regex;
48 this.expressionCollection = new ExpressionCollection ();
51 public void Parse (string expression, bool allowItems)
53 expression = expression.Replace ('/', Path.DirectorySeparatorChar);
54 expression = expression.Replace ('\\', Path.DirectorySeparatorChar);
56 string [] parts = expression.Split (';');
58 List <ArrayList> p1 = new List <ArrayList> (parts.Length);
59 List <ArrayList> p2 = new List <ArrayList> (parts.Length);
60 List <ArrayList> p3 = new List <ArrayList> (parts.Length);
62 Prepare (p1, parts.Length);
63 Prepare (p2, parts.Length);
64 Prepare (p3, parts.Length);
66 for (int i = 0; i < parts.Length; i++)
67 p1 [i] = SplitItems (parts [i], allowItems);
69 for (int i = 0; i < parts.Length; i++) {
70 p2 [i] = new ArrayList ();
71 foreach (object o in p1 [i]) {
73 p2 [i].AddRange (SplitProperties ((string) o));
79 for (int i = 0; i < parts.Length; i++) {
80 p3 [i] = new ArrayList ();
81 foreach (object o in p2 [i]) {
83 p3 [i].AddRange (SplitMetadata ((string) o));
89 CopyToExpressionCollection (p3);
92 void Prepare (List <ArrayList> l, int length)
94 for (int i = 0; i < length; i++)
98 void CopyToExpressionCollection (List <ArrayList> lists)
100 for (int i = 0; i < lists.Count; i++) {
101 foreach (object o in lists [i]) {
103 expressionCollection.Add (Utilities.Unescape ((string) o));
104 else if (o is ItemReference)
105 expressionCollection.Add ((ItemReference) o);
106 else if (o is PropertyReference)
107 expressionCollection.Add ((PropertyReference) o);
108 else if (o is MetadataReference)
109 expressionCollection.Add ((MetadataReference) o);
111 if (i < lists.Count - 1)
112 expressionCollection.Add (";");
116 ArrayList SplitItems (string text, bool allowItems)
119 // FIXME: it's probably larger than 1
120 ArrayList l = new ArrayList ();
125 ArrayList phase1 = new ArrayList ();
127 m = ItemRegex.Match (text);
130 string name = null, transform = null, separator = null;
133 name = m.Groups [ItemRegex.GroupNumberFromName ("itemname")].Value;
135 if (m.Groups [ItemRegex.GroupNumberFromName ("has_transform")].Success)
136 transform = m.Groups [ItemRegex.GroupNumberFromName ("transform")].Value;
138 if (m.Groups [ItemRegex.GroupNumberFromName ("has_separator")].Success)
139 separator = m.Groups [ItemRegex.GroupNumberFromName ("separator")].Value;
141 ir = new ItemReference (name, transform, separator, m.Groups [0].Index, m.Groups [0].Length);
146 ArrayList phase2 = new ArrayList ();
148 int end = text.Length - 1;
150 foreach (ItemReference ir in phase1) {
157 phase2.Add (text.Substring (a + 1, b - a - 1));
165 phase2.Add (text.Substring (last_end + 1, end - last_end));
170 ArrayList SplitProperties (string text)
172 ArrayList phase1 = new ArrayList ();
174 m = PropertyRegex.Match (text);
178 PropertyReference pr;
180 name = m.Groups [PropertyRegex.GroupNumberFromName ("name")].Value;
182 pr = new PropertyReference (name, m.Groups [0].Index, m.Groups [0].Length);
187 ArrayList phase2 = new ArrayList ();
189 int end = text.Length - 1;
191 foreach (PropertyReference pr in phase1) {
198 phase2.Add (text.Substring (a + 1, b - a - 1));
206 phase2.Add (text.Substring (last_end + 1, end - last_end));
211 ArrayList SplitMetadata (string text)
213 ArrayList phase1 = new ArrayList ();
215 m = MetadataRegex.Match (text);
218 string name = null, meta = null;
219 MetadataReference mr;
221 if (m.Groups [MetadataRegex.GroupNumberFromName ("name")].Success)
222 name = m.Groups [MetadataRegex.GroupNumberFromName ("name")].Value;
224 meta = m.Groups [MetadataRegex.GroupNumberFromName ("meta")].Value;
226 mr = new MetadataReference (name, meta, m.Groups [0].Index, m.Groups [0].Length);
231 ArrayList phase2 = new ArrayList ();
233 int end = text.Length - 1;
235 foreach (MetadataReference mr in phase1) {
242 phase2.Add (text.Substring (a + 1, b - a - 1));
250 phase2.Add (text.Substring (last_end + 1, end - last_end));
255 public object ConvertTo (Project project, Type type)
257 return expressionCollection.ConvertTo (project, type);
260 public ExpressionCollection Collection {
261 get { return expressionCollection; }
264 static Regex ItemRegex {
266 if (item_regex == null)
267 item_regex = new Regex (
269 + @"(?<itemname>[_A-Za-z][_0-9a-zA-Z]*)"
270 + @"(?<has_transform>\s*->\s*'(?<transform>[^']*)')?"
271 + @"(?<has_separator>\s*,\s*'(?<separator>[^']*)')?"
277 static Regex PropertyRegex {
279 if (property_regex == null)
280 property_regex = new Regex (
282 + @"(?<name>[_a-zA-Z][_0-9a-zA-Z]*)"
284 return property_regex;
288 static Regex MetadataRegex {
290 if (metadata_regex == null)
291 metadata_regex = new Regex (
293 + @"((?<name>[_a-zA-Z][_0-9a-zA-Z]*)\.)?"
294 + @"(?<meta>[_a-zA-Z][_0-9a-zA-Z]*)"
296 return metadata_regex;