[xbuild] Expression.ParseAs<T> - new method
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / Expression.cs
index c09d1fdbc6d2252b649c4d921062afeaba7ddff7..0d7ad2fa5984896fe57d3b622bc8b6ceefddab82 100644 (file)
@@ -33,6 +33,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Text;
 using System.Text.RegularExpressions;
+using Mono.XBuild.Utilities;
 
 namespace Microsoft.Build.BuildEngine {
 
@@ -65,19 +66,33 @@ namespace Microsoft.Build.BuildEngine {
                        this.expressionCollection = new ExpressionCollection ();
                }
 
-               public void Parse (string expression, bool allowItems)
+               public static T ParseAs<T> (string expression, ParseOptions options, Project project)
                {
-                       Parse (expression, allowItems, true);
+                       Expression expr = new Expression ();
+                       expr.Parse (expression, options);
+                       return (T)expr.ConvertTo (project, typeof (T));
                }
 
-               // @split: Split on ';'
+               public static T ParseAs<T> (string expression, ParseOptions options, Project project, ExpressionOptions exprOptions)
+               {
+                       Expression expr = new Expression ();
+                       expr.Parse (expression, options);
+                       return (T)expr.ConvertTo (project, typeof (T), exprOptions);
+               }
+
+               // Split: Split on ';'
                //         Eg. Property values don't need to be split
                //
-               // @allowItems: item refs should not be treated as item refs!
+               // AllowItems: if false, item refs should not be treated as item refs!
                //              it converts them to strings in the final expressionCollection
-               public void Parse (string expression, bool allowItems, bool split)
+               //
+               // AllowMetadata: same as AllowItems, for metadata
+               public void Parse (string expression, ParseOptions options)
                {
-                       expression = expression.Replace ('/', Path.DirectorySeparatorChar);
+                       bool split = (options & ParseOptions.Split) == ParseOptions.Split;
+                       bool allowItems = (options & ParseOptions.AllowItems) == ParseOptions.AllowItems;
+                       bool allowMd = (options & ParseOptions.AllowMetadata) == ParseOptions.AllowMetadata;
+
                        expression = expression.Replace ('\\', Path.DirectorySeparatorChar);
                
                        string [] parts;
@@ -117,7 +132,7 @@ namespace Microsoft.Build.BuildEngine {
                                }
                        }
 
-                       CopyToExpressionCollection (p3, allowItems);
+                       CopyToExpressionCollection (p3, allowItems, allowMd);
                }
 
                void Prepare (List <ArrayList> l, int length)
@@ -126,14 +141,17 @@ namespace Microsoft.Build.BuildEngine {
                                l.Add (null);
                }
                
-               void CopyToExpressionCollection (List <ArrayList> lists, bool allowItems)
+               void CopyToExpressionCollection (List <ArrayList> lists, bool allowItems, bool allowMd)
                {
                        for (int i = 0; i < lists.Count; i++) {
                                foreach (object o in lists [i]) {
                                        if (o is string)
-                                               expressionCollection.Add (Utilities.Unescape ((string) o));
+                                               expressionCollection.Add (MSBuildUtils.Unescape ((string) o));
                                        else if (!allowItems && o is ItemReference)
                                                expressionCollection.Add (((ItemReference) o).OriginalString);
+                                       else if (!allowMd && o is MetadataReference) {
+                                               expressionCollection.Add (((MetadataReference) o).OriginalString);
+                                       }
                                        else if (o is IReference)
                                                expressionCollection.Add ((IReference) o);
                                }
@@ -246,7 +264,8 @@ namespace Microsoft.Build.BuildEngine {
                                
                                meta = m.Groups [MetadataRegex.GroupNumberFromName ("meta")].Value;
                                
-                               mr = new MetadataReference (name, meta, m.Groups [0].Index, m.Groups [0].Length);
+                               mr = new MetadataReference (text.Substring (m.Groups [0].Index, m.Groups [0].Length),
+                                                               name, meta, m.Groups [0].Index, m.Groups [0].Length);
                                phase1.Add (mr);
                                m = m.NextMatch ();
                        }
@@ -294,7 +313,7 @@ namespace Microsoft.Build.BuildEngine {
                                if (item_regex == null)
                                        item_regex = new Regex (
                                                @"@\(\s*"
-                                               + @"(?<itemname>[_A-Za-z][_0-9a-zA-Z]*)"
+                                               + @"(?<itemname>[_A-Za-z][_\-0-9a-zA-Z]*)"
                                                + @"(?<has_transform>\s*->\s*'(?<transform>[^']*)')?"
                                                + @"(?<has_separator>\s*,\s*'(?<separator>[^']*)')?"
                                                + @"\s*\)");
@@ -307,7 +326,7 @@ namespace Microsoft.Build.BuildEngine {
                                if (property_regex == null)
                                        property_regex = new Regex (
                                                @"\$\(\s*"
-                                               + @"(?<name>[_a-zA-Z][_0-9a-zA-Z]*)"
+                                               + @"(?<name>[_a-zA-Z][_\-0-9a-zA-Z]*)"
                                                + @"\s*\)");
                                return property_regex;
                        }
@@ -318,14 +337,29 @@ namespace Microsoft.Build.BuildEngine {
                                if (metadata_regex == null)
                                        metadata_regex = new Regex (
                                                @"%\(\s*"
-                                               + @"((?<name>[_a-zA-Z][_0-9a-zA-Z]*)\.)?"
-                                               + @"(?<meta>[_a-zA-Z][_0-9a-zA-Z]*)"
+                                               + @"((?<name>[_a-zA-Z][_\-0-9a-zA-Z]*)\.)?"
+                                               + @"(?<meta>[_a-zA-Z][_\-0-9a-zA-Z]*)"
                                                + @"\s*\)");
                                return metadata_regex;
                        }
                }
        }
 
+       [Flags]
+       enum ParseOptions {
+               // absence of one of these flags, means
+               // false for that option
+               AllowItems = 0x1,
+               Split = 0x2,
+               AllowMetadata = 0x4,
+
+               None = 0x8, // == no items, no metadata, and no split
+
+               // commonly used options
+               AllowItemsMetadataAndSplit = AllowItems | Split | AllowMetadata,
+               AllowItemsNoMetadataAndSplit = AllowItems | Split
+       }
+
        enum ExpressionOptions {
                ExpandItemRefs,
                DoNotExpandItemRefs