25 |
25 |
26 package com.sun.tools.javac.parser; |
26 package com.sun.tools.javac.parser; |
27 |
27 |
28 import java.util.*; |
28 import java.util.*; |
29 |
29 |
|
30 import com.sun.source.tree.MemberReferenceTree.ReferenceMode; |
|
31 |
30 import com.sun.tools.javac.code.*; |
32 import com.sun.tools.javac.code.*; |
31 import com.sun.tools.javac.parser.Tokens.*; |
33 import com.sun.tools.javac.parser.Tokens.*; |
32 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; |
34 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; |
33 import com.sun.tools.javac.tree.*; |
35 import com.sun.tools.javac.tree.*; |
34 import com.sun.tools.javac.tree.JCTree.*; |
36 import com.sun.tools.javac.tree.JCTree.*; |
110 this.allowDiamond = source.allowDiamond(); |
112 this.allowDiamond = source.allowDiamond(); |
111 this.allowMulticatch = source.allowMulticatch(); |
113 this.allowMulticatch = source.allowMulticatch(); |
112 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); |
114 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); |
113 this.allowLambda = source.allowLambda() && |
115 this.allowLambda = source.allowLambda() && |
114 fac.options.isSet("allowLambda"); |
116 fac.options.isSet("allowLambda"); |
|
117 this.allowMethodReferences = source.allowMethodReferences() && |
|
118 fac.options.isSet("allowMethodReferences"); |
115 this.keepDocComments = keepDocComments; |
119 this.keepDocComments = keepDocComments; |
116 docComments = keepDocComments ? new HashMap<JCTree,String>() : null; |
120 docComments = keepDocComments ? new HashMap<JCTree,String>() : null; |
117 this.keepLineMap = keepLineMap; |
121 this.keepLineMap = keepLineMap; |
118 this.errorTree = F.Erroneous(); |
122 this.errorTree = F.Erroneous(); |
119 endPosTable = newEndPosTable(keepEndPositions); |
123 endPosTable = newEndPosTable(keepEndPositions); |
169 boolean allowStringFolding; |
173 boolean allowStringFolding; |
170 |
174 |
171 /** Switch: should we recognize lambda expressions? |
175 /** Switch: should we recognize lambda expressions? |
172 */ |
176 */ |
173 boolean allowLambda; |
177 boolean allowLambda; |
|
178 |
|
179 /** Switch: should we allow method/constructor references? |
|
180 */ |
|
181 boolean allowMethodReferences; |
174 |
182 |
175 /** Switch: should we keep docComments? |
183 /** Switch: should we keep docComments? |
176 */ |
184 */ |
177 boolean keepDocComments; |
185 boolean keepDocComments; |
178 |
186 |
777 while (prec(token.kind) >= minprec) { |
785 while (prec(token.kind) >= minprec) { |
778 opStack[top] = topOp; |
786 opStack[top] = topOp; |
779 top++; |
787 top++; |
780 topOp = token; |
788 topOp = token; |
781 nextToken(); |
789 nextToken(); |
782 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3(); |
790 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3NoParams(); |
783 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { |
791 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { |
784 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], |
792 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], |
785 odStack[top]); |
793 odStack[top]); |
786 top--; |
794 top--; |
787 topOp = opStack[top]; |
795 topOp = opStack[top]; |
880 * | [TypeArguments] SUPER SuperSuffix |
888 * | [TypeArguments] SUPER SuperSuffix |
881 * | NEW [TypeArguments] Creator |
889 * | NEW [TypeArguments] Creator |
882 * | "(" Arguments ")" "->" ( Expression | Block ) |
890 * | "(" Arguments ")" "->" ( Expression | Block ) |
883 * | Ident "->" ( Expression | Block ) |
891 * | Ident "->" ( Expression | Block ) |
884 * | Ident { "." Ident } |
892 * | Ident { "." Ident } |
|
893 * | Expression3 MemberReferenceSuffix |
885 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) |
894 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) |
886 * | Arguments |
895 * | Arguments |
887 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) |
896 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) |
888 * ] |
897 * ] |
889 * | BasicType BracketsOpt "." CLASS |
898 * | BasicType BracketsOpt "." CLASS |
920 (token.kind == INTLITERAL || token.kind == LONGLITERAL) && |
929 (token.kind == INTLITERAL || token.kind == LONGLITERAL) && |
921 token.radix() == 10) { |
930 token.radix() == 10) { |
922 mode = EXPR; |
931 mode = EXPR; |
923 t = literal(names.hyphen, pos); |
932 t = literal(names.hyphen, pos); |
924 } else { |
933 } else { |
925 t = term3(); |
934 t = term3NoParams(); |
926 return F.at(pos).Unary(unoptag(tk), t); |
935 return F.at(pos).Unary(unoptag(tk), t); |
927 } |
936 } |
928 } else return illegal(); |
937 } else return illegal(); |
929 break; |
938 break; |
930 case LPAREN: |
939 case LPAREN: |
936 //implicit n-ary lambda |
945 //implicit n-ary lambda |
937 t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos); |
946 t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos); |
938 break; |
947 break; |
939 } else { |
948 } else { |
940 nextToken(); |
949 nextToken(); |
941 mode = EXPR | TYPE | NOPARAMS; |
950 mode = EXPR | TYPE; |
942 t = term3(); |
951 t = term3NoParams(); |
943 if ((mode & TYPE) != 0 && token.kind == LT) { |
952 if ((mode & TYPE) != 0 && token.kind == LT) { |
944 // Could be a cast to a parameterized type |
953 // Could be a cast to a parameterized type |
945 JCTree.Tag op = JCTree.Tag.LT; |
954 JCTree.Tag op = JCTree.Tag.LT; |
946 int pos1 = token.pos; |
955 int pos1 = token.pos; |
947 nextToken(); |
956 nextToken(); |
1000 |
1009 |
1001 accept(RPAREN); |
1010 accept(RPAREN); |
1002 lastmode = mode; |
1011 lastmode = mode; |
1003 mode = EXPR; |
1012 mode = EXPR; |
1004 if ((lastmode & EXPR) == 0) { |
1013 if ((lastmode & EXPR) == 0) { |
1005 JCExpression t1 = term3(); |
1014 JCExpression t1 = term3NoParams(); |
1006 return F.at(pos).TypeCast(t, t1); |
1015 return F.at(pos).TypeCast(t, t1); |
1007 } else if ((lastmode & TYPE) != 0) { |
1016 } else if ((lastmode & TYPE) != 0) { |
1008 switch (token.kind) { |
1017 switch (token.kind) { |
1009 /*case PLUSPLUS: case SUBSUB: */ |
1018 /*case PLUSPLUS: case SUBSUB: */ |
1010 case BANG: case TILDE: |
1019 case BANG: case TILDE: |
1013 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: |
1022 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: |
1014 case TRUE: case FALSE: case NULL: |
1023 case TRUE: case FALSE: case NULL: |
1015 case NEW: case IDENTIFIER: case ASSERT: case ENUM: |
1024 case NEW: case IDENTIFIER: case ASSERT: case ENUM: |
1016 case BYTE: case SHORT: case CHAR: case INT: |
1025 case BYTE: case SHORT: case CHAR: case INT: |
1017 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: |
1026 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: |
1018 JCExpression t1 = term3(); |
1027 JCExpression t1 = term3NoParams(); |
1019 return F.at(pos).TypeCast(t, t1); |
1028 return F.at(pos).TypeCast(t, t1); |
1020 } |
1029 } |
1021 } |
1030 } |
1022 } else { |
1031 } else { |
1023 return illegal(); |
1032 return illegal(); |
1132 } |
1141 } |
1133 } |
1142 } |
1134 // typeArgs saved for next loop iteration. |
1143 // typeArgs saved for next loop iteration. |
1135 t = toP(F.at(pos).Select(t, ident())); |
1144 t = toP(F.at(pos).Select(t, ident())); |
1136 break; |
1145 break; |
|
1146 case LT: |
|
1147 if ((mode & (TYPE | NOPARAMS)) == 0) { |
|
1148 //could be an unbound method reference whose qualifier |
|
1149 //is a generic type i.e. A<S>#m |
|
1150 mode = EXPR | TYPE; |
|
1151 JCTree.Tag op = JCTree.Tag.LT; |
|
1152 int pos1 = token.pos; |
|
1153 nextToken(); |
|
1154 mode |= EXPR | TYPE | TYPEARG; |
|
1155 JCExpression t1 = term3(); |
|
1156 if ((mode & TYPE) != 0 && |
|
1157 (token.kind == COMMA || token.kind == GT)) { |
|
1158 mode = TYPE; |
|
1159 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); |
|
1160 args.append(t1); |
|
1161 while (token.kind == COMMA) { |
|
1162 nextToken(); |
|
1163 args.append(typeArgument()); |
|
1164 } |
|
1165 accept(GT); |
|
1166 t = toP(F.at(pos1).TypeApply(t, args.toList())); |
|
1167 checkGenerics(); |
|
1168 while (token.kind == DOT) { |
|
1169 nextToken(); |
|
1170 mode = TYPE; |
|
1171 t = toP(F.at(token.pos).Select(t, ident())); |
|
1172 t = typeArgumentsOpt(t); |
|
1173 } |
|
1174 if (token.kind != HASH) { |
|
1175 //method reference expected here |
|
1176 t = illegal(); |
|
1177 } |
|
1178 mode = EXPR; |
|
1179 break; |
|
1180 } else if ((mode & EXPR) != 0) { |
|
1181 //rollback - it was a binary expression |
|
1182 mode = EXPR; |
|
1183 JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); |
|
1184 t = F.at(pos1).Binary(op, t, e); |
|
1185 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); |
|
1186 } |
|
1187 } |
|
1188 break loop; |
1137 default: |
1189 default: |
1138 break loop; |
1190 break loop; |
1139 } |
1191 } |
1140 } |
1192 } |
1141 } |
1193 } |
1216 } else { |
1277 } else { |
1217 t = toP(F.at(pos1).Select(t, ident())); |
1278 t = toP(F.at(pos1).Select(t, ident())); |
1218 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); |
1279 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); |
1219 typeArgs = null; |
1280 typeArgs = null; |
1220 } |
1281 } |
|
1282 } else if ((mode & EXPR) != 0 && token.kind == HASH) { |
|
1283 mode = EXPR; |
|
1284 if (typeArgs != null) return illegal(); |
|
1285 accept(HASH); |
|
1286 t = memberReferenceSuffix(pos1, t); |
1221 } else { |
1287 } else { |
1222 break; |
1288 break; |
1223 } |
1289 } |
1224 } |
1290 } |
1225 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { |
1291 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { |
1279 */ |
1345 */ |
1280 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { |
1346 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { |
1281 nextToken(); |
1347 nextToken(); |
1282 if (token.kind == LPAREN || typeArgs != null) { |
1348 if (token.kind == LPAREN || typeArgs != null) { |
1283 t = arguments(typeArgs, t); |
1349 t = arguments(typeArgs, t); |
|
1350 } else if (token.kind == HASH) { |
|
1351 if (typeArgs != null) return illegal(); |
|
1352 t = memberReferenceSuffix(t); |
1284 } else { |
1353 } else { |
1285 int pos = token.pos; |
1354 int pos = token.pos; |
1286 accept(DOT); |
1355 accept(DOT); |
1287 typeArgs = (token.kind == LT) ? typeArguments(false) : null; |
1356 typeArgs = (token.kind == LT) ? typeArguments(false) : null; |
1288 t = toP(F.at(pos).Select(t, ident())); |
1357 t = toP(F.at(pos).Select(t, ident())); |
1486 mode = TYPE; |
1555 mode = TYPE; |
1487 } else { |
1556 } else { |
1488 syntaxError(token.pos, "dot.class.expected"); |
1557 syntaxError(token.pos, "dot.class.expected"); |
1489 } |
1558 } |
1490 return t; |
1559 return t; |
|
1560 } |
|
1561 |
|
1562 /** |
|
1563 * MemberReferenceSuffix = "#" [TypeArguments] Ident |
|
1564 * | "#" [TypeArguments] "new" |
|
1565 */ |
|
1566 JCExpression memberReferenceSuffix(JCExpression t) { |
|
1567 int pos1 = token.pos; |
|
1568 accept(HASH); |
|
1569 return memberReferenceSuffix(pos1, t); |
|
1570 } |
|
1571 |
|
1572 JCExpression memberReferenceSuffix(int pos1, JCExpression t) { |
|
1573 checkMethodReferences(); |
|
1574 mode = EXPR; |
|
1575 List<JCExpression> typeArgs = null; |
|
1576 if (token.kind == LT) { |
|
1577 typeArgs = typeArguments(false); |
|
1578 } |
|
1579 Name refName = null; |
|
1580 ReferenceMode refMode = null; |
|
1581 if (token.kind == NEW) { |
|
1582 refMode = ReferenceMode.NEW; |
|
1583 refName = names.init; |
|
1584 nextToken(); |
|
1585 } else { |
|
1586 refMode = ReferenceMode.INVOKE; |
|
1587 refName = ident(); |
|
1588 } |
|
1589 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); |
1491 } |
1590 } |
1492 |
1591 |
1493 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) |
1592 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) |
1494 */ |
1593 */ |
1495 JCExpression creator(int newpos, List<JCExpression> typeArgs) { |
1594 JCExpression creator(int newpos, List<JCExpression> typeArgs) { |
3164 if (!allowLambda) { |
3263 if (!allowLambda) { |
3165 log.error(token.pos, "lambda.not.supported.in.source", source.name); |
3264 log.error(token.pos, "lambda.not.supported.in.source", source.name); |
3166 allowLambda = true; |
3265 allowLambda = true; |
3167 } |
3266 } |
3168 } |
3267 } |
|
3268 void checkMethodReferences() { |
|
3269 if (!allowMethodReferences) { |
|
3270 log.error(token.pos, "method.references.not.supported.in.source", source.name); |
|
3271 allowMethodReferences = true; |
|
3272 } |
|
3273 } |
3169 |
3274 |
3170 /* |
3275 /* |
3171 * a functional source tree and end position mappings |
3276 * a functional source tree and end position mappings |
3172 */ |
3277 */ |
3173 protected class SimpleEndPosTable extends AbstractEndPosTable { |
3278 protected class SimpleEndPosTable extends AbstractEndPosTable { |