Parser: Improve error messages (mention what was expected)

--
MOS_MIGRATED_REVID=89296523
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 187f11b..3ce949d 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
@@ -240,11 +240,11 @@
     }
   }
 
-  private void syntaxError(Token token) {
+  private void syntaxError(Token token, String message) {
     if (!recoveryMode) {
       String msg = token.kind == TokenKind.INDENT
           ? "indentation error"
-          : "syntax error at '" + token + "'";
+          : "syntax error at '" + token + "': " + message;
       reportError(lexer.createLocation(token.left, token.right), msg);
       recoveryMode = true;
     }
@@ -255,7 +255,7 @@
   private boolean expect(TokenKind kind) {
     boolean expected = token.kind == kind;
     if (!expected) {
-      syntaxError(token);
+      syntaxError(token, "expected " + kind.getPrettyName());
     }
     nextToken();
     return expected;
@@ -454,7 +454,7 @@
         return setLocation(new DotExpression(receiver, ident), start, token.right);
       }
     } else {
-      syntaxError(token);
+      syntaxError(token, "expected identifier after dot");
       int end = syncTo(EXPR_TERMINATOR_SET);
       return makeErrorExpression(start, end);
     }
@@ -632,7 +632,7 @@
           nextToken();
           return expression;
         }
-        syntaxError(token);
+        expect(TokenKind.RPAREN);
         int end = syncTo(EXPR_TERMINATOR_SET);
         return makeErrorExpression(start, end);
       }
@@ -646,7 +646,7 @@
                                      start, token.right);
       }
       default: {
-        syntaxError(token);
+        syntaxError(token, "expected expression");
         int end = syncTo(EXPR_TERMINATOR_SET);
         return makeErrorExpression(start, end);
       }
@@ -772,7 +772,7 @@
           }
         } while (token.kind == TokenKind.FOR);
 
-        syntaxError(token);
+        syntaxError(token, "expected 'for' or ']'");
         int end = syncPast(LIST_TERMINATOR_SET);
         return makeErrorExpression(start, end);
       }
@@ -787,12 +787,12 @@
           nextToken();
           return literal;
         }
-        syntaxError(token);
+        expect(TokenKind.RBRACKET);
         int end = syncPast(LIST_TERMINATOR_SET);
         return makeErrorExpression(start, end);
       }
       default: {
-        syntaxError(token);
+        syntaxError(token, "expected ',', 'for' or ']'");
         int end = syncPast(LIST_TERMINATOR_SET);
         return makeErrorExpression(start, end);
       }
@@ -834,14 +834,14 @@
       nextToken();
       return literal;
     }
-    syntaxError(token);
+    expect(TokenKind.RBRACE);
     int end = syncPast(DICT_TERMINATOR_SET);
     return makeErrorExpression(start, end);
   }
 
   private Ident parseIdent() {
     if (token.kind != TokenKind.IDENTIFIER) {
-      syntaxError(token);
+      expect(TokenKind.IDENTIFIER);
       return makeErrorExpression(token.left, token.right);
     }
     Ident ident = new Ident(((String) token.value));
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java b/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
index 5a0b0a3..5a1eaad 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
@@ -119,7 +119,7 @@
       parseBuildFile("foo() bar() something = baz() bar()");
 
     Event event = events.collector().iterator().next();
-    assertEquals("syntax error at \'bar\'", event.getMessage());
+    assertEquals("syntax error at \'bar\': expected newline", event.getMessage());
     assertEquals("/a/build/file/BUILD",
                  event.getLocation().getPath().toString());
     assertEquals(1, event.getLocation().getStartLineAndColumn().getLine());
@@ -173,8 +173,7 @@
   public void testWithSyntaxErrorsDoesNotPrintDollarError() throws Exception {
     events.setFailFast(false);
     BuildFileAST buildFile = parseBuildFile(
-        "abi = cxx_abi + '-glibc-' + glibc_version + '-' + "
-        + "generic_cpu + '-' + sysname",
+        "abi = cxx_abi + '-glibc-' + glibc_version + '-' + generic_cpu + '-' + sysname",
         "libs = [abi + opt_level + '/lib/libcc.a']",
         "shlibs = [abi + opt_level + '/lib/libcc.so']",
         "+* shlibs", // syntax error at '+'
@@ -183,7 +182,7 @@
         "           includes = [ abi + opt_level + '/include' ])");
     assertTrue(buildFile.containsErrors());
     Event event = events.collector().iterator().next();
-    assertEquals("syntax error at '+'", event.getMessage());
+    assertEquals("syntax error at '+': expected expression", event.getMessage());
     Environment env = new Environment();
     assertFalse(buildFile.exec(env, events.reporter()));
     assertNull(findEvent(events.collector(), "$error$"));
@@ -313,7 +312,7 @@
     // Check the location is properly reported
     Event event = events.collector().iterator().next();
     assertEquals("/foo/bar/file:1:9", event.getLocation().print());
-    assertEquals("syntax error at '%'", event.getMessage());
+    assertEquals("syntax error at '%': expected expression", event.getMessage());
   }
 
   @Test