< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

Print this page
rev 51104 : imported patch switch


  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 import java.util.stream.Collectors;
  30 

  31 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  32 import com.sun.source.tree.ModuleTree.ModuleKind;

  33 
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.code.Source.Feature;
  36 import com.sun.tools.javac.parser.Tokens.*;
  37 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  38 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  39 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  40 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  41 import com.sun.tools.javac.tree.*;
  42 import com.sun.tools.javac.tree.JCTree.*;
  43 import com.sun.tools.javac.util.*;
  44 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  45 import com.sun.tools.javac.util.JCDiagnostic.Error;
  46 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  47 import com.sun.tools.javac.util.List;
  48 
  49 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  50 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  51 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  52 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  53 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  54 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  57 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  58 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  59 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;

  61 
  62 /** The parser maps a token sequence into an abstract syntax
  63  *  tree. It operates by recursive descent, with code derived
  64  *  systematically from an LL(1) grammar. For efficiency reasons, an
  65  *  operator precedence scheme is used for parsing binary operation
  66  *  expressions.
  67  *
  68  *  <p><b>This is NOT part of any supported API.
  69  *  If you write code that depends on this, you do so at your own risk.
  70  *  This code and its internal interfaces are subject to change or
  71  *  deletion without notice.</b>
  72  */
  73 public class JavacParser implements Parser {
  74 
  75     /** The number of precedence levels of infix operators.
  76      */
  77     private static final int infixPrecedenceLevels = 10;
  78 
  79     /** Is the parser instantiated to parse a module-info file ?
  80      */


 207     /** Switch: is "this" allowed as an identifier?
 208      * This is needed to parse receiver types.
 209      */
 210     boolean allowThisIdent;
 211 
 212     /** The type of the method receiver, as specified by a first "this" parameter.
 213      */
 214     JCVariableDecl receiverParam;
 215 
 216     /** When terms are parsed, the mode determines which is expected:
 217      *     mode = EXPR        : an expression
 218      *     mode = TYPE        : a type
 219      *     mode = NOPARAMS    : no parameters allowed for type
 220      *     mode = TYPEARG     : type argument
 221      */
 222     protected static final int EXPR = 0x1;
 223     protected static final int TYPE = 0x2;
 224     protected static final int NOPARAMS = 0x4;
 225     protected static final int TYPEARG = 0x8;
 226     protected static final int DIAMOND = 0x10;

 227 
 228     /** The current mode.
 229      */
 230     protected int mode = 0;
 231 
 232     /** The mode of the term that was parsed last.
 233      */
 234     protected int lastmode = 0;
 235 
 236     /* ---------- token management -------------- */
 237 
 238     protected Token token;
 239 
 240     public Token token() {
 241         return token;
 242     }
 243 
 244     public void nextToken() {
 245         S.nextToken();
 246         token = S.token();


1176                     JCFieldAccess sel = (JCFieldAccess) expr;
1177 
1178                     if (sel.name != names._class) {
1179                         return illegal();
1180                     } else {
1181                         log.error(token.pos, Errors.NoAnnotationsOnDotClass);
1182                         return expr;
1183                     }
1184                 }
1185                 default:
1186                     return illegal(typeAnnos.head.pos);
1187                 }
1188 
1189             } else {
1190                 // Type annotations targeting a cast
1191                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1192             }
1193             break;
1194         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1195             if (typeArgs != null) return illegal();
1196             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
1197                 t = lambdaExpressionOrStatement(false, false, pos);
1198             } else {
1199                 t = toP(F.at(token.pos).Ident(ident()));
1200                 loop: while (true) {
1201                     pos = token.pos;
1202                     final List<JCAnnotation> annos = typeAnnotationsOpt();
1203 
1204                     // need to report an error later if LBRACKET is for array
1205                     // index access rather than array creation level
1206                     if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1207                         return illegal(annos.head.pos);
1208 
1209                     switch (token.kind) {
1210                     case LBRACKET:
1211                         nextToken();
1212                         if (token.kind == RBRACKET) {
1213                             nextToken();
1214                             t = bracketsOpt(t);
1215                             t = toP(F.at(pos).TypeArray(t));
1216                             if (annos.nonEmpty()) {


1339         case VOID:
1340             if (typeArgs != null) illegal();
1341             if ((mode & EXPR) != 0) {
1342                 nextToken();
1343                 if (token.kind == DOT) {
1344                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1345                     t = bracketsSuffix(ti);
1346                 } else {
1347                     return illegal(pos);
1348                 }
1349             } else {
1350                 // Support the corner case of myMethodHandle.<void>invoke() by passing
1351                 // a void type (like other primitive types) to the next phase.
1352                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1353                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1354                 nextToken();
1355                 return ti;
1356                 //return illegal();
1357             }
1358             break;
























1359         default:
1360             return illegal();
1361         }
1362         return term3Rest(t, typeArgs);
1363     }
1364 














































1365     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1366         if (typeArgs != null) illegal();
1367         while (true) {
1368             int pos1 = token.pos;
1369             final List<JCAnnotation> annos = typeAnnotationsOpt();
1370 
1371             if (token.kind == LBRACKET) {
1372                 nextToken();
1373                 if ((mode & TYPE) != 0) {
1374                     int oldmode = mode;
1375                     mode = TYPE;
1376                     if (token.kind == RBRACKET) {
1377                         nextToken();
1378                         t = bracketsOpt(t);
1379                         t = toP(F.at(pos1).TypeArray(t));
1380                         if (token.kind == COLCOL) {
1381                             mode = EXPR;
1382                             continue;
1383                         }
1384                         if (annos.nonEmpty()) {


2600             JCExpression lock = parExpression();
2601             JCBlock body = block();
2602             return F.at(pos).Synchronized(lock, body);
2603         }
2604         case RETURN: {
2605             nextToken();
2606             JCExpression result = token.kind == SEMI ? null : parseExpression();
2607             accept(SEMI);
2608             JCReturn t = toP(F.at(pos).Return(result));
2609             return t;
2610         }
2611         case THROW: {
2612             nextToken();
2613             JCExpression exc = parseExpression();
2614             accept(SEMI);
2615             JCThrow t = toP(F.at(pos).Throw(exc));
2616             return t;
2617         }
2618         case BREAK: {
2619             nextToken();
2620             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2621             accept(SEMI);
2622             JCBreak t = toP(F.at(pos).Break(label));
2623             return t;
2624         }
2625         case CONTINUE: {
2626             nextToken();
2627             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2628             accept(SEMI);
2629             JCContinue t =  toP(F.at(pos).Continue(label));
2630             return t;
2631         }
2632         case SEMI:
2633             nextToken();
2634             return toP(F.at(pos).Skip());
2635         case ELSE:
2636             int elsePos = token.pos;
2637             nextToken();
2638             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.ElseWithoutIf);
2639         case FINALLY:
2640             int finallyPos = token.pos;
2641             nextToken();
2642             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.FinallyWithoutTry);


2696         while (token.kind == BAR) {
2697             nextToken();
2698             // Instead of qualident this is now parseType.
2699             // But would that allow too much, e.g. arrays or generics?
2700             catchTypes.add(parseType());
2701         }
2702         return catchTypes.toList();
2703     }
2704 
2705     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2706      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
2707      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2708      */
2709     List<JCCase> switchBlockStatementGroups() {
2710         ListBuffer<JCCase> cases = new ListBuffer<>();
2711         while (true) {
2712             int pos = token.pos;
2713             switch (token.kind) {
2714             case CASE:
2715             case DEFAULT:
2716                 cases.append(switchBlockStatementGroup());
2717                 break;
2718             case RBRACE: case EOF:
2719                 return cases.toList();
2720             default:
2721                 nextToken(); // to ensure progress
2722                 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
2723             }
2724         }
2725     }
2726 
2727     protected JCCase switchBlockStatementGroup() {
2728         int pos = token.pos;
2729         List<JCStatement> stats;
2730         JCCase c;

2731         switch (token.kind) {
2732         case CASE:





2733             nextToken();
2734             JCExpression pat = parseExpression();















2735             accept(COLON);

2736             stats = blockStatements();
2737             c = F.at(pos).Case(pat, stats);

2738             if (stats.isEmpty())
2739                 storeEnd(c, S.prevToken().endPos);
2740             return c;
2741         case DEFAULT:

2742             nextToken();




2743             accept(COLON);

2744             stats = blockStatements();
2745             c = F.at(pos).Case(null, stats);











2746             if (stats.isEmpty())
2747                 storeEnd(c, S.prevToken().endPos);
2748             return c;

2749         }
2750         throw new AssertionError("should not reach here");
2751     }
2752 
2753     /** MoreStatementExpressions = { COMMA StatementExpression }
2754      */
2755     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2756                                                                     JCExpression first,
2757                                                                     T stats) {
2758         // This Exec is a "StatementExpression"; it subsumes no terminating token
2759         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2760         while (token.kind == COMMA) {
2761             nextToken();
2762             pos = token.pos;
2763             JCExpression t = parseExpression();
2764             // This Exec is a "StatementExpression"; it subsumes no terminating token
2765             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2766         }
2767         return stats;
2768     }




  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 import java.util.stream.Collectors;
  30 
  31 import com.sun.source.tree.CaseTree.CaseKind;
  32 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  33 import com.sun.source.tree.ModuleTree.ModuleKind;
  34 import com.sun.source.tree.Tree;
  35 
  36 import com.sun.tools.javac.code.*;
  37 import com.sun.tools.javac.code.Source.Feature;
  38 import com.sun.tools.javac.parser.Tokens.*;
  39 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  40 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  41 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  42 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  43 import com.sun.tools.javac.tree.*;
  44 import com.sun.tools.javac.tree.JCTree.*;
  45 import com.sun.tools.javac.util.*;
  46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  47 import com.sun.tools.javac.util.JCDiagnostic.Error;
  48 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  49 import com.sun.tools.javac.util.List;
  50 
  51 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  52 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  53 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  54 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  59 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  61 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  62 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  63 import com.sun.tools.javac.tree.JCTree.JCStatement;
  64 
  65 /** The parser maps a token sequence into an abstract syntax
  66  *  tree. It operates by recursive descent, with code derived
  67  *  systematically from an LL(1) grammar. For efficiency reasons, an
  68  *  operator precedence scheme is used for parsing binary operation
  69  *  expressions.
  70  *
  71  *  <p><b>This is NOT part of any supported API.
  72  *  If you write code that depends on this, you do so at your own risk.
  73  *  This code and its internal interfaces are subject to change or
  74  *  deletion without notice.</b>
  75  */
  76 public class JavacParser implements Parser {
  77 
  78     /** The number of precedence levels of infix operators.
  79      */
  80     private static final int infixPrecedenceLevels = 10;
  81 
  82     /** Is the parser instantiated to parse a module-info file ?
  83      */


 210     /** Switch: is "this" allowed as an identifier?
 211      * This is needed to parse receiver types.
 212      */
 213     boolean allowThisIdent;
 214 
 215     /** The type of the method receiver, as specified by a first "this" parameter.
 216      */
 217     JCVariableDecl receiverParam;
 218 
 219     /** When terms are parsed, the mode determines which is expected:
 220      *     mode = EXPR        : an expression
 221      *     mode = TYPE        : a type
 222      *     mode = NOPARAMS    : no parameters allowed for type
 223      *     mode = TYPEARG     : type argument
 224      */
 225     protected static final int EXPR = 0x1;
 226     protected static final int TYPE = 0x2;
 227     protected static final int NOPARAMS = 0x4;
 228     protected static final int TYPEARG = 0x8;
 229     protected static final int DIAMOND = 0x10;
 230     protected static final int NOLAMBDA = 0x20;
 231 
 232     /** The current mode.
 233      */
 234     protected int mode = 0;
 235 
 236     /** The mode of the term that was parsed last.
 237      */
 238     protected int lastmode = 0;
 239 
 240     /* ---------- token management -------------- */
 241 
 242     protected Token token;
 243 
 244     public Token token() {
 245         return token;
 246     }
 247 
 248     public void nextToken() {
 249         S.nextToken();
 250         token = S.token();


1180                     JCFieldAccess sel = (JCFieldAccess) expr;
1181 
1182                     if (sel.name != names._class) {
1183                         return illegal();
1184                     } else {
1185                         log.error(token.pos, Errors.NoAnnotationsOnDotClass);
1186                         return expr;
1187                     }
1188                 }
1189                 default:
1190                     return illegal(typeAnnos.head.pos);
1191                 }
1192 
1193             } else {
1194                 // Type annotations targeting a cast
1195                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1196             }
1197             break;
1198         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1199             if (typeArgs != null) return illegal();
1200             if ((mode & EXPR) != 0 && (mode & NOLAMBDA) == 0 && peekToken(ARROW)) {
1201                 t = lambdaExpressionOrStatement(false, false, pos);
1202             } else {
1203                 t = toP(F.at(token.pos).Ident(ident()));
1204                 loop: while (true) {
1205                     pos = token.pos;
1206                     final List<JCAnnotation> annos = typeAnnotationsOpt();
1207 
1208                     // need to report an error later if LBRACKET is for array
1209                     // index access rather than array creation level
1210                     if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1211                         return illegal(annos.head.pos);
1212 
1213                     switch (token.kind) {
1214                     case LBRACKET:
1215                         nextToken();
1216                         if (token.kind == RBRACKET) {
1217                             nextToken();
1218                             t = bracketsOpt(t);
1219                             t = toP(F.at(pos).TypeArray(t));
1220                             if (annos.nonEmpty()) {


1343         case VOID:
1344             if (typeArgs != null) illegal();
1345             if ((mode & EXPR) != 0) {
1346                 nextToken();
1347                 if (token.kind == DOT) {
1348                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1349                     t = bracketsSuffix(ti);
1350                 } else {
1351                     return illegal(pos);
1352                 }
1353             } else {
1354                 // Support the corner case of myMethodHandle.<void>invoke() by passing
1355                 // a void type (like other primitive types) to the next phase.
1356                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1357                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1358                 nextToken();
1359                 return ti;
1360                 //return illegal();
1361             }
1362             break;
1363         case SWITCH:
1364             checkSourceLevel(Feature.SWITCH_EXPRESSION);
1365             int switchPos = token.pos;
1366             nextToken();
1367             JCExpression selector = parExpression();
1368             accept(LBRACE);
1369             ListBuffer<JCCase> cases = new ListBuffer<>();
1370             while (true) {
1371                 pos = token.pos;
1372                 switch (token.kind) {
1373                 case CASE:
1374                 case DEFAULT:
1375                     cases.appendList(switchExpressionStatementGroup());
1376                     break;
1377                 case RBRACE: case EOF:
1378                     JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
1379                                                                                cases.toList()));
1380                     accept(RBRACE);
1381                     return e;
1382                 default:
1383                     nextToken(); // to ensure progress
1384                     syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
1385                 }
1386             }
1387         default:
1388             return illegal();
1389         }
1390         return term3Rest(t, typeArgs);
1391     }
1392 
1393     private List<JCCase> switchExpressionStatementGroup() {
1394         ListBuffer<JCCase> caseExprs = new ListBuffer<>();
1395         int casePos = token.pos;
1396         ListBuffer<JCExpression> pats = new ListBuffer<>();
1397 
1398         if (token.kind == DEFAULT) {
1399             nextToken();
1400         } else {
1401             accept(CASE);
1402             while (true) {
1403                 pats.append(term(EXPR | NOLAMBDA));
1404                 if (token.kind != COMMA) break;
1405                 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
1406                 nextToken();
1407             };
1408         }
1409         List<JCStatement> stats = null;
1410         JCTree body = null;
1411         @SuppressWarnings("removal")
1412         CaseKind kind;
1413         switch (token.kind) {
1414             case ARROW:
1415                 checkSourceLevel(Feature.SWITCH_RULE);
1416                 nextToken();
1417                 if (token.kind == TokenKind.THROW || token.kind == TokenKind.LBRACE) {
1418                     stats = List.of(parseStatement());
1419                     body = stats.head;
1420                     kind = JCCase.RULE;
1421                 } else {
1422                     JCExpression value = parseExpression();
1423                     stats = List.of(to(F.at(value).Break(value)));
1424                     body = value;
1425                     kind = JCCase.RULE;
1426                     accept(SEMI);
1427                 }
1428                 break;
1429             default:
1430                 accept(COLON);
1431                 stats = blockStatements();
1432                 kind = JCCase.STATEMENT;
1433                 break;
1434         }
1435         caseExprs.append(toP(F.at(casePos).Case(kind, pats.toList(), stats, body)));
1436         return caseExprs.toList();
1437     }
1438 
1439     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1440         if (typeArgs != null) illegal();
1441         while (true) {
1442             int pos1 = token.pos;
1443             final List<JCAnnotation> annos = typeAnnotationsOpt();
1444 
1445             if (token.kind == LBRACKET) {
1446                 nextToken();
1447                 if ((mode & TYPE) != 0) {
1448                     int oldmode = mode;
1449                     mode = TYPE;
1450                     if (token.kind == RBRACKET) {
1451                         nextToken();
1452                         t = bracketsOpt(t);
1453                         t = toP(F.at(pos1).TypeArray(t));
1454                         if (token.kind == COLCOL) {
1455                             mode = EXPR;
1456                             continue;
1457                         }
1458                         if (annos.nonEmpty()) {


2674             JCExpression lock = parExpression();
2675             JCBlock body = block();
2676             return F.at(pos).Synchronized(lock, body);
2677         }
2678         case RETURN: {
2679             nextToken();
2680             JCExpression result = token.kind == SEMI ? null : parseExpression();
2681             accept(SEMI);
2682             JCReturn t = toP(F.at(pos).Return(result));
2683             return t;
2684         }
2685         case THROW: {
2686             nextToken();
2687             JCExpression exc = parseExpression();
2688             accept(SEMI);
2689             JCThrow t = toP(F.at(pos).Throw(exc));
2690             return t;
2691         }
2692         case BREAK: {
2693             nextToken();
2694             JCExpression value = token.kind == SEMI ? null : parseExpression();
2695             accept(SEMI);
2696             JCBreak t = toP(F.at(pos).Break(value));
2697             return t;
2698         }
2699         case CONTINUE: {
2700             nextToken();
2701             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2702             accept(SEMI);
2703             JCContinue t =  toP(F.at(pos).Continue(label));
2704             return t;
2705         }
2706         case SEMI:
2707             nextToken();
2708             return toP(F.at(pos).Skip());
2709         case ELSE:
2710             int elsePos = token.pos;
2711             nextToken();
2712             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.ElseWithoutIf);
2713         case FINALLY:
2714             int finallyPos = token.pos;
2715             nextToken();
2716             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.FinallyWithoutTry);


2770         while (token.kind == BAR) {
2771             nextToken();
2772             // Instead of qualident this is now parseType.
2773             // But would that allow too much, e.g. arrays or generics?
2774             catchTypes.add(parseType());
2775         }
2776         return catchTypes.toList();
2777     }
2778 
2779     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2780      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
2781      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2782      */
2783     List<JCCase> switchBlockStatementGroups() {
2784         ListBuffer<JCCase> cases = new ListBuffer<>();
2785         while (true) {
2786             int pos = token.pos;
2787             switch (token.kind) {
2788             case CASE:
2789             case DEFAULT:
2790                 cases.appendList(switchBlockStatementGroup());
2791                 break;
2792             case RBRACE: case EOF:
2793                 return cases.toList();
2794             default:
2795                 nextToken(); // to ensure progress
2796                 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
2797             }
2798         }
2799     }
2800 
2801     protected List<JCCase> switchBlockStatementGroup() {
2802         int pos = token.pos;
2803         List<JCStatement> stats;
2804         JCCase c;
2805         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2806         switch (token.kind) {
2807         case CASE: {
2808             nextToken();
2809             ListBuffer<JCExpression> pats = new ListBuffer<>();
2810             while (true) {
2811                 pats.append(term(EXPR | NOLAMBDA));
2812                 if (token.kind != COMMA) break;
2813                 nextToken();
2814                 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
2815             };
2816             @SuppressWarnings("removal")
2817             CaseKind caseKind;
2818             JCTree body = null;
2819             if (token.kind == ARROW) {
2820                 checkSourceLevel(Feature.SWITCH_RULE);
2821                 accept(ARROW);
2822                 caseKind = JCCase.RULE;
2823                 JCStatement statement = parseStatementAsBlock();
2824                 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
2825                     log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
2826                 }
2827                 stats = List.of(statement);
2828                 body = stats.head;
2829             } else {
2830                 accept(COLON);
2831                 caseKind = JCCase.STATEMENT;
2832                 stats = blockStatements();
2833             }
2834             c = F.at(pos).Case(caseKind, pats.toList(), stats, body);
2835             if (stats.isEmpty())
2836                 storeEnd(c, S.prevToken().endPos);
2837             return cases.append(c).toList();
2838         }
2839         case DEFAULT: {
2840             nextToken();
2841             @SuppressWarnings("removal")
2842             CaseKind caseKind;
2843             JCTree body = null;
2844             if (token.kind == COLON) {
2845                 accept(COLON);
2846                 caseKind = JCCase.STATEMENT;
2847                 stats = blockStatements();
2848             } else {
2849                 checkSourceLevel(Feature.SWITCH_RULE);
2850                 accept(ARROW);
2851                 caseKind = JCCase.RULE;
2852                 JCStatement statement = parseStatementAsBlock();
2853                 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
2854                     log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
2855                 }
2856                 stats = List.of(statement);
2857                 body = stats.head;
2858             }
2859             c = F.at(pos).Case(caseKind, List.nil(), stats, body);
2860             if (stats.isEmpty())
2861                 storeEnd(c, S.prevToken().endPos);
2862             return cases.append(c).toList();
2863         }
2864         }
2865         throw new AssertionError("should not reach here");
2866     }
2867 
2868     /** MoreStatementExpressions = { COMMA StatementExpression }
2869      */
2870     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2871                                                                     JCExpression first,
2872                                                                     T stats) {
2873         // This Exec is a "StatementExpression"; it subsumes no terminating token
2874         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2875         while (token.kind == COMMA) {
2876             nextToken();
2877             pos = token.pos;
2878             JCExpression t = parseExpression();
2879             // This Exec is a "StatementExpression"; it subsumes no terminating token
2880             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2881         }
2882         return stats;
2883     }


< prev index next >