2009-02-01 Marek Safar <marek.safar@gmail.com>
authorMarek Safar <marek.safar@gmail.com>
Sun, 1 Feb 2009 18:23:13 +0000 (18:23 -0000)
committerMarek Safar <marek.safar@gmail.com>
Sun, 1 Feb 2009 18:23:13 +0000 (18:23 -0000)
A fix for bug #359731
* cs-tokenizer.cs, cs-parser.jay: Correctly parse nested query
expressions.

svn path=/trunk/mcs/; revision=125268

mcs/mcs/ChangeLog
mcs/mcs/cs-parser.jay
mcs/mcs/cs-tokenizer.cs

index 997e387102aa64fcd339053a96818475ca5a04e2..841cf6d6a48ce041015f6a8ac88f794444981d80 100644 (file)
@@ -1,3 +1,9 @@
+2009-02-01  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bug #359731
+       * cs-tokenizer.cs, cs-parser.jay: Correctly parse nested query
+       expressions.
+
 2009-01-30  Marek Safar  <marek.safar@gmail.com>
 
        A fix for bug #470767
index cc88b2df096a72310343e1694ece3a5802da9933..bcd77aba95d2ec8eb2fc8601fd09b98b902c064c 100644 (file)
@@ -232,6 +232,7 @@ namespace Mono.CSharp
 %token PARTIAL
 %token ARROW
 %token FROM
+%token FROM_FIRST
 %token JOIN
 %token ON
 %token EQUALS
@@ -5194,18 +5195,23 @@ using_statement
 // LINQ
 
 query_expression
-       : first_from_clause
+       : first_from_clause query_body
          {
-               ++lexer.query_parsing;
+               lexer.query_parsing = false;
+                       
+               Linq.AQueryClause from = $1 as Linq.AQueryClause;
+                       
+               from.Tail.Next = (Linq.AQueryClause)$2;
+               $$ = from;
+               
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
          }
-         query_body
+       | nested_from_clause query_body
          {
-               if (--lexer.query_parsing == 1)
-                       lexer.query_parsing = 0;
-                       
                Linq.AQueryClause from = $1 as Linq.AQueryClause;
                        
-               from.Tail.Next = (Linq.AQueryClause)$3;
+               from.Tail.Next = (Linq.AQueryClause)$2;
                $$ = from;
                
                current_block.SetEndLocation (lexer.Location);
@@ -5214,6 +5220,19 @@ query_expression
        ;
        
 first_from_clause
+       : FROM_FIRST IDENTIFIER IN expression
+         {
+               $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, GetLocation ($1));
+         }
+       | FROM_FIRST type IDENTIFIER IN expression
+         {
+               $$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $3, GetLocation ($1));
+         }
+       ;
+
+nested_from_clause
        : FROM IDENTIFIER IN expression
          {
                $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
@@ -6402,6 +6421,7 @@ static string GetTokenName (int token)
        case Token.ARROW:
                return "=>";
        case Token.FROM:
+       case Token.FROM_FIRST:
                return "from";
        case Token.JOIN:
                return "join";
index 5503239286789f3b212423d1621e11b3cae83d83..addf9aa98c78fe893ad595b5dc5d1aed0a44479e 100644 (file)
@@ -51,7 +51,7 @@ namespace Mono.CSharp
                // scope only
                //
                public int parsing_block;
-               internal int query_parsing;
+               internal bool query_parsing;
                
                // 
                // When parsing type only, useful for ambiguous nullable types
@@ -444,7 +444,7 @@ namespace Mono.CSharp
                                }
                                break;
                        case Token.WHERE:
-                               if (!handle_where && query_parsing == 0)
+                               if (!handle_where && !query_parsing)
                                        res = -1;
                                break;
                        case Token.FROM:
@@ -452,7 +452,7 @@ namespace Mono.CSharp
                                // A query expression is any expression that starts with `from identifier'
                                // followed by any token except ; , =
                                // 
-                               if (query_parsing == 0) {
+                               if (!query_parsing) {
                                        if (lambda_arguments_parsing) {
                                                res = -1;
                                                break;
@@ -479,7 +479,8 @@ namespace Mono.CSharp
                                                if (next_token == Token.SEMICOLON || next_token == Token.COMMA || next_token == Token.EQUALS)
                                                        goto default;
                                                
-                                               ++query_parsing;
+                                               res = Token.FROM_FIRST;
+                                               query_parsing = true;
                                                if (RootContext.Version <= LanguageVersion.ISO_2)
                                                        Report.FeatureIsNotAvailable (Location, "query expressions");
                                                break;
@@ -507,7 +508,7 @@ namespace Mono.CSharp
                        case Token.ASCENDING:
                        case Token.DESCENDING:
                        case Token.INTO:
-                               if (query_parsing == 0)
+                               if (!query_parsing)
                                        res = -1;
                                break;