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