< prev index next >
src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
Print this page
rev 51258 : imported patch switch.diff
@@ -26,10 +26,11 @@
package com.sun.tools.javac.parser;
import java.util.*;
import java.util.stream.Collectors;
+import com.sun.source.tree.CaseTree.CaseKind;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Source.Feature;
@@ -222,10 +223,11 @@
protected static final int EXPR = 0x1;
protected static final int TYPE = 0x2;
protected static final int NOPARAMS = 0x4;
protected static final int TYPEARG = 0x8;
protected static final int DIAMOND = 0x10;
+ protected static final int NOLAMBDA = 0x20;
/** The current mode.
*/
protected int mode = 0;
@@ -1191,11 +1193,11 @@
t = insertAnnotationsToMostInner(expr, typeAnnos, false);
}
break;
case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
if (typeArgs != null) return illegal();
- if ((mode & EXPR) != 0 && peekToken(ARROW)) {
+ if ((mode & EXPR) != 0 && (mode & NOLAMBDA) == 0 && peekToken(ARROW)) {
t = lambdaExpressionOrStatement(false, false, pos);
} else {
t = toP(F.at(token.pos).Ident(ident()));
loop: while (true) {
pos = token.pos;
@@ -1354,16 +1356,86 @@
nextToken();
return ti;
//return illegal();
}
break;
+ case SWITCH:
+ checkSourceLevel(Feature.SWITCH_EXPRESSION);
+ int switchPos = token.pos;
+ nextToken();
+ JCExpression selector = parExpression();
+ accept(LBRACE);
+ ListBuffer<JCCase> cases = new ListBuffer<>();
+ while (true) {
+ pos = token.pos;
+ switch (token.kind) {
+ case CASE:
+ case DEFAULT:
+ cases.appendList(switchExpressionStatementGroup());
+ break;
+ case RBRACE: case EOF:
+ JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
+ cases.toList()));
+ accept(RBRACE);
+ return e;
+ default:
+ nextToken(); // to ensure progress
+ syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
+ }
+ }
default:
return illegal();
}
return term3Rest(t, typeArgs);
}
+ private List<JCCase> switchExpressionStatementGroup() {
+ ListBuffer<JCCase> caseExprs = new ListBuffer<>();
+ int casePos = token.pos;
+ ListBuffer<JCExpression> pats = new ListBuffer<>();
+
+ if (token.kind == DEFAULT) {
+ nextToken();
+ } else {
+ accept(CASE);
+ while (true) {
+ pats.append(term(EXPR | NOLAMBDA));
+ if (token.kind != COMMA) break;
+ checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
+ nextToken();
+ };
+ }
+ List<JCStatement> stats = null;
+ JCTree body = null;
+ @SuppressWarnings("removal")
+ CaseKind kind;
+ switch (token.kind) {
+ case ARROW:
+ checkSourceLevel(Feature.SWITCH_RULE);
+ nextToken();
+ if (token.kind == TokenKind.THROW || token.kind == TokenKind.LBRACE) {
+ stats = List.of(parseStatement());
+ body = stats.head;
+ kind = JCCase.RULE;
+ } else {
+ JCExpression value = parseExpression();
+ stats = List.of(to(F.at(value).Break(value)));
+ body = value;
+ kind = JCCase.RULE;
+ accept(SEMI);
+ }
+ break;
+ default:
+ accept(COLON);
+ stats = blockStatements();
+ kind = JCCase.STATEMENT;
+ break;
+ }
+ caseExprs.append(toP(F.at(casePos).Case(kind, pats.toList(), stats, body)));
+ return caseExprs.toList();
+ }
+
JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
if (typeArgs != null) illegal();
while (true) {
int pos1 = token.pos;
final List<JCAnnotation> annos = typeAnnotationsOpt();
@@ -2615,13 +2687,13 @@
JCThrow t = toP(F.at(pos).Throw(exc));
return t;
}
case BREAK: {
nextToken();
- Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
+ JCExpression value = token.kind == SEMI ? null : parseExpression();
accept(SEMI);
- JCBreak t = toP(F.at(pos).Break(label));
+ JCBreak t = toP(F.at(pos).Break(value));
return t;
}
case CONTINUE: {
nextToken();
Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
@@ -2711,43 +2783,84 @@
while (true) {
int pos = token.pos;
switch (token.kind) {
case CASE:
case DEFAULT:
- cases.append(switchBlockStatementGroup());
+ cases.appendList(switchBlockStatementGroup());
break;
case RBRACE: case EOF:
return cases.toList();
default:
nextToken(); // to ensure progress
syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
}
}
}
- protected JCCase switchBlockStatementGroup() {
+ protected List<JCCase> switchBlockStatementGroup() {
int pos = token.pos;
List<JCStatement> stats;
JCCase c;
+ ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
switch (token.kind) {
- case CASE:
+ case CASE: {
+ nextToken();
+ ListBuffer<JCExpression> pats = new ListBuffer<>();
+ while (true) {
+ pats.append(term(EXPR | NOLAMBDA));
+ if (token.kind != COMMA) break;
nextToken();
- JCExpression pat = parseExpression();
+ checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
+ };
+ @SuppressWarnings("removal")
+ CaseKind caseKind;
+ JCTree body = null;
+ if (token.kind == ARROW) {
+ checkSourceLevel(Feature.SWITCH_RULE);
+ accept(ARROW);
+ caseKind = JCCase.RULE;
+ JCStatement statement = parseStatementAsBlock();
+ if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
+ log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
+ }
+ stats = List.of(statement);
+ body = stats.head;
+ } else {
accept(COLON);
+ caseKind = JCCase.STATEMENT;
stats = blockStatements();
- c = F.at(pos).Case(pat, stats);
+ }
+ c = F.at(pos).Case(caseKind, pats.toList(), stats, body);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
- return c;
- case DEFAULT:
+ return cases.append(c).toList();
+ }
+ case DEFAULT: {
nextToken();
+ @SuppressWarnings("removal")
+ CaseKind caseKind;
+ JCTree body = null;
+ if (token.kind == COLON) {
accept(COLON);
+ caseKind = JCCase.STATEMENT;
stats = blockStatements();
- c = F.at(pos).Case(null, stats);
+ } else {
+ checkSourceLevel(Feature.SWITCH_RULE);
+ accept(ARROW);
+ caseKind = JCCase.RULE;
+ JCStatement statement = parseStatementAsBlock();
+ if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
+ log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
+ }
+ stats = List.of(statement);
+ body = stats.head;
+ }
+ c = F.at(pos).Case(caseKind, List.nil(), stats, body);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
- return c;
+ return cases.append(c).toList();
+ }
}
throw new AssertionError("should not reach here");
}
/** MoreStatementExpressions = { COMMA StatementExpression }
< prev index next >