Parser: Allow more complex expressions as for loop variables.

Also, use LValue in ForStatement.

--
MOS_MIGRATED_REVID=89122760
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index d736a27..187f11b 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -705,37 +705,28 @@
                                  start, token.right);
   }
 
-  // loop_variables ::= '(' variables ')'
-  //                  | variables
-  // variables ::= ident (',' ident)*
-  private Ident parseForLoopVariables() {
+  // Equivalent to 'exprlist' rule in Python grammar.
+  // loop_variables ::= primary_with_suffix ( ',' primary_with_suffix )* ','?
+  private Expression parseForLoopVariables() {
+    // We cannot reuse parseExpression because it would parse the 'in' operator.
+    // e.g.  "for i in e: pass"  -> we want to parse only "i" here.
     int start = token.left;
-    boolean hasParen = false;
-    if (token.kind == TokenKind.LPAREN) {
-      hasParen = true;
-      nextToken();
+    Expression e1 = parsePrimaryWithSuffix();
+    if (token.kind != TokenKind.COMMA) {
+      return e1;
     }
 
-    // TODO(bazel-team): allow multiple variables in the core Blaze language too.
-    Ident firstIdent = parseIdent();
-    boolean multipleVariables = false;
-
+    // It's a tuple
+    List<Expression> tuple = new ArrayList<>();
+    tuple.add(e1);
     while (token.kind == TokenKind.COMMA) {
-      multipleVariables = true;
-      nextToken();
-      parseIdent();
+      expect(TokenKind.COMMA);
+      if (EXPR_LIST_TERMINATOR_SET.contains(token.kind)) {
+        break;
+      }
+      tuple.add(parsePrimaryWithSuffix());
     }
-
-    if (hasParen) {
-      expect(TokenKind.RPAREN);
-    }
-
-    int end = token.right;
-    if (multipleVariables && !parsePython) {
-      reportError(lexer.createLocation(start, end),
-          "For loops with multiple variables are not yet supported");
-    }
-    return multipleVariables ? makeErrorExpression(start, end) : firstIdent;
+    return setLocation(ListLiteral.makeTuple(tuple), start, token.right);
   }
 
   // list_maker ::= '[' ']'
@@ -766,11 +757,11 @@
           new ListComprehension(expression);
         do {
           nextToken();
-          Ident ident = parseForLoopVariables();
+          Expression loopVar = parseForLoopVariables();
           if (token.kind == TokenKind.IN) {
             nextToken();
             Expression listExpression = parseExpression();
-            listComprehension.add(ident, listExpression);
+            listComprehension.add(loopVar, listExpression);
           } else {
             break;
           }
@@ -824,7 +815,7 @@
     if (token.kind == TokenKind.FOR) {
       // Dict comprehension
       nextToken();
-      Ident loopVar = parseForLoopVariables();
+      Expression loopVar = parseForLoopVariables();
       expect(TokenKind.IN);
       Expression listExpression = parseExpression();
       expect(TokenKind.RBRACE);
@@ -1144,12 +1135,12 @@
   private void parseForStatement(List<Statement> list) {
     int start = token.left;
     expect(TokenKind.FOR);
-    Ident ident = parseIdent();
+    Expression loopVar = parseForLoopVariables();
     expect(TokenKind.IN);
     Expression collection = parseExpression();
     expect(TokenKind.COLON);
     List<Statement> block = parseSuite();
-    Statement stmt = new ForStatement(ident, collection, block);
+    Statement stmt = new ForStatement(loopVar, collection, block);
     list.add(setLocation(stmt, start, token.right));
   }