Merge pull request #601 from knocte/sock_improvements
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / ConditionParser.cs
index fa4a4a982f7a19a401cc6904cdca093c7979c8e7..ec538abc29f3441d5927656608e29ecdb24ed11c 100644 (file)
@@ -27,8 +27,6 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-#if NET_2_0
-
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -39,11 +37,13 @@ namespace Microsoft.Build.BuildEngine {
        internal class ConditionParser {
        
                ConditionTokenizer tokenizer;
+               string conditionStr;
                
                ConditionParser (string condition)
                {
                        tokenizer = new ConditionTokenizer ();
                        tokenizer.Tokenize (condition);
+                       conditionStr = condition;
                }
                
                public static bool ParseAndEvaluate (string condition, Project context)
@@ -51,12 +51,22 @@ namespace Microsoft.Build.BuildEngine {
                        if (String.IsNullOrEmpty (condition))
                                return true;
 
-                       ConditionExpression ce = ParseCondition (condition);
+                       try {
+                               ConditionExpression ce = ParseCondition (condition);
 
-                       if (!ce.CanEvaluateToBool (context))
-                               throw new InvalidProjectFileException (String.Format ("Can not evaluate \"{0}\" to bool.", condition));
+                               if (!ce.CanEvaluateToBool (context))
+                                       throw new InvalidProjectFileException (String.Format ("Can not evaluate \"{0}\" to bool.", condition));
 
-                       return ce.BoolEvaluate (context);
+                               return ce.BoolEvaluate (context);
+                       } catch (ExpressionParseException epe) {
+                               throw new InvalidProjectFileException (
+                                               String.Format ("Unable to parse condition \"{0}\" : {1}", condition, epe.Message),
+                                               epe);
+                       } catch (ExpressionEvaluationException epe) {
+                               throw new InvalidProjectFileException (
+                                               String.Format ("Unable to evaluate condition \"{0}\" : {1}", condition, epe.Message),
+                                               epe);
+                       }
                }
 
                public static ConditionExpression ParseCondition (string condition)
@@ -65,7 +75,7 @@ namespace Microsoft.Build.BuildEngine {
                        ConditionExpression e = parser.ParseExpression ();
                        
                        if (!parser.tokenizer.IsEOF ())
-                               throw new ExpressionParseException (String.Format ("Unexpected token at end of condition: \"{0}\"", parser.tokenizer.Token.Value));
+                               throw new ExpressionParseException (String.Format ("Unexpected token found, {0}, in condition \"{1}\"", parser.tokenizer.Token, condition));
                        
                        return e;
                }
@@ -79,6 +89,11 @@ namespace Microsoft.Build.BuildEngine {
                {
                        return ParseBooleanAnd ();
                }
+
+               public static string And (string a, string b)
+               {
+                       return a + " and " + b;
+               }
                
                ConditionExpression ParseBooleanAnd ()
                {
@@ -165,14 +180,13 @@ namespace Microsoft.Build.BuildEngine {
                                e = new ConditionFactorExpression (token);
                        } else if (token.Type == TokenType.Number) {
                                e = new ConditionFactorExpression (token);
-                       } else if (token.Type == TokenType.Item) {
-                               throw new NotImplementedException ();
-                       } else if (token.Type == TokenType.Property) {
-                               throw new NotImplementedException ();
+                       } else if (token.Type == TokenType.Item || token.Type == TokenType.Property
+                                       || token.Type == TokenType.Metadata) {
+                               e = ParseReferenceExpression (token.Value);
                        } else if (token.Type == TokenType.Not) {
                                e = ParseNotExpression ();
                        } else
-                               throw new ExpressionParseException (String.Format ("Unexpected token type {0}.", token.Type));
+                               throw new ExpressionParseException (String.Format ("Unexpected token {0}, while parsing condition \"{1}\"", token, conditionStr));
                        
                        return e;
                }
@@ -208,7 +222,61 @@ namespace Microsoft.Build.BuildEngine {
                        
                        return list;
                }
+
+               //@prefix: @ or $
+               ConditionExpression ParseReferenceExpression (string prefix)
+               {
+                       StringBuilder sb = new StringBuilder ();
+
+                       string ref_type = prefix [0] == '$' ? "a property" : "an item list";
+                       int token_pos = tokenizer.Token.Position;
+                       IsAtToken (TokenType.LeftParen, String.Format (
+                                               "Expected {0} at position {1} in condition \"{2}\". Missing opening parantheses after the '{3}'.",
+                                               ref_type, token_pos, conditionStr, prefix));
+                       tokenizer.GetNextToken ();
+
+                       sb.AppendFormat ("{0}({1}", prefix, tokenizer.Token.Value);
+
+                       tokenizer.GetNextToken ();
+                       if (prefix == "@" && tokenizer.Token.Type == TokenType.Transform) {
+                               tokenizer.GetNextToken ();
+                               sb.AppendFormat ("->'{0}'", tokenizer.Token.Value);
+
+                               tokenizer.GetNextToken ();
+                               if (tokenizer.Token.Type == TokenType.Comma) {
+                                       tokenizer.GetNextToken ();
+                                       sb.AppendFormat (", '{0}'", tokenizer.Token.Value);
+                                       tokenizer.GetNextToken ();
+                               }
+                       }
+
+                       IsAtToken (TokenType.RightParen, String.Format (
+                                               "Expected {0} at position {1} in condition \"{2}\". Missing closing parantheses'.",
+                                               ref_type, token_pos, conditionStr, prefix));
+                       tokenizer.GetNextToken ();
+
+                       sb.Append (")");
+
+                       //FIXME: HACKY!
+                       return new ConditionFactorExpression (new Token (sb.ToString (), TokenType.String, token_pos));
+               }
+
+               // used to check current token type
+               void IsAtToken (TokenType type, string error_msg)
+               {
+                       if (tokenizer.Token.Type != type) {
+                               if (!String.IsNullOrEmpty (error_msg))
+                                       throw new ExpressionParseException (error_msg);
+
+                               if (tokenizer.Token.Type == TokenType.EOF)
+                                       throw new ExpressionParseException (String.Format (
+                                                               "Expected a \"{0}\" but the condition ended abruptly, while parsing condition \"{1}\"",
+                                                               Token.TypeAsString (type), conditionStr));
+
+                               throw new ExpressionParseException (String.Format (
+                                                               "Expected \"{0}\" token,  but got {1}, while parsing \"{2}\"",
+                                                               Token.TypeAsString (type), tokenizer.Token, conditionStr));
+                       }
+               }
        }
 }
-
-#endif