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 }
|