Fix bogus expression tokenizer that failed at parenthesized expressions with And/Or.
authorAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Thu, 21 Nov 2013 14:17:09 +0000 (23:17 +0900)
committerAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Tue, 3 Dec 2013 07:52:33 +0000 (16:52 +0900)
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionParser.jay
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionParserManual.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionTokenizer.cs
mcs/class/Microsoft.Build/Test/Microsoft.Build.Internal/ExpressionParserTest.cs

index 1b3cd3db18ddfcd31e99522b51aff37e5a5612c4..d93ecb340e71b25087db9d2b5178157c0e59e3d5 100644 (file)
@@ -73,7 +73,7 @@ namespace Microsoft.Build.Internal
 {
        class ExpressionParser
        {
-               const int yacc_verbose_flag = 0;
+               static readonly int yacc_verbose_flag = Environment.GetEnvironmentVariable ("MONO_MSBUILD_PARSER_DEBUG") == "1" ? 1 : 0;
 
                object debug_obj = yacc_verbose_flag == 0 ? null : new yydebug.yyDebugSimple ();
                
@@ -169,6 +169,7 @@ PrimaryExpression
        | MetadataAccessExpression
        | RawStringLiteralOrFunction
        | ParenthesizedExpression
+       ;
        
 BooleanLiteral
        : TRUE_LITERAL
index 6e5526cef301d137335613e5658c3025ed796189..83d4e9b15655ef9d13bfa1de904a655736672342 100644 (file)
@@ -105,12 +105,13 @@ namespace Microsoft.Build.Internal
                                        goto default;
                                start++;
                                last = FindMatchingCloseParen (start, end);
-                               if (last < 0)
-                               if (validation_type == ExpressionValidationType.StrictBoolean)
-                                       throw new InvalidProjectFileException (string.Format ("expression did not have matching ')' since index {0} in \"{1}\"", start, source));
-                               else {
-                                       start--;
-                                       goto default; // treat as raw literal to the section end
+                               if (last < 0) {
+                                       if (validation_type == ExpressionValidationType.StrictBoolean)
+                                               throw new InvalidProjectFileException (string.Format ("expression did not have matching ')' since index {0} in \"{1}\"", start, source));
+                                       else {
+                                               start--;
+                                               goto default; // treat as raw literal to the section end
+                                       }
                                }
                                var contents = Parse (start, last).ToArray ();
                                if (contents.Length > 1)
index a1bb0101dc24f4a7fe0cd39609e1490191a9bf26..6820cc467d1c2b4b9cb65bdd5e7fb1a63c430fec 100644 (file)
@@ -98,6 +98,7 @@ namespace Microsoft.Build.Internal
                                TokenForItemPropertyValue ("]", Token.BRACE_CLOSE);
                                break;
                        case '(':
+                               modes.Push (TokenizerMode.Default);
                                TokenForItemPropertyValue ("(", Token.PAREN_OPEN);
                                break;
                        case ')':
index fbf435c0f15a14b181c7fcef943f640dda924317..0f55735aec4cb76af498e7160d50d00eeb05c5d9 100644 (file)
@@ -84,6 +84,10 @@ namespace MonoTests.Microsoft.Build.Internal
                                "$([System.String]::Format('True'))",
                                "$([System.String]::Format('True', null))",
                                "False And True == True And True",
+                               "True or True or False",
+                               "(True or True or False)",
+                               "True and False",
+                               "(True) and (False)",
                        };
                        string [] depends = {
                                // valid only if evaluated to boolean