--- old/src/share/classes/com/sun/tools/javac/parser/JavacParser.java 2009-12-27 19:02:20.000000000 +0100 +++ new/src/share/classes/com/sun/tools/javac/parser/JavacParser.java 2009-12-27 19:02:20.000000000 +0100 @@ -133,6 +133,8 @@ 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(); @@ -169,7 +171,7 @@ */ boolean allowForeach; - /** Switch: should we recognize foreach? + /** Switch: should we recognize static import? */ boolean allowStaticImport; @@ -180,6 +182,14 @@ /** 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? */ @@ -880,6 +890,7 @@ * PostfixOp = "++" | "--" * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt * | BasicType + * | FunctionType * TypeNoParams3 = Ident { "." Ident } BracketsOpt * Selector = "." [TypeArguments] Ident [Arguments] * | "." THIS @@ -975,7 +986,8 @@ 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 LONG: case FLOAT: case DOUBLE: case BOOLEAN: + case VOID: case SHARP: JCExpression t1 = term3(); return F.at(pos).TypeCast(t, t1); } @@ -1049,6 +1061,14 @@ 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())); @@ -1084,7 +1104,7 @@ case LPAREN: if ((mode & EXPR) != 0) { mode = EXPR; - t = arguments(typeArgs, t); + t = argumentsOrLambda(typeArgs, t); typeArgs = null; } break loop; @@ -1258,6 +1278,20 @@ S.nextToken(); return t; } + + /** FunctionType = "#" Type "(" [Type { "," Type}] ")" + */ + JCExpression functionType() { + checkFunctionType(); + int pos = S.pos(); + S.nextToken(); + JCExpression returnType = parseType(); + accept(LPAREN); + List parameterTypes = (S.token() != RPAREN)? typeList(): List.nil(); + accept(RPAREN); + JCFunctionType t = to(F.at(S.pos()).FunctionType(parameterTypes, returnType)); + return t; + } /** ArgumentsOpt = [ Arguments ] */ @@ -1295,7 +1329,90 @@ List args = arguments(); return toP(F.at(pos).Apply(typeArgs, t, args)); } + + JCExpression argumentsOrLambda(List 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.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 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.nil(), lambdaExpression())); + case LBRACE: // lambda statement + return toP(F.at(applyPos).Lambda(List.nil(), block())); + default: // method call with no argument + return toP(F.at(applyPos).Apply(typeArgs, t, List.nil())); + } + } + + JCLambda lambdaRest(int pos, ListBuffer 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) { @@ -3155,4 +3272,16 @@ 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; + } + } }