src/share/classes/com/sun/tools/javac/parser/JavacParser.java
Print this page
*** 131,140 ****
--- 131,142 ----
this.allowForeach = source.allowForeach();
this.allowStaticImport = source.allowStaticImport();
this.allowAnnotations = source.allowAnnotations();
this.allowDiamond = source.allowDiamond();
this.allowTypeAnnotations = source.allowTypeAnnotations();
+ this.allowFunctionType = source.allowFunctionType();
+ this.allowLambda = source.allowLambda();
this.keepDocComments = keepDocComments;
if (keepDocComments)
docComments = new HashMap<JCTree,String>();
this.keepLineMap = keepLineMap;
this.errorTree = F.Erroneous();
*** 167,177 ****
/** Switch: should we recognize foreach?
*/
boolean allowForeach;
! /** Switch: should we recognize foreach?
*/
boolean allowStaticImport;
/** Switch: should we recognize annotations?
*/
--- 169,179 ----
/** Switch: should we recognize foreach?
*/
boolean allowForeach;
! /** Switch: should we recognize static import?
*/
boolean allowStaticImport;
/** Switch: should we recognize annotations?
*/
*** 179,188 ****
--- 181,198 ----
/** Switch: should we recognize type annotations?
*/
boolean allowTypeAnnotations;
+ /** Switch: should we recognize function type?
+ */
+ boolean allowFunctionType;
+
+ /** Switch: should we recognize lambda?
+ */
+ boolean allowLambda;
+
/** Switch: should we keep docComments?
*/
boolean keepDocComments;
/** Switch: should we keep line table?
*** 878,887 ****
--- 888,898 ----
* | BasicType BracketsOpt "." CLASS
* PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
* PostfixOp = "++" | "--"
* Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
* | BasicType
+ * | FunctionType
* TypeNoParams3 = Ident { "." Ident } BracketsOpt
* Selector = "." [TypeArguments] Ident [Arguments]
* | "." THIS
* | "." [TypeArguments] SUPER SuperSuffix
* | "." NEW [TypeArguments] InnerCreator
*** 973,983 ****
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 BYTE: case SHORT: case CHAR: case INT:
! case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
JCExpression t1 = term3();
return F.at(pos).TypeCast(t, t1);
}
}
} else return illegal();
--- 984,995 ----
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 BYTE: case SHORT: case CHAR: case INT:
! case LONG: case FLOAT: case DOUBLE: case BOOLEAN:
! case VOID: case SHARP:
JCExpression t1 = term3();
return F.at(pos).TypeCast(t, t1);
}
}
} else return illegal();
*** 1047,1056 ****
--- 1059,1076 ----
} else {
// type annotation targeting a cast
t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
}
break;
+ case SHARP:
+ if (typeArgs != null) illegal();
+ JCExpression exprType = bracketsOpt(functionType());
+ if (S.token() == DOT) {
+ exprType = bracketsSuffix(exprType);
+ }
+ t = exprType;
+ break;
case IDENTIFIER: case ASSERT: case ENUM:
if (typeArgs != null) return illegal();
t = toP(F.at(S.pos()).Ident(ident()));
loop: while (true) {
pos = S.pos();
*** 1082,1092 ****
}
break loop;
case LPAREN:
if ((mode & EXPR) != 0) {
mode = EXPR;
! t = arguments(typeArgs, t);
typeArgs = null;
}
break loop;
case DOT:
S.nextToken();
--- 1102,1112 ----
}
break loop;
case LPAREN:
if ((mode & EXPR) != 0) {
mode = EXPR;
! t = argumentsOrLambda(typeArgs, t);
typeArgs = null;
}
break loop;
case DOT:
S.nextToken();
*** 1257,1266 ****
--- 1277,1300 ----
JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
S.nextToken();
return t;
}
+ /** FunctionType = "#" Type "(" [Type { "," Type}] ")"
+ */
+ JCExpression functionType() {
+ checkFunctionType();
+ int pos = S.pos();
+ S.nextToken();
+ JCExpression returnType = parseType();
+ accept(LPAREN);
+ List<JCExpression> parameterTypes = (S.token() != RPAREN)? typeList(): List.<JCExpression>nil();
+ accept(RPAREN);
+ JCFunctionType t = to(F.at(S.pos()).FunctionType(parameterTypes, returnType));
+ return t;
+ }
+
/** ArgumentsOpt = [ Arguments ]
*/
JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
mode = EXPR;
*** 1294,1303 ****
--- 1328,1420 ----
int pos = S.pos();
List<JCExpression> args = arguments();
return toP(F.at(pos).Apply(typeArgs, t, args));
}
+ JCExpression argumentsOrLambda(List<JCExpression> typeArgs, JCExpression t) {
+ if (typeArgs != null ||
+ t.getTag() != JCTree.IDENT ||
+ ((JCIdent)t).name != names._lambda)
+ return arguments(typeArgs, t);
+
+
+ int applyPos = S.pos();
+ accept(LPAREN);
+
+ if (S.token() != RPAREN) {
+ int firstFormalPos = S.pos();
+ if (S.token() == FINAL || S.token() == MONKEYS_AT) {
+ return lambdaRest(t.pos, ListBuffer.<JCVariableDecl>lb());
+ }
+
+ JCExpression exprOrType = term(EXPR | TYPE);
+ if ((lastmode & TYPE) != 0 &&
+ (S.token() == IDENTIFIER ||
+ S.token() == ASSERT ||
+ S.token() == ENUM)) {
+ JCModifiers mods = toP(F.at(firstFormalPos).Modifiers(Flags.PARAMETER));
+ return lambdaRest(t.pos, ListBuffer.of(variableDeclaratorId(mods, exprOrType)));
+ }
+
+ // not a lambda, so it's a method call
+ ListBuffer<JCExpression> args = ListBuffer.of(exprOrType);
+ while (S.token() == COMMA) {
+ S.nextToken();
+ args.append(parseExpression());
+ }
+ accept(RPAREN);
+
+ return toP(F.at(applyPos).Apply(typeArgs, t, args.toList()));
+ }
+
+ accept(RPAREN);
+
+ switch(S.token()) {
+ case LPAREN: // lambda expression
+ return toP(F.at(applyPos).Lambda(List.<JCVariableDecl>nil(), lambdaExpression()));
+ case LBRACE: // lambda statement
+ return toP(F.at(applyPos).Lambda(List.<JCVariableDecl>nil(), block()));
+ default: // method call with no argument
+ return toP(F.at(applyPos).Apply(typeArgs, t, List.<JCExpression>nil()));
+ }
+ }
+
+ JCLambda lambdaRest(int pos, ListBuffer<JCVariableDecl> formals) {
+ if (S.token() != RPAREN) {
+ if (!formals.isEmpty()) {
+ accept(COMMA);
+ }
+
+ formals.append(lambdaFormalParameter());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ formals.append(lambdaFormalParameter());
+ }
+ }
+ accept(RPAREN);
+
+ if (S.token() == LBRACE) {
+ return toP(F.at(pos).Lambda(formals.toList(), block()));
+ } else {
+ return toP(F.at(pos).Lambda(formals.toList(), lambdaExpression()));
+ }
+ }
+
+ JCVariableDecl lambdaFormalParameter() {
+ JCModifiers mods = optFinal(Flags.PARAMETER);
+ JCExpression type = parseType();
+ return variableDeclaratorId(mods, type);
+ }
+
+ JCExpression lambdaExpression() {
+ accept(LPAREN);
+ JCExpression expr = parseExpression();
+ accept(RPAREN);
+ return expr;
+ }
+
+
/** TypeArgumentsOpt = [ TypeArguments ]
*/
JCExpression typeArgumentsOpt(JCExpression t) {
if (S.token() == LT &&
(mode & TYPE) != 0 &&
*** 3153,3158 ****
--- 3270,3287 ----
if (!allowTypeAnnotations) {
log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
allowTypeAnnotations = true;
}
}
+ void checkFunctionType() {
+ if (!allowFunctionType) {
+ log.error(S.pos(), "function.type.not.supported.in.source", source.name);
+ allowFunctionType = true;
+ }
+ }
+ void checkLambda() {
+ if (!allowLambda) {
+ log.error(S.pos(), "lambda.not.supported.in.source", source.name);
+ allowLambda = true;
+ }
+ }
}