%token PARTIAL
%token ARROW
%token FROM
+%token FROM_FIRST
%token JOIN
%token ON
%token EQUALS
// 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);
;
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));
case Token.ARROW:
return "=>";
case Token.FROM:
+ case Token.FROM_FIRST:
return "from";
case Token.JOIN:
return "join";
// scope only
//
public int parsing_block;
- internal int query_parsing;
+ internal bool query_parsing;
//
// When parsing type only, useful for ambiguous nullable types
}
break;
case Token.WHERE:
- if (!handle_where && query_parsing == 0)
+ if (!handle_where && !query_parsing)
res = -1;
break;
case Token.FROM:
// 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;
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;
case Token.ASCENDING:
case Token.DESCENDING:
case Token.INTO:
- if (query_parsing == 0)
+ if (!query_parsing)
res = -1;
break;