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;
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
35 import com.sun.tools.javac.code.*;
36 import com.sun.tools.javac.code.Source.Feature;
37 import com.sun.tools.javac.parser.Tokens.*;
38 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
39 import com.sun.tools.javac.resources.CompilerProperties.Errors;
40 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
41 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
42 import com.sun.tools.javac.tree.*;
43 import com.sun.tools.javac.tree.JCTree.*;
44 import com.sun.tools.javac.util.*;
45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
46 import com.sun.tools.javac.util.JCDiagnostic.Error;
47 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
48 import com.sun.tools.javac.util.List;
49
50 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
51 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
208 /** Switch: is "this" allowed as an identifier?
209 * This is needed to parse receiver types.
210 */
211 boolean allowThisIdent;
212
213 /** The type of the method receiver, as specified by a first "this" parameter.
214 */
215 JCVariableDecl receiverParam;
216
217 /** When terms are parsed, the mode determines which is expected:
218 * mode = EXPR : an expression
219 * mode = TYPE : a type
220 * mode = NOPARAMS : no parameters allowed for type
221 * mode = TYPEARG : type argument
222 */
223 protected static final int EXPR = 0x1;
224 protected static final int TYPE = 0x2;
225 protected static final int NOPARAMS = 0x4;
226 protected static final int TYPEARG = 0x8;
227 protected static final int DIAMOND = 0x10;
228 protected static final int NOLAMBDA = 0x20;
229
230 /** The current mode.
231 */
232 protected int mode = 0;
233
234 /** The mode of the term that was parsed last.
235 */
236 protected int lastmode = 0;
237
238 /* ---------- token management -------------- */
239
240 protected Token token;
241
242 public Token token() {
243 return token;
244 }
245
246 public void nextToken() {
247 S.nextToken();
248 token = S.token();
1178 JCFieldAccess sel = (JCFieldAccess) expr;
1179
1180 if (sel.name != names._class) {
1181 return illegal();
1182 } else {
1183 log.error(token.pos, Errors.NoAnnotationsOnDotClass);
1184 return expr;
1185 }
1186 }
1187 default:
1188 return illegal(typeAnnos.head.pos);
1189 }
1190
1191 } else {
1192 // Type annotations targeting a cast
1193 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1194 }
1195 break;
1196 case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1197 if (typeArgs != null) return illegal();
1198 if ((mode & EXPR) != 0 && (mode & NOLAMBDA) == 0 && peekToken(ARROW)) {
1199 t = lambdaExpressionOrStatement(false, false, pos);
1200 } else {
1201 t = toP(F.at(token.pos).Ident(ident()));
1202 loop: while (true) {
1203 pos = token.pos;
1204 final List<JCAnnotation> annos = typeAnnotationsOpt();
1205
1206 // need to report an error later if LBRACKET is for array
1207 // index access rather than array creation level
1208 if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1209 return illegal(annos.head.pos);
1210
1211 switch (token.kind) {
1212 case LBRACKET:
1213 nextToken();
1214 if (token.kind == RBRACKET) {
1215 nextToken();
1216 t = bracketsOpt(t);
1217 t = toP(F.at(pos).TypeArray(t));
1218 if (annos.nonEmpty()) {
1341 case VOID:
1342 if (typeArgs != null) illegal();
1343 if ((mode & EXPR) != 0) {
1344 nextToken();
1345 if (token.kind == DOT) {
1346 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1347 t = bracketsSuffix(ti);
1348 } else {
1349 return illegal(pos);
1350 }
1351 } else {
1352 // Support the corner case of myMethodHandle.<void>invoke() by passing
1353 // a void type (like other primitive types) to the next phase.
1354 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1355 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1356 nextToken();
1357 return ti;
1358 //return illegal();
1359 }
1360 break;
1361 case SWITCH:
1362 checkSourceLevel(Feature.SWITCH_EXPRESSION);
1363 int switchPos = token.pos;
1364 nextToken();
1365 JCExpression selector = parExpression();
1366 accept(LBRACE);
1367 ListBuffer<JCCase> cases = new ListBuffer<>();
1368 while (true) {
1369 pos = token.pos;
1370 switch (token.kind) {
1371 case CASE:
1372 case DEFAULT:
1373 cases.appendList(switchExpressionStatementGroup());
1374 break;
1375 case RBRACE: case EOF:
1376 JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
1377 cases.toList()));
1378 accept(RBRACE);
1379 return e;
1380 default:
1381 nextToken(); // to ensure progress
1382 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
1383 }
1384 }
1385 default:
1386 return illegal();
1387 }
1388 return term3Rest(t, typeArgs);
1389 }
1390
1391 private List<JCCase> switchExpressionStatementGroup() {
1392 ListBuffer<JCCase> caseExprs = new ListBuffer<>();
1393 int casePos = token.pos;
1394 ListBuffer<JCExpression> pats = new ListBuffer<>();
1395
1396 if (token.kind == DEFAULT) {
1397 nextToken();
1398 } else {
1399 accept(CASE);
1400 while (true) {
1401 pats.append(term(EXPR | NOLAMBDA));
1402 if (token.kind != COMMA) break;
1403 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
1404 nextToken();
1405 };
1406 }
1407 List<JCStatement> stats = null;
1408 JCTree body = null;
1409 @SuppressWarnings("removal")
1410 CaseKind kind;
1411 switch (token.kind) {
1412 case ARROW:
1413 checkSourceLevel(Feature.SWITCH_RULE);
1414 nextToken();
1415 if (token.kind == TokenKind.THROW || token.kind == TokenKind.LBRACE) {
1416 stats = List.of(parseStatement());
1417 body = stats.head;
1418 kind = JCCase.RULE;
1419 } else {
1420 JCExpression value = parseExpression();
1421 stats = List.of(to(F.at(value).Break(value)));
1422 body = value;
1423 kind = JCCase.RULE;
1424 accept(SEMI);
1425 }
1426 break;
1427 default:
1428 accept(COLON);
1429 stats = blockStatements();
1430 kind = JCCase.STATEMENT;
1431 break;
1432 }
1433 caseExprs.append(toP(F.at(casePos).Case(kind, pats.toList(), stats, body)));
1434 return caseExprs.toList();
1435 }
1436
1437 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1438 if (typeArgs != null) illegal();
1439 while (true) {
1440 int pos1 = token.pos;
1441 final List<JCAnnotation> annos = typeAnnotationsOpt();
1442
1443 if (token.kind == LBRACKET) {
1444 nextToken();
1445 if ((mode & TYPE) != 0) {
1446 int oldmode = mode;
1447 mode = TYPE;
1448 if (token.kind == RBRACKET) {
1449 nextToken();
1450 t = bracketsOpt(t);
1451 t = toP(F.at(pos1).TypeArray(t));
1452 if (token.kind == COLCOL) {
1453 mode = EXPR;
1454 continue;
1455 }
1456 if (annos.nonEmpty()) {
2672 JCExpression lock = parExpression();
2673 JCBlock body = block();
2674 return F.at(pos).Synchronized(lock, body);
2675 }
2676 case RETURN: {
2677 nextToken();
2678 JCExpression result = token.kind == SEMI ? null : parseExpression();
2679 accept(SEMI);
2680 JCReturn t = toP(F.at(pos).Return(result));
2681 return t;
2682 }
2683 case THROW: {
2684 nextToken();
2685 JCExpression exc = parseExpression();
2686 accept(SEMI);
2687 JCThrow t = toP(F.at(pos).Throw(exc));
2688 return t;
2689 }
2690 case BREAK: {
2691 nextToken();
2692 JCExpression value = token.kind == SEMI ? null : parseExpression();
2693 accept(SEMI);
2694 JCBreak t = toP(F.at(pos).Break(value));
2695 return t;
2696 }
2697 case CONTINUE: {
2698 nextToken();
2699 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2700 accept(SEMI);
2701 JCContinue t = toP(F.at(pos).Continue(label));
2702 return t;
2703 }
2704 case SEMI:
2705 nextToken();
2706 return toP(F.at(pos).Skip());
2707 case ELSE:
2708 int elsePos = token.pos;
2709 nextToken();
2710 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.ElseWithoutIf);
2711 case FINALLY:
2712 int finallyPos = token.pos;
2713 nextToken();
2714 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.FinallyWithoutTry);
2768 while (token.kind == BAR) {
2769 nextToken();
2770 // Instead of qualident this is now parseType.
2771 // But would that allow too much, e.g. arrays or generics?
2772 catchTypes.add(parseType());
2773 }
2774 return catchTypes.toList();
2775 }
2776
2777 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2778 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
2779 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2780 */
2781 List<JCCase> switchBlockStatementGroups() {
2782 ListBuffer<JCCase> cases = new ListBuffer<>();
2783 while (true) {
2784 int pos = token.pos;
2785 switch (token.kind) {
2786 case CASE:
2787 case DEFAULT:
2788 cases.appendList(switchBlockStatementGroup());
2789 break;
2790 case RBRACE: case EOF:
2791 return cases.toList();
2792 default:
2793 nextToken(); // to ensure progress
2794 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
2795 }
2796 }
2797 }
2798
2799 protected List<JCCase> switchBlockStatementGroup() {
2800 int pos = token.pos;
2801 List<JCStatement> stats;
2802 JCCase c;
2803 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2804 switch (token.kind) {
2805 case CASE: {
2806 nextToken();
2807 ListBuffer<JCExpression> pats = new ListBuffer<>();
2808 while (true) {
2809 pats.append(term(EXPR | NOLAMBDA));
2810 if (token.kind != COMMA) break;
2811 nextToken();
2812 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
2813 };
2814 @SuppressWarnings("removal")
2815 CaseKind caseKind;
2816 JCTree body = null;
2817 if (token.kind == ARROW) {
2818 checkSourceLevel(Feature.SWITCH_RULE);
2819 accept(ARROW);
2820 caseKind = JCCase.RULE;
2821 JCStatement statement = parseStatementAsBlock();
2822 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
2823 log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
2824 }
2825 stats = List.of(statement);
2826 body = stats.head;
2827 } else {
2828 accept(COLON);
2829 caseKind = JCCase.STATEMENT;
2830 stats = blockStatements();
2831 }
2832 c = F.at(pos).Case(caseKind, pats.toList(), stats, body);
2833 if (stats.isEmpty())
2834 storeEnd(c, S.prevToken().endPos);
2835 return cases.append(c).toList();
2836 }
2837 case DEFAULT: {
2838 nextToken();
2839 @SuppressWarnings("removal")
2840 CaseKind caseKind;
2841 JCTree body = null;
2842 if (token.kind == COLON) {
2843 accept(COLON);
2844 caseKind = JCCase.STATEMENT;
2845 stats = blockStatements();
2846 } else {
2847 checkSourceLevel(Feature.SWITCH_RULE);
2848 accept(ARROW);
2849 caseKind = JCCase.RULE;
2850 JCStatement statement = parseStatementAsBlock();
2851 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
2852 log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
2853 }
2854 stats = List.of(statement);
2855 body = stats.head;
2856 }
2857 c = F.at(pos).Case(caseKind, List.nil(), stats, body);
2858 if (stats.isEmpty())
2859 storeEnd(c, S.prevToken().endPos);
2860 return cases.append(c).toList();
2861 }
2862 }
2863 throw new AssertionError("should not reach here");
2864 }
2865
2866 /** MoreStatementExpressions = { COMMA StatementExpression }
2867 */
2868 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2869 JCExpression first,
2870 T stats) {
2871 // This Exec is a "StatementExpression"; it subsumes no terminating token
2872 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2873 while (token.kind == COMMA) {
2874 nextToken();
2875 pos = token.pos;
2876 JCExpression t = parseExpression();
2877 // This Exec is a "StatementExpression"; it subsumes no terminating token
2878 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2879 }
2880 return stats;
2881 }
|