langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 15367 31b57f2b8d0b
parent 14803 88347e495d34
child 15375 d2529dc91d77
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jan 16 20:41:14 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Jan 17 18:15:20 2013 +0000
@@ -245,40 +245,42 @@
         token = S.token();
     }
 
-    protected boolean peekToken(TokenKind tk) {
+    protected boolean peekToken(Filter<TokenKind> tk) {
         return peekToken(0, tk);
     }
 
-    protected boolean peekToken(int lookahead, TokenKind tk) {
-        return S.token(lookahead + 1).kind == tk;
+    protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
+        return tk.accepts(S.token(lookahead + 1).kind);
     }
 
-    protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
+    protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
         return peekToken(0, tk1, tk2);
     }
 
-    protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) {
-        return S.token(lookahead + 1).kind == tk1 &&
-                S.token(lookahead + 2).kind == tk2;
+    protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
+        return tk1.accepts(S.token(lookahead + 1).kind) &&
+                tk2.accepts(S.token(lookahead + 2).kind);
     }
 
-    protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
+    protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
         return peekToken(0, tk1, tk2, tk3);
     }
 
-    protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) {
-        return S.token(lookahead + 1).kind == tk1 &&
-                S.token(lookahead + 2).kind == tk2 &&
-                S.token(lookahead + 3).kind == tk3;
+    protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
+        return tk1.accepts(S.token(lookahead + 1).kind) &&
+                tk2.accepts(S.token(lookahead + 2).kind) &&
+                tk3.accepts(S.token(lookahead + 3).kind);
     }
 
-    protected boolean peekToken(TokenKind... kinds) {
+    @SuppressWarnings("unchecked")
+    protected boolean peekToken(Filter<TokenKind>... kinds) {
         return peekToken(0, kinds);
     }
 
-    protected boolean peekToken(int lookahead, TokenKind... kinds) {
+    @SuppressWarnings("unchecked")
+    protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
         for (; lookahead < kinds.length ; lookahead++) {
-            if (S.token(lookahead + 1).kind != kinds[lookahead]) {
+            if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
                 return false;
             }
         }
@@ -333,6 +335,7 @@
                     if (stopAtMemberDecl)
                         return;
                     break;
+                case UNDERSCORE:
                 case IDENTIFIER:
                    if (stopAtIdentifier)
                         return;
@@ -552,11 +555,16 @@
                 nextToken();
                 return name;
             }
+        } else if (token.kind == UNDERSCORE) {
+            warning(token.pos, "underscore.as.identifier");
+            Name name = token.name();
+            nextToken();
+            return name;
         } else {
             accept(IDENTIFIER);
             return names.error;
         }
-}
+    }
 
     /**
      * Qualident = Ident { DOT Ident }
@@ -1056,7 +1064,7 @@
                 typeArgs = null;
             } else return illegal();
             break;
-        case IDENTIFIER: case ASSERT: case ENUM:
+        case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
             if (typeArgs != null) return illegal();
             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
                 t = lambdaExpressionOrStatement(false, false, pos);
@@ -1274,7 +1282,7 @@
         int pos = 0, depth = 0;
         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
             switch (t.kind) {
-                case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
+                case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
                 case DOUBLE: case BOOLEAN: case CHAR:
@@ -1323,8 +1331,8 @@
                     if (peekToken(lookahead, RPAREN)) {
                         //Type, ')' -> cast
                         return ParensResult.CAST;
-                    } else if (peekToken(lookahead, IDENTIFIER)) {
-                        //Type, 'Identifier -> explicit lambda
+                    } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
+                        //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
                         return ParensResult.EXPLICIT_LAMBDA;
                     }
                     break;
@@ -1350,16 +1358,19 @@
                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
                         case TRUE: case FALSE: case NULL:
-                            case NEW: case IDENTIFIER: case ASSERT: case ENUM:
+                        case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
                         case BYTE: case SHORT: case CHAR: case INT:
                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
                             return ParensResult.CAST;
                         default:
                             return ParensResult.PARENS;
                     }
+                case UNDERSCORE:
+                case ASSERT:
+                case ENUM:
                 case IDENTIFIER:
-                    if (peekToken(lookahead, IDENTIFIER)) {
-                        // Identifier, Identifier -> explicit lambda
+                    if (peekToken(lookahead, LAX_IDENTIFIER)) {
+                        // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
                         return ParensResult.EXPLICIT_LAMBDA;
                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
                         // Identifier, ')' '->' -> implicit lambda
@@ -1372,8 +1383,8 @@
                     //those can only appear in explicit lambdas
                     return ParensResult.EXPLICIT_LAMBDA;
                 case LBRACKET:
-                    if (peekToken(lookahead, RBRACKET, IDENTIFIER)) {
-                        // '[', ']', Identifier -> explicit lambda
+                    if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
+                        // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
                         return ParensResult.EXPLICIT_LAMBDA;
                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
                             peekToken(lookahead, RBRACKET, AMP)) {
@@ -1402,11 +1413,11 @@
                             // '>', ')' -> cast
                             // '>', '&' -> cast
                             return ParensResult.CAST;
-                        } else if (peekToken(lookahead, IDENTIFIER, COMMA) ||
-                                peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) ||
+                        } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
+                                peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
                                 peekToken(lookahead, ELLIPSIS)) {
-                            // '>', Identifier, ',' -> explicit lambda
-                            // '>', Identifier, ')', '->' -> explicit lambda
+                            // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
+                            // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
                             // '>', '...' -> explicit lambda
                             return ParensResult.EXPLICIT_LAMBDA;
                         }
@@ -1426,6 +1437,13 @@
         }
     }
 
+    /** Accepts all identifier-like tokens */
+    Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
+        public boolean accepts(TokenKind t) {
+            return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
+        }
+    };
+
     enum ParensResult {
         CAST,
         EXPLICIT_LAMBDA,
@@ -1433,21 +1451,9 @@
         PARENS;
     }
 
-    JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
-        ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
-        params.append(firstParam);
-        JCVariableDecl lastParam = firstParam;
-        while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
-            nextToken();
-            params.append(lastParam = formalParameter());
-        }
-        accept(RPAREN);
-        return lambdaExpressionOrStatementRest(params.toList(), pos);
-    }
-
     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
         List<JCVariableDecl> params = explicitParams ?
-                formalParameters() :
+                formalParameters(true) :
                 implicitParameters(hasParens);
 
         return lambdaExpressionOrStatementRest(params, pos);
@@ -1628,7 +1634,7 @@
             nextToken();
             JCExpression bound = parseType();
             return F.at(pos).Wildcard(t, bound);
-        } else if (token.kind == IDENTIFIER) {
+        } else if (LAX_IDENTIFIER.accepts(token.kind)) {
             //error recovery
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
@@ -1678,7 +1684,7 @@
             if (token.pos == endPosTable.errorEndPos) {
                 // error recovery
                 Name name = null;
-                if (token.kind == IDENTIFIER) {
+                if (LAX_IDENTIFIER.accepts(token.kind)) {
                     name = token.name();
                     nextToken();
                 } else {
@@ -2026,10 +2032,7 @@
                 nextToken();
                 JCStatement stat = parseStatement();
                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
-            } else if ((lastmode & TYPE) != 0 &&
-                       (token.kind == IDENTIFIER ||
-                        token.kind == ASSERT ||
-                        token.kind == ENUM)) {
+            } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
                 pos = token.pos;
                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
                 F.at(pos);
@@ -2183,14 +2186,14 @@
         }
         case BREAK: {
             nextToken();
-            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
+            Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
             JCBreak t = to(F.at(pos).Break(label));
             accept(SEMI);
             return t;
         }
         case CONTINUE: {
             nextToken();
-            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
+            Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
             JCContinue t =  to(F.at(pos).Continue(label));
             accept(SEMI);
             return t;
@@ -2351,9 +2354,7 @@
             return variableDeclarators(optFinal(0), parseType(), stats).toList();
         } else {
             JCExpression t = term(EXPR | TYPE);
-            if ((lastmode & TYPE) != 0 &&
-                (token.kind == IDENTIFIER || token.kind == ASSERT ||
-                 token.kind == ENUM)) {
+            if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
                 return variableDeclarators(modifiersOpt(), t, stats).toList();
             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
                 error(pos, "bad.initializer", "for-loop");
@@ -2609,8 +2610,18 @@
     /** VariableDeclaratorId = Ident BracketsOpt
      */
     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
+        return variableDeclaratorId(mods, type, false);
+    }
+    //where
+    JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
         int pos = token.pos;
-        Name name = ident();
+        Name name;
+        if (lambdaParameter && token.kind == UNDERSCORE) {
+            syntaxError(pos, "expected", IDENTIFIER);
+            name = token.name();
+        } else {
+            name = ident();
+        }
         if ((mods.flags & Flags.VARARGS) != 0 &&
                 token.kind == LBRACKET) {
             log.error(token.pos, "varargs.and.old.array.syntax");
@@ -2770,7 +2781,7 @@
             } else {
                 int pos = token.pos;
                 List<JCTree> errs;
-                if (token.kind == IDENTIFIER) {
+                if (LAX_IDENTIFIER.accepts(token.kind)) {
                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
                     setErrorEndPos(token.pos);
                 } else {
@@ -2787,7 +2798,7 @@
             }
             int pos = token.pos;
             List<JCTree> errs;
-            if (token.kind == IDENTIFIER) {
+            if (LAX_IDENTIFIER.accepts(token.kind)) {
                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
                 setErrorEndPos(token.pos);
             } else {
@@ -3182,14 +3193,17 @@
      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
      */
     List<JCVariableDecl> formalParameters() {
+        return formalParameters(false);
+    }
+    List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
         JCVariableDecl lastParam = null;
         accept(LPAREN);
         if (token.kind != RPAREN) {
-            params.append(lastParam = formalParameter());
+            params.append(lastParam = formalParameter(lambdaParameters));
             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
                 nextToken();
-                params.append(lastParam = formalParameter());
+                params.append(lastParam = formalParameter(lambdaParameters));
             }
         }
         accept(RPAREN);
@@ -3225,6 +3239,9 @@
      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
      */
     protected JCVariableDecl formalParameter() {
+        return formalParameter(false);
+    }
+    protected JCVariableDecl formalParameter(boolean lambdaParameter) {
         JCModifiers mods = optFinal(Flags.PARAMETER);
         JCExpression type = parseType();
         if (token.kind == ELLIPSIS) {
@@ -3233,12 +3250,12 @@
             type = to(F.at(token.pos).TypeArray(type));
             nextToken();
         }
-        return variableDeclaratorId(mods, type);
+        return variableDeclaratorId(mods, type, lambdaParameter);
     }
 
     protected JCVariableDecl implicitParameter() {
         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
-        return variableDeclaratorId(mods, null);
+        return variableDeclaratorId(mods, null, true);
     }
 
 /* ---------- auxiliary methods -------------- */