Fri, 30 Nov 2012 15:14:36 +0000
8004101: Add checks for method reference well-formedness
Summary: Bring method reference type-checking in sync with latest EDR
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.parser;
28 import java.util.*;
30 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
32 import com.sun.tools.javac.code.*;
33 import com.sun.tools.javac.parser.Tokens.*;
34 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
35 import com.sun.tools.javac.tree.*;
36 import com.sun.tools.javac.tree.JCTree.*;
37 import com.sun.tools.javac.util.*;
38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
40 import com.sun.tools.javac.util.List;
42 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
43 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
44 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
45 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
46 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
47 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
48 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
49 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
50 import static com.sun.tools.javac.tree.JCTree.Tag.*;
51 import static com.sun.tools.javac.util.ListBuffer.lb;
53 /** The parser maps a token sequence into an abstract syntax
54 * tree. It operates by recursive descent, with code derived
55 * systematically from an LL(1) grammar. For efficiency reasons, an
56 * operator precedence scheme is used for parsing binary operation
57 * expressions.
58 *
59 * <p><b>This is NOT part of any supported API.
60 * If you write code that depends on this, you do so at your own risk.
61 * This code and its internal interfaces are subject to change or
62 * deletion without notice.</b>
63 */
64 public class JavacParser implements Parser {
66 /** The number of precedence levels of infix operators.
67 */
68 private static final int infixPrecedenceLevels = 10;
70 /** The scanner used for lexical analysis.
71 */
72 protected Lexer S;
74 /** The factory to be used for abstract syntax tree construction.
75 */
76 protected TreeMaker F;
78 /** The log to be used for error diagnostics.
79 */
80 private Log log;
82 /** The Source language setting. */
83 private Source source;
85 /** The name table. */
86 private Names names;
88 /** End position mappings container */
89 private final AbstractEndPosTable endPosTable;
91 interface ErrorRecoveryAction {
92 JCTree doRecover(JavacParser parser);
93 }
95 enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
96 BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
97 CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
98 }
100 /** Construct a parser from a given scanner, tree factory and log.
101 */
102 protected JavacParser(ParserFactory fac,
103 Lexer S,
104 boolean keepDocComments,
105 boolean keepLineMap,
106 boolean keepEndPositions) {
107 this.S = S;
108 nextToken(); // prime the pump
109 this.F = fac.F;
110 this.log = fac.log;
111 this.names = fac.names;
112 this.source = fac.source;
113 this.allowGenerics = source.allowGenerics();
114 this.allowVarargs = source.allowVarargs();
115 this.allowAsserts = source.allowAsserts();
116 this.allowEnums = source.allowEnums();
117 this.allowForeach = source.allowForeach();
118 this.allowStaticImport = source.allowStaticImport();
119 this.allowAnnotations = source.allowAnnotations();
120 this.allowTWR = source.allowTryWithResources();
121 this.allowDiamond = source.allowDiamond();
122 this.allowMulticatch = source.allowMulticatch();
123 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
124 this.allowLambda = source.allowLambda();
125 this.allowMethodReferences = source.allowMethodReferences();
126 this.allowDefaultMethods = source.allowDefaultMethods();
127 this.keepDocComments = keepDocComments;
128 docComments = newDocCommentTable(keepDocComments, fac);
129 this.keepLineMap = keepLineMap;
130 this.errorTree = F.Erroneous();
131 endPosTable = newEndPosTable(keepEndPositions);
132 }
134 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
135 return keepEndPositions
136 ? new SimpleEndPosTable()
137 : new EmptyEndPosTable();
138 }
140 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
141 return keepDocComments ? new LazyDocCommentTable(fac) : null;
142 }
144 /** Switch: Should generics be recognized?
145 */
146 boolean allowGenerics;
148 /** Switch: Should diamond operator be recognized?
149 */
150 boolean allowDiamond;
152 /** Switch: Should multicatch clause be accepted?
153 */
154 boolean allowMulticatch;
156 /** Switch: Should varargs be recognized?
157 */
158 boolean allowVarargs;
160 /** Switch: should we recognize assert statements, or just give a warning?
161 */
162 boolean allowAsserts;
164 /** Switch: should we recognize enums, or just give a warning?
165 */
166 boolean allowEnums;
168 /** Switch: should we recognize foreach?
169 */
170 boolean allowForeach;
172 /** Switch: should we recognize foreach?
173 */
174 boolean allowStaticImport;
176 /** Switch: should we recognize annotations?
177 */
178 boolean allowAnnotations;
180 /** Switch: should we recognize try-with-resources?
181 */
182 boolean allowTWR;
184 /** Switch: should we fold strings?
185 */
186 boolean allowStringFolding;
188 /** Switch: should we recognize lambda expressions?
189 */
190 boolean allowLambda;
192 /** Switch: should we allow method/constructor references?
193 */
194 boolean allowMethodReferences;
196 /** Switch: should we allow default methods in interfaces?
197 */
198 boolean allowDefaultMethods;
200 /** Switch: should we keep docComments?
201 */
202 boolean keepDocComments;
204 /** Switch: should we keep line table?
205 */
206 boolean keepLineMap;
208 /** When terms are parsed, the mode determines which is expected:
209 * mode = EXPR : an expression
210 * mode = TYPE : a type
211 * mode = NOPARAMS : no parameters allowed for type
212 * mode = TYPEARG : type argument
213 */
214 static final int EXPR = 0x1;
215 static final int TYPE = 0x2;
216 static final int NOPARAMS = 0x4;
217 static final int TYPEARG = 0x8;
218 static final int DIAMOND = 0x10;
220 /** The current mode.
221 */
222 private int mode = 0;
224 /** The mode of the term that was parsed last.
225 */
226 private int lastmode = 0;
228 /* ---------- token management -------------- */
230 protected Token token;
232 public Token token() {
233 return token;
234 }
236 public void nextToken() {
237 S.nextToken();
238 token = S.token();
239 }
241 protected boolean peekToken(TokenKind tk) {
242 return S.token(1).kind == tk;
243 }
245 protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
246 return S.token(1).kind == tk1 &&
247 S.token(2).kind == tk2;
248 }
250 protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
251 return S.token(1).kind == tk1 &&
252 S.token(2).kind == tk2 &&
253 S.token(3).kind == tk3;
254 }
256 protected boolean peekToken(TokenKind... kinds) {
257 for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) {
258 if (S.token(lookahead + 1).kind != kinds[lookahead]) {
259 return false;
260 }
261 }
262 return true;
263 }
265 /* ---------- error recovery -------------- */
267 private JCErroneous errorTree;
269 /** Skip forward until a suitable stop token is found.
270 */
271 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
272 while (true) {
273 switch (token.kind) {
274 case SEMI:
275 nextToken();
276 return;
277 case PUBLIC:
278 case FINAL:
279 case ABSTRACT:
280 case MONKEYS_AT:
281 case EOF:
282 case CLASS:
283 case INTERFACE:
284 case ENUM:
285 return;
286 case IMPORT:
287 if (stopAtImport)
288 return;
289 break;
290 case LBRACE:
291 case RBRACE:
292 case PRIVATE:
293 case PROTECTED:
294 case STATIC:
295 case TRANSIENT:
296 case NATIVE:
297 case VOLATILE:
298 case SYNCHRONIZED:
299 case STRICTFP:
300 case LT:
301 case BYTE:
302 case SHORT:
303 case CHAR:
304 case INT:
305 case LONG:
306 case FLOAT:
307 case DOUBLE:
308 case BOOLEAN:
309 case VOID:
310 if (stopAtMemberDecl)
311 return;
312 break;
313 case IDENTIFIER:
314 if (stopAtIdentifier)
315 return;
316 break;
317 case CASE:
318 case DEFAULT:
319 case IF:
320 case FOR:
321 case WHILE:
322 case DO:
323 case TRY:
324 case SWITCH:
325 case RETURN:
326 case THROW:
327 case BREAK:
328 case CONTINUE:
329 case ELSE:
330 case FINALLY:
331 case CATCH:
332 if (stopAtStatement)
333 return;
334 break;
335 }
336 nextToken();
337 }
338 }
340 private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
341 return syntaxError(pos, List.<JCTree>nil(), key, args);
342 }
344 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
345 setErrorEndPos(pos);
346 JCErroneous err = F.at(pos).Erroneous(errs);
347 reportSyntaxError(err, key, (Object[])args);
348 if (errs != null) {
349 JCTree last = errs.last();
350 if (last != null)
351 storeEnd(last, pos);
352 }
353 return toP(err);
354 }
356 private int errorPos = Position.NOPOS;
358 /**
359 * Report a syntax using the given the position parameter and arguments,
360 * unless one was already reported at the same position.
361 */
362 private void reportSyntaxError(int pos, String key, Object... args) {
363 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
364 reportSyntaxError(diag, key, args);
365 }
367 /**
368 * Report a syntax error using the given DiagnosticPosition object and
369 * arguments, unless one was already reported at the same position.
370 */
371 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
372 int pos = diagPos.getPreferredPosition();
373 if (pos > S.errPos() || pos == Position.NOPOS) {
374 if (token.kind == EOF) {
375 error(diagPos, "premature.eof");
376 } else {
377 error(diagPos, key, args);
378 }
379 }
380 S.errPos(pos);
381 if (token.pos == errorPos)
382 nextToken(); // guarantee progress
383 errorPos = token.pos;
384 }
387 /** Generate a syntax error at current position unless one was already
388 * reported at the same position.
389 */
390 private JCErroneous syntaxError(String key) {
391 return syntaxError(token.pos, key);
392 }
394 /** Generate a syntax error at current position unless one was
395 * already reported at the same position.
396 */
397 private JCErroneous syntaxError(String key, TokenKind arg) {
398 return syntaxError(token.pos, key, arg);
399 }
401 /** If next input token matches given token, skip it, otherwise report
402 * an error.
403 */
404 public void accept(TokenKind tk) {
405 if (token.kind == tk) {
406 nextToken();
407 } else {
408 setErrorEndPos(token.pos);
409 reportSyntaxError(S.prevToken().endPos, "expected", tk);
410 }
411 }
413 /** Report an illegal start of expression/type error at given position.
414 */
415 JCExpression illegal(int pos) {
416 setErrorEndPos(pos);
417 if ((mode & EXPR) != 0)
418 return syntaxError(pos, "illegal.start.of.expr");
419 else
420 return syntaxError(pos, "illegal.start.of.type");
422 }
424 /** Report an illegal start of expression/type error at current position.
425 */
426 JCExpression illegal() {
427 return illegal(token.pos);
428 }
430 /** Diagnose a modifier flag from the set, if any. */
431 void checkNoMods(long mods) {
432 if (mods != 0) {
433 long lowestMod = mods & -mods;
434 error(token.pos, "mod.not.allowed.here",
435 Flags.asFlagSet(lowestMod));
436 }
437 }
439 /* ---------- doc comments --------- */
441 /** A table to store all documentation comments
442 * indexed by the tree nodes they refer to.
443 * defined only if option flag keepDocComment is set.
444 */
445 private final DocCommentTable docComments;
447 /** Make an entry into docComments hashtable,
448 * provided flag keepDocComments is set and given doc comment is non-null.
449 * @param tree The tree to be used as index in the hashtable
450 * @param dc The doc comment to associate with the tree, or null.
451 */
452 void attach(JCTree tree, Comment dc) {
453 if (keepDocComments && dc != null) {
454 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
455 docComments.putComment(tree, dc);
456 }
457 }
459 /* -------- source positions ------- */
461 private void setErrorEndPos(int errPos) {
462 endPosTable.setErrorEndPos(errPos);
463 }
465 private void storeEnd(JCTree tree, int endpos) {
466 endPosTable.storeEnd(tree, endpos);
467 }
469 private <T extends JCTree> T to(T t) {
470 return endPosTable.to(t);
471 }
473 private <T extends JCTree> T toP(T t) {
474 return endPosTable.toP(t);
475 }
477 /** Get the start position for a tree node. The start position is
478 * defined to be the position of the first character of the first
479 * token of the node's source text.
480 * @param tree The tree node
481 */
482 public int getStartPos(JCTree tree) {
483 return TreeInfo.getStartPos(tree);
484 }
486 /**
487 * Get the end position for a tree node. The end position is
488 * defined to be the position of the last character of the last
489 * token of the node's source text. Returns Position.NOPOS if end
490 * positions are not generated or the position is otherwise not
491 * found.
492 * @param tree The tree node
493 */
494 public int getEndPos(JCTree tree) {
495 return endPosTable.getEndPos(tree);
496 }
500 /* ---------- parsing -------------- */
502 /**
503 * Ident = IDENTIFIER
504 */
505 Name ident() {
506 if (token.kind == IDENTIFIER) {
507 Name name = token.name();
508 nextToken();
509 return name;
510 } else if (token.kind == ASSERT) {
511 if (allowAsserts) {
512 error(token.pos, "assert.as.identifier");
513 nextToken();
514 return names.error;
515 } else {
516 warning(token.pos, "assert.as.identifier");
517 Name name = token.name();
518 nextToken();
519 return name;
520 }
521 } else if (token.kind == ENUM) {
522 if (allowEnums) {
523 error(token.pos, "enum.as.identifier");
524 nextToken();
525 return names.error;
526 } else {
527 warning(token.pos, "enum.as.identifier");
528 Name name = token.name();
529 nextToken();
530 return name;
531 }
532 } else {
533 accept(IDENTIFIER);
534 return names.error;
535 }
536 }
538 /**
539 * Qualident = Ident { DOT Ident }
540 */
541 public JCExpression qualident() {
542 JCExpression t = toP(F.at(token.pos).Ident(ident()));
543 while (token.kind == DOT) {
544 int pos = token.pos;
545 nextToken();
546 t = toP(F.at(pos).Select(t, ident()));
547 }
548 return t;
549 }
551 JCExpression literal(Name prefix) {
552 return literal(prefix, token.pos);
553 }
555 /**
556 * Literal =
557 * INTLITERAL
558 * | LONGLITERAL
559 * | FLOATLITERAL
560 * | DOUBLELITERAL
561 * | CHARLITERAL
562 * | STRINGLITERAL
563 * | TRUE
564 * | FALSE
565 * | NULL
566 */
567 JCExpression literal(Name prefix, int pos) {
568 JCExpression t = errorTree;
569 switch (token.kind) {
570 case INTLITERAL:
571 try {
572 t = F.at(pos).Literal(
573 TypeTag.INT,
574 Convert.string2int(strval(prefix), token.radix()));
575 } catch (NumberFormatException ex) {
576 error(token.pos, "int.number.too.large", strval(prefix));
577 }
578 break;
579 case LONGLITERAL:
580 try {
581 t = F.at(pos).Literal(
582 TypeTag.LONG,
583 new Long(Convert.string2long(strval(prefix), token.radix())));
584 } catch (NumberFormatException ex) {
585 error(token.pos, "int.number.too.large", strval(prefix));
586 }
587 break;
588 case FLOATLITERAL: {
589 String proper = token.radix() == 16 ?
590 ("0x"+ token.stringVal()) :
591 token.stringVal();
592 Float n;
593 try {
594 n = Float.valueOf(proper);
595 } catch (NumberFormatException ex) {
596 // error already reported in scanner
597 n = Float.NaN;
598 }
599 if (n.floatValue() == 0.0f && !isZero(proper))
600 error(token.pos, "fp.number.too.small");
601 else if (n.floatValue() == Float.POSITIVE_INFINITY)
602 error(token.pos, "fp.number.too.large");
603 else
604 t = F.at(pos).Literal(TypeTag.FLOAT, n);
605 break;
606 }
607 case DOUBLELITERAL: {
608 String proper = token.radix() == 16 ?
609 ("0x"+ token.stringVal()) :
610 token.stringVal();
611 Double n;
612 try {
613 n = Double.valueOf(proper);
614 } catch (NumberFormatException ex) {
615 // error already reported in scanner
616 n = Double.NaN;
617 }
618 if (n.doubleValue() == 0.0d && !isZero(proper))
619 error(token.pos, "fp.number.too.small");
620 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
621 error(token.pos, "fp.number.too.large");
622 else
623 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
624 break;
625 }
626 case CHARLITERAL:
627 t = F.at(pos).Literal(
628 TypeTag.CHAR,
629 token.stringVal().charAt(0) + 0);
630 break;
631 case STRINGLITERAL:
632 t = F.at(pos).Literal(
633 TypeTag.CLASS,
634 token.stringVal());
635 break;
636 case TRUE: case FALSE:
637 t = F.at(pos).Literal(
638 TypeTag.BOOLEAN,
639 (token.kind == TRUE ? 1 : 0));
640 break;
641 case NULL:
642 t = F.at(pos).Literal(
643 TypeTag.BOT,
644 null);
645 break;
646 default:
647 Assert.error();
648 }
649 if (t == errorTree)
650 t = F.at(pos).Erroneous();
651 storeEnd(t, token.endPos);
652 nextToken();
653 return t;
654 }
655 //where
656 boolean isZero(String s) {
657 char[] cs = s.toCharArray();
658 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
659 int i = ((base==16) ? 2 : 0);
660 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
661 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
662 }
664 String strval(Name prefix) {
665 String s = token.stringVal();
666 return prefix.isEmpty() ? s : prefix + s;
667 }
669 /** terms can be either expressions or types.
670 */
671 public JCExpression parseExpression() {
672 return term(EXPR);
673 }
675 public JCExpression parseType() {
676 return term(TYPE);
677 }
679 JCExpression term(int newmode) {
680 int prevmode = mode;
681 mode = newmode;
682 JCExpression t = term();
683 lastmode = mode;
684 mode = prevmode;
685 return t;
686 }
688 /**
689 * {@literal
690 * Expression = Expression1 [ExpressionRest]
691 * ExpressionRest = [AssignmentOperator Expression1]
692 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
693 * "&=" | "|=" | "^=" |
694 * "%=" | "<<=" | ">>=" | ">>>="
695 * Type = Type1
696 * TypeNoParams = TypeNoParams1
697 * StatementExpression = Expression
698 * ConstantExpression = Expression
699 * }
700 */
701 JCExpression term() {
702 JCExpression t = term1();
703 if ((mode & EXPR) != 0 &&
704 token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
705 return termRest(t);
706 else
707 return t;
708 }
710 JCExpression termRest(JCExpression t) {
711 switch (token.kind) {
712 case EQ: {
713 int pos = token.pos;
714 nextToken();
715 mode = EXPR;
716 JCExpression t1 = term();
717 return toP(F.at(pos).Assign(t, t1));
718 }
719 case PLUSEQ:
720 case SUBEQ:
721 case STAREQ:
722 case SLASHEQ:
723 case PERCENTEQ:
724 case AMPEQ:
725 case BAREQ:
726 case CARETEQ:
727 case LTLTEQ:
728 case GTGTEQ:
729 case GTGTGTEQ:
730 int pos = token.pos;
731 TokenKind tk = token.kind;
732 nextToken();
733 mode = EXPR;
734 JCExpression t1 = term();
735 return F.at(pos).Assignop(optag(tk), t, t1);
736 default:
737 return t;
738 }
739 }
741 /** Expression1 = Expression2 [Expression1Rest]
742 * Type1 = Type2
743 * TypeNoParams1 = TypeNoParams2
744 */
745 JCExpression term1() {
746 JCExpression t = term2();
747 if ((mode & EXPR) != 0 && token.kind == QUES) {
748 mode = EXPR;
749 return term1Rest(t);
750 } else {
751 return t;
752 }
753 }
755 /** Expression1Rest = ["?" Expression ":" Expression1]
756 */
757 JCExpression term1Rest(JCExpression t) {
758 if (token.kind == QUES) {
759 int pos = token.pos;
760 nextToken();
761 JCExpression t1 = term();
762 accept(COLON);
763 JCExpression t2 = term1();
764 return F.at(pos).Conditional(t, t1, t2);
765 } else {
766 return t;
767 }
768 }
770 /** Expression2 = Expression3 [Expression2Rest]
771 * Type2 = Type3
772 * TypeNoParams2 = TypeNoParams3
773 */
774 JCExpression term2() {
775 JCExpression t = term3();
776 if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
777 mode = EXPR;
778 return term2Rest(t, TreeInfo.orPrec);
779 } else {
780 return t;
781 }
782 }
784 /* Expression2Rest = {infixop Expression3}
785 * | Expression3 instanceof Type
786 * infixop = "||"
787 * | "&&"
788 * | "|"
789 * | "^"
790 * | "&"
791 * | "==" | "!="
792 * | "<" | ">" | "<=" | ">="
793 * | "<<" | ">>" | ">>>"
794 * | "+" | "-"
795 * | "*" | "/" | "%"
796 */
797 JCExpression term2Rest(JCExpression t, int minprec) {
798 List<JCExpression[]> savedOd = odStackSupply.elems;
799 JCExpression[] odStack = newOdStack();
800 List<Token[]> savedOp = opStackSupply.elems;
801 Token[] opStack = newOpStack();
803 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
804 int top = 0;
805 odStack[0] = t;
806 int startPos = token.pos;
807 Token topOp = Tokens.DUMMY;
808 while (prec(token.kind) >= minprec) {
809 opStack[top] = topOp;
810 top++;
811 topOp = token;
812 nextToken();
813 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
814 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
815 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
816 odStack[top]);
817 top--;
818 topOp = opStack[top];
819 }
820 }
821 Assert.check(top == 0);
822 t = odStack[0];
824 if (t.hasTag(JCTree.Tag.PLUS)) {
825 StringBuilder buf = foldStrings(t);
826 if (buf != null) {
827 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
828 }
829 }
831 odStackSupply.elems = savedOd; // optimization
832 opStackSupply.elems = savedOp; // optimization
833 return t;
834 }
835 //where
836 /** Construct a binary or type test node.
837 */
838 private JCExpression makeOp(int pos,
839 TokenKind topOp,
840 JCExpression od1,
841 JCExpression od2)
842 {
843 if (topOp == INSTANCEOF) {
844 return F.at(pos).TypeTest(od1, od2);
845 } else {
846 return F.at(pos).Binary(optag(topOp), od1, od2);
847 }
848 }
849 /** If tree is a concatenation of string literals, replace it
850 * by a single literal representing the concatenated string.
851 */
852 protected StringBuilder foldStrings(JCTree tree) {
853 if (!allowStringFolding)
854 return null;
855 List<String> buf = List.nil();
856 while (true) {
857 if (tree.hasTag(LITERAL)) {
858 JCLiteral lit = (JCLiteral) tree;
859 if (lit.typetag == TypeTag.CLASS) {
860 StringBuilder sbuf =
861 new StringBuilder((String)lit.value);
862 while (buf.nonEmpty()) {
863 sbuf.append(buf.head);
864 buf = buf.tail;
865 }
866 return sbuf;
867 }
868 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
869 JCBinary op = (JCBinary)tree;
870 if (op.rhs.hasTag(LITERAL)) {
871 JCLiteral lit = (JCLiteral) op.rhs;
872 if (lit.typetag == TypeTag.CLASS) {
873 buf = buf.prepend((String) lit.value);
874 tree = op.lhs;
875 continue;
876 }
877 }
878 }
879 return null;
880 }
881 }
883 /** optimization: To save allocating a new operand/operator stack
884 * for every binary operation, we use supplys.
885 */
886 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
887 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
889 private JCExpression[] newOdStack() {
890 if (odStackSupply.elems == odStackSupply.last)
891 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
892 JCExpression[] odStack = odStackSupply.elems.head;
893 odStackSupply.elems = odStackSupply.elems.tail;
894 return odStack;
895 }
897 private Token[] newOpStack() {
898 if (opStackSupply.elems == opStackSupply.last)
899 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
900 Token[] opStack = opStackSupply.elems.head;
901 opStackSupply.elems = opStackSupply.elems.tail;
902 return opStack;
903 }
905 /**
906 * Expression3 = PrefixOp Expression3
907 * | "(" Expr | TypeNoParams ")" Expression3
908 * | Primary {Selector} {PostfixOp}
909 *
910 * {@literal
911 * Primary = "(" Expression ")"
912 * | Literal
913 * | [TypeArguments] THIS [Arguments]
914 * | [TypeArguments] SUPER SuperSuffix
915 * | NEW [TypeArguments] Creator
916 * | "(" Arguments ")" "->" ( Expression | Block )
917 * | Ident "->" ( Expression | Block )
918 * | Ident { "." Ident }
919 * | Expression3 MemberReferenceSuffix
920 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
921 * | Arguments
922 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
923 * ]
924 * | BasicType BracketsOpt "." CLASS
925 * }
926 *
927 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
928 * PostfixOp = "++" | "--"
929 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
930 * | BasicType
931 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
932 * Selector = "." [TypeArguments] Ident [Arguments]
933 * | "." THIS
934 * | "." [TypeArguments] SUPER SuperSuffix
935 * | "." NEW [TypeArguments] InnerCreator
936 * | "[" Expression "]"
937 * TypeSelector = "." Ident [TypeArguments]
938 * SuperSuffix = Arguments | "." Ident [Arguments]
939 */
940 protected JCExpression term3() {
941 int pos = token.pos;
942 JCExpression t;
943 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
944 switch (token.kind) {
945 case QUES:
946 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
947 mode = TYPE;
948 return typeArgument();
949 } else
950 return illegal();
951 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
952 if (typeArgs == null && (mode & EXPR) != 0) {
953 TokenKind tk = token.kind;
954 nextToken();
955 mode = EXPR;
956 if (tk == SUB &&
957 (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
958 token.radix() == 10) {
959 mode = EXPR;
960 t = literal(names.hyphen, pos);
961 } else {
962 t = term3();
963 return F.at(pos).Unary(unoptag(tk), t);
964 }
965 } else return illegal();
966 break;
967 case LPAREN:
968 if (typeArgs == null && (mode & EXPR) != 0) {
969 if (peekToken(MONKEYS_AT) ||
970 peekToken(FINAL) ||
971 peekToken(RPAREN) ||
972 peekToken(IDENTIFIER, COMMA) ||
973 peekToken(IDENTIFIER, RPAREN, ARROW)) {
974 //implicit n-ary lambda
975 t = lambdaExpressionOrStatement(true, peekToken(MONKEYS_AT) || peekToken(FINAL), pos);
976 break;
977 } else {
978 nextToken();
979 mode = EXPR | TYPE | NOPARAMS;
980 t = term3();
981 if ((mode & TYPE) != 0 && token.kind == LT) {
982 // Could be a cast to a parameterized type
983 JCTree.Tag op = JCTree.Tag.LT;
984 int pos1 = token.pos;
985 nextToken();
986 mode &= (EXPR | TYPE);
987 mode |= TYPEARG;
988 JCExpression t1 = term3();
989 if ((mode & TYPE) != 0 &&
990 (token.kind == COMMA || token.kind == GT)) {
991 mode = TYPE;
992 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
993 args.append(t1);
994 while (token.kind == COMMA) {
995 nextToken();
996 args.append(typeArgument());
997 }
998 accept(GT);
999 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1000 checkGenerics();
1001 mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type
1002 t = term3Rest(t, typeArgs);
1003 if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) {
1004 //explicit lambda (w/ generic type)
1005 mode = EXPR;
1006 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
1007 if (token.kind == ELLIPSIS) {
1008 mods.flags = Flags.VARARGS;
1009 t = to(F.at(token.pos).TypeArray(t));
1010 nextToken();
1011 }
1012 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
1013 break;
1014 }
1015 } else if ((mode & EXPR) != 0) {
1016 mode = EXPR;
1017 JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
1018 t = F.at(pos1).Binary(op, t, e);
1019 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
1020 } else {
1021 accept(GT);
1022 }
1023 } else if ((mode & TYPE) != 0 &&
1024 (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) {
1025 //explicit lambda (w/ non-generic type)
1026 mode = EXPR;
1027 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
1028 if (token.kind == ELLIPSIS) {
1029 mods.flags = Flags.VARARGS;
1030 t = to(F.at(token.pos).TypeArray(t));
1031 nextToken();
1032 }
1033 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
1034 break;
1035 } else {
1036 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
1037 }
1038 }
1040 accept(RPAREN);
1041 lastmode = mode;
1042 mode = EXPR;
1043 if ((lastmode & EXPR) == 0) {
1044 JCExpression t1 = term3();
1045 return F.at(pos).TypeCast(t, t1);
1046 } else if ((lastmode & TYPE) != 0) {
1047 switch (token.kind) {
1048 /*case PLUSPLUS: case SUBSUB: */
1049 case BANG: case TILDE:
1050 case LPAREN: case THIS: case SUPER:
1051 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
1052 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
1053 case TRUE: case FALSE: case NULL:
1054 case NEW: case IDENTIFIER: case ASSERT: case ENUM:
1055 case BYTE: case SHORT: case CHAR: case INT:
1056 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
1057 JCExpression t1 = term3();
1058 return F.at(pos).TypeCast(t, t1);
1059 }
1060 }
1061 } else {
1062 return illegal();
1063 }
1064 t = toP(F.at(pos).Parens(t));
1065 break;
1066 case THIS:
1067 if ((mode & EXPR) != 0) {
1068 mode = EXPR;
1069 t = to(F.at(pos).Ident(names._this));
1070 nextToken();
1071 if (typeArgs == null)
1072 t = argumentsOpt(null, t);
1073 else
1074 t = arguments(typeArgs, t);
1075 typeArgs = null;
1076 } else return illegal();
1077 break;
1078 case SUPER:
1079 if ((mode & EXPR) != 0) {
1080 mode = EXPR;
1081 t = to(F.at(pos).Ident(names._super));
1082 t = superSuffix(typeArgs, t);
1083 typeArgs = null;
1084 } else return illegal();
1085 break;
1086 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1087 case CHARLITERAL: case STRINGLITERAL:
1088 case TRUE: case FALSE: case NULL:
1089 if (typeArgs == null && (mode & EXPR) != 0) {
1090 mode = EXPR;
1091 t = literal(names.empty);
1092 } else return illegal();
1093 break;
1094 case NEW:
1095 if (typeArgs != null) return illegal();
1096 if ((mode & EXPR) != 0) {
1097 mode = EXPR;
1098 nextToken();
1099 if (token.kind == LT) typeArgs = typeArguments(false);
1100 t = creator(pos, typeArgs);
1101 typeArgs = null;
1102 } else return illegal();
1103 break;
1104 case IDENTIFIER: case ASSERT: case ENUM:
1105 if (typeArgs != null) return illegal();
1106 if ((mode & EXPR) != 0 && peekToken(ARROW)) {
1107 t = lambdaExpressionOrStatement(false, false, pos);
1108 } else {
1109 t = toP(F.at(token.pos).Ident(ident()));
1110 loop: while (true) {
1111 pos = token.pos;
1112 switch (token.kind) {
1113 case LBRACKET:
1114 nextToken();
1115 if (token.kind == RBRACKET) {
1116 nextToken();
1117 t = bracketsOpt(t);
1118 t = toP(F.at(pos).TypeArray(t));
1119 t = bracketsSuffix(t);
1120 } else {
1121 if ((mode & EXPR) != 0) {
1122 mode = EXPR;
1123 JCExpression t1 = term();
1124 t = to(F.at(pos).Indexed(t, t1));
1125 }
1126 accept(RBRACKET);
1127 }
1128 break loop;
1129 case LPAREN:
1130 if ((mode & EXPR) != 0) {
1131 mode = EXPR;
1132 t = arguments(typeArgs, t);
1133 typeArgs = null;
1134 }
1135 break loop;
1136 case DOT:
1137 nextToken();
1138 int oldmode = mode;
1139 mode &= ~NOPARAMS;
1140 typeArgs = typeArgumentsOpt(EXPR);
1141 mode = oldmode;
1142 if ((mode & EXPR) != 0) {
1143 switch (token.kind) {
1144 case CLASS:
1145 if (typeArgs != null) return illegal();
1146 mode = EXPR;
1147 t = to(F.at(pos).Select(t, names._class));
1148 nextToken();
1149 break loop;
1150 case THIS:
1151 if (typeArgs != null) return illegal();
1152 mode = EXPR;
1153 t = to(F.at(pos).Select(t, names._this));
1154 nextToken();
1155 break loop;
1156 case SUPER:
1157 mode = EXPR;
1158 t = to(F.at(pos).Select(t, names._super));
1159 t = superSuffix(typeArgs, t);
1160 typeArgs = null;
1161 break loop;
1162 case NEW:
1163 if (typeArgs != null) return illegal();
1164 mode = EXPR;
1165 int pos1 = token.pos;
1166 nextToken();
1167 if (token.kind == LT) typeArgs = typeArguments(false);
1168 t = innerCreator(pos1, typeArgs, t);
1169 typeArgs = null;
1170 break loop;
1171 }
1172 }
1173 // typeArgs saved for next loop iteration.
1174 t = toP(F.at(pos).Select(t, ident()));
1175 break;
1176 case LT:
1177 if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
1178 //this is an unbound method reference whose qualifier
1179 //is a generic type i.e. A<S>::m
1180 int pos1 = token.pos;
1181 accept(LT);
1182 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
1183 args.append(typeArgument());
1184 while (token.kind == COMMA) {
1185 nextToken();
1186 args.append(typeArgument());
1187 }
1188 accept(GT);
1189 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1190 checkGenerics();
1191 while (token.kind == DOT) {
1192 nextToken();
1193 mode = TYPE;
1194 t = toP(F.at(token.pos).Select(t, ident()));
1195 t = typeArgumentsOpt(t);
1196 }
1197 t = bracketsOpt(t);
1198 if (token.kind != COLCOL) {
1199 //method reference expected here
1200 t = illegal();
1201 }
1202 mode = EXPR;
1203 return term3Rest(t, typeArgs);
1204 }
1205 break loop;
1206 default:
1207 break loop;
1208 }
1209 }
1210 }
1211 if (typeArgs != null) illegal();
1212 t = typeArgumentsOpt(t);
1213 break;
1214 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1215 case DOUBLE: case BOOLEAN:
1216 if (typeArgs != null) illegal();
1217 t = bracketsSuffix(bracketsOpt(basicType()));
1218 break;
1219 case VOID:
1220 if (typeArgs != null) illegal();
1221 if ((mode & EXPR) != 0) {
1222 nextToken();
1223 if (token.kind == DOT) {
1224 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1225 t = bracketsSuffix(ti);
1226 } else {
1227 return illegal(pos);
1228 }
1229 } else {
1230 // Support the corner case of myMethodHandle.<void>invoke() by passing
1231 // a void type (like other primitive types) to the next phase.
1232 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1233 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1234 nextToken();
1235 return ti;
1236 //return illegal();
1237 }
1238 break;
1239 default:
1240 return illegal();
1241 }
1242 return term3Rest(t, typeArgs);
1243 }
1245 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1246 if (typeArgs != null) illegal();
1247 while (true) {
1248 int pos1 = token.pos;
1249 if (token.kind == LBRACKET) {
1250 nextToken();
1251 if ((mode & TYPE) != 0) {
1252 int oldmode = mode;
1253 mode = TYPE;
1254 if (token.kind == RBRACKET) {
1255 nextToken();
1256 t = bracketsOpt(t);
1257 t = toP(F.at(pos1).TypeArray(t));
1258 if (token.kind == COLCOL) {
1259 mode = EXPR;
1260 continue;
1261 }
1262 return t;
1263 }
1264 mode = oldmode;
1265 }
1266 if ((mode & EXPR) != 0) {
1267 mode = EXPR;
1268 JCExpression t1 = term();
1269 t = to(F.at(pos1).Indexed(t, t1));
1270 }
1271 accept(RBRACKET);
1272 } else if (token.kind == DOT) {
1273 nextToken();
1274 typeArgs = typeArgumentsOpt(EXPR);
1275 if (token.kind == SUPER && (mode & EXPR) != 0) {
1276 mode = EXPR;
1277 t = to(F.at(pos1).Select(t, names._super));
1278 nextToken();
1279 t = arguments(typeArgs, t);
1280 typeArgs = null;
1281 } else if (token.kind == NEW && (mode & EXPR) != 0) {
1282 if (typeArgs != null) return illegal();
1283 mode = EXPR;
1284 int pos2 = token.pos;
1285 nextToken();
1286 if (token.kind == LT) typeArgs = typeArguments(false);
1287 t = innerCreator(pos2, typeArgs, t);
1288 typeArgs = null;
1289 } else {
1290 t = toP(F.at(pos1).Select(t, ident()));
1291 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1292 typeArgs = null;
1293 }
1294 } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
1295 mode = EXPR;
1296 if (typeArgs != null) return illegal();
1297 accept(COLCOL);
1298 t = memberReferenceSuffix(pos1, t);
1299 } else {
1300 break;
1301 }
1302 }
1303 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
1304 mode = EXPR;
1305 t = to(F.at(token.pos).Unary(
1306 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1307 nextToken();
1308 }
1309 return toP(t);
1310 }
1312 /**
1313 * If we see an identifier followed by a '<' it could be an unbound
1314 * method reference or a binary expression. To disambiguate, look for a
1315 * matching '>' and see if the subsequent terminal is either '.' or '#'.
1316 */
1317 @SuppressWarnings("fallthrough")
1318 boolean isUnboundMemberRef() {
1319 int pos = 0, depth = 0;
1320 for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1321 switch (t.kind) {
1322 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
1323 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1324 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1325 case DOUBLE: case BOOLEAN: case CHAR:
1326 break;
1327 case LT:
1328 depth++; break;
1329 case GTGTGT:
1330 depth--;
1331 case GTGT:
1332 depth--;
1333 case GT:
1334 depth--;
1335 if (depth == 0) {
1336 TokenKind nextKind = S.token(pos + 1).kind;
1337 return
1338 nextKind == TokenKind.DOT ||
1339 nextKind == TokenKind.LBRACKET ||
1340 nextKind == TokenKind.COLCOL;
1341 }
1342 break;
1343 default:
1344 return false;
1345 }
1346 }
1347 }
1349 JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
1350 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
1351 params.append(firstParam);
1352 JCVariableDecl lastParam = firstParam;
1353 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
1354 nextToken();
1355 params.append(lastParam = formalParameter());
1356 }
1357 accept(RPAREN);
1358 return lambdaExpressionOrStatementRest(params.toList(), pos);
1359 }
1361 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
1362 List<JCVariableDecl> params = explicitParams ?
1363 formalParameters() :
1364 implicitParameters(hasParens);
1366 return lambdaExpressionOrStatementRest(params, pos);
1367 }
1369 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
1370 checkLambda();
1371 accept(ARROW);
1373 return token.kind == LBRACE ?
1374 lambdaStatement(args, pos, pos) :
1375 lambdaExpression(args, pos);
1376 }
1378 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
1379 JCBlock block = block(pos2, 0);
1380 return toP(F.at(pos).Lambda(args, block));
1381 }
1383 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
1384 JCTree expr = parseExpression();
1385 return toP(F.at(pos).Lambda(args, expr));
1386 }
1388 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1389 */
1390 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1391 nextToken();
1392 if (token.kind == LPAREN || typeArgs != null) {
1393 t = arguments(typeArgs, t);
1394 } else if (token.kind == COLCOL) {
1395 if (typeArgs != null) return illegal();
1396 t = memberReferenceSuffix(t);
1397 } else {
1398 int pos = token.pos;
1399 accept(DOT);
1400 typeArgs = (token.kind == LT) ? typeArguments(false) : null;
1401 t = toP(F.at(pos).Select(t, ident()));
1402 t = argumentsOpt(typeArgs, t);
1403 }
1404 return t;
1405 }
1407 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1408 */
1409 JCPrimitiveTypeTree basicType() {
1410 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
1411 nextToken();
1412 return t;
1413 }
1415 /** ArgumentsOpt = [ Arguments ]
1416 */
1417 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1418 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
1419 mode = EXPR;
1420 return arguments(typeArgs, t);
1421 } else {
1422 return t;
1423 }
1424 }
1426 /** Arguments = "(" [Expression { COMMA Expression }] ")"
1427 */
1428 List<JCExpression> arguments() {
1429 ListBuffer<JCExpression> args = lb();
1430 if (token.kind == LPAREN) {
1431 nextToken();
1432 if (token.kind != RPAREN) {
1433 args.append(parseExpression());
1434 while (token.kind == COMMA) {
1435 nextToken();
1436 args.append(parseExpression());
1437 }
1438 }
1439 accept(RPAREN);
1440 } else {
1441 syntaxError(token.pos, "expected", LPAREN);
1442 }
1443 return args.toList();
1444 }
1446 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1447 int pos = token.pos;
1448 List<JCExpression> args = arguments();
1449 return toP(F.at(pos).Apply(typeArgs, t, args));
1450 }
1452 /** TypeArgumentsOpt = [ TypeArguments ]
1453 */
1454 JCExpression typeArgumentsOpt(JCExpression t) {
1455 if (token.kind == LT &&
1456 (mode & TYPE) != 0 &&
1457 (mode & NOPARAMS) == 0) {
1458 mode = TYPE;
1459 checkGenerics();
1460 return typeArguments(t, false);
1461 } else {
1462 return t;
1463 }
1464 }
1465 List<JCExpression> typeArgumentsOpt() {
1466 return typeArgumentsOpt(TYPE);
1467 }
1469 List<JCExpression> typeArgumentsOpt(int useMode) {
1470 if (token.kind == LT) {
1471 checkGenerics();
1472 if ((mode & useMode) == 0 ||
1473 (mode & NOPARAMS) != 0) {
1474 illegal();
1475 }
1476 mode = useMode;
1477 return typeArguments(false);
1478 }
1479 return null;
1480 }
1482 /**
1483 * {@literal
1484 * TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1485 * }
1486 */
1487 List<JCExpression> typeArguments(boolean diamondAllowed) {
1488 if (token.kind == LT) {
1489 nextToken();
1490 if (token.kind == GT && diamondAllowed) {
1491 checkDiamond();
1492 mode |= DIAMOND;
1493 nextToken();
1494 return List.nil();
1495 } else {
1496 ListBuffer<JCExpression> args = ListBuffer.lb();
1497 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1498 while (token.kind == COMMA) {
1499 nextToken();
1500 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1501 }
1502 switch (token.kind) {
1504 case GTGTGTEQ: case GTGTEQ: case GTEQ:
1505 case GTGTGT: case GTGT:
1506 token = S.split();
1507 break;
1508 case GT:
1509 nextToken();
1510 break;
1511 default:
1512 args.append(syntaxError(token.pos, "expected", GT));
1513 break;
1514 }
1515 return args.toList();
1516 }
1517 } else {
1518 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
1519 }
1520 }
1522 /**
1523 * {@literal
1524 * TypeArgument = Type
1525 * | "?"
1526 * | "?" EXTENDS Type {"&" Type}
1527 * | "?" SUPER Type
1528 * }
1529 */
1530 JCExpression typeArgument() {
1531 if (token.kind != QUES) return parseType();
1532 int pos = token.pos;
1533 nextToken();
1534 if (token.kind == EXTENDS) {
1535 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
1536 nextToken();
1537 JCExpression bound = parseType();
1538 return F.at(pos).Wildcard(t, bound);
1539 } else if (token.kind == SUPER) {
1540 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
1541 nextToken();
1542 JCExpression bound = parseType();
1543 return F.at(pos).Wildcard(t, bound);
1544 } else if (token.kind == IDENTIFIER) {
1545 //error recovery
1546 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1547 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1548 JCIdent id = toP(F.at(token.pos).Ident(ident()));
1549 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1550 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
1551 return err;
1552 } else {
1553 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
1554 return toP(F.at(pos).Wildcard(t, null));
1555 }
1556 }
1558 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
1559 int pos = token.pos;
1560 List<JCExpression> args = typeArguments(diamondAllowed);
1561 return toP(F.at(pos).TypeApply(t, args));
1562 }
1564 /** BracketsOpt = {"[" "]"}
1565 */
1566 private JCExpression bracketsOpt(JCExpression t) {
1567 if (token.kind == LBRACKET) {
1568 int pos = token.pos;
1569 nextToken();
1570 t = bracketsOptCont(t, pos);
1571 F.at(pos);
1572 }
1573 return t;
1574 }
1576 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1577 accept(RBRACKET);
1578 t = bracketsOpt(t);
1579 return toP(F.at(pos).TypeArray(t));
1580 }
1582 /** BracketsSuffixExpr = "." CLASS
1583 * BracketsSuffixType =
1584 */
1585 JCExpression bracketsSuffix(JCExpression t) {
1586 if ((mode & EXPR) != 0 && token.kind == DOT) {
1587 mode = EXPR;
1588 int pos = token.pos;
1589 nextToken();
1590 accept(CLASS);
1591 if (token.pos == endPosTable.errorEndPos) {
1592 // error recovery
1593 Name name = null;
1594 if (token.kind == IDENTIFIER) {
1595 name = token.name();
1596 nextToken();
1597 } else {
1598 name = names.error;
1599 }
1600 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1601 } else {
1602 t = toP(F.at(pos).Select(t, names._class));
1603 }
1604 } else if ((mode & TYPE) != 0) {
1605 if (token.kind != COLCOL) {
1606 mode = TYPE;
1607 }
1608 } else if (token.kind != COLCOL) {
1609 syntaxError(token.pos, "dot.class.expected");
1610 }
1611 return t;
1612 }
1614 /**
1615 * MemberReferenceSuffix = "::" [TypeArguments] Ident
1616 * | "::" [TypeArguments] "new"
1617 */
1618 JCExpression memberReferenceSuffix(JCExpression t) {
1619 int pos1 = token.pos;
1620 accept(COLCOL);
1621 return memberReferenceSuffix(pos1, t);
1622 }
1624 JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
1625 checkMethodReferences();
1626 mode = EXPR;
1627 List<JCExpression> typeArgs = null;
1628 if (token.kind == LT) {
1629 typeArgs = typeArguments(false);
1630 }
1631 Name refName = null;
1632 ReferenceMode refMode = null;
1633 if (token.kind == NEW) {
1634 refMode = ReferenceMode.NEW;
1635 refName = names.init;
1636 nextToken();
1637 } else {
1638 refMode = ReferenceMode.INVOKE;
1639 refName = ident();
1640 }
1641 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
1642 }
1644 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1645 */
1646 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1647 switch (token.kind) {
1648 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1649 case DOUBLE: case BOOLEAN:
1650 if (typeArgs == null)
1651 return arrayCreatorRest(newpos, basicType());
1652 break;
1653 default:
1654 }
1655 JCExpression t = qualident();
1656 int oldmode = mode;
1657 mode = TYPE;
1658 boolean diamondFound = false;
1659 int lastTypeargsPos = -1;
1660 if (token.kind == LT) {
1661 checkGenerics();
1662 lastTypeargsPos = token.pos;
1663 t = typeArguments(t, true);
1664 diamondFound = (mode & DIAMOND) != 0;
1665 }
1666 while (token.kind == DOT) {
1667 if (diamondFound) {
1668 //cannot select after a diamond
1669 illegal();
1670 }
1671 int pos = token.pos;
1672 nextToken();
1673 t = toP(F.at(pos).Select(t, ident()));
1674 if (token.kind == LT) {
1675 lastTypeargsPos = token.pos;
1676 checkGenerics();
1677 t = typeArguments(t, true);
1678 diamondFound = (mode & DIAMOND) != 0;
1679 }
1680 }
1681 mode = oldmode;
1682 if (token.kind == LBRACKET) {
1683 JCExpression e = arrayCreatorRest(newpos, t);
1684 if (diamondFound) {
1685 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
1686 return toP(F.at(newpos).Erroneous(List.of(e)));
1687 }
1688 else if (typeArgs != null) {
1689 int pos = newpos;
1690 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1691 // note: this should always happen but we should
1692 // not rely on this as the parser is continuously
1693 // modified to improve error recovery.
1694 pos = typeArgs.head.pos;
1695 }
1696 setErrorEndPos(S.prevToken().endPos);
1697 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
1698 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
1699 return toP(err);
1700 }
1701 return e;
1702 } else if (token.kind == LPAREN) {
1703 return classCreatorRest(newpos, null, typeArgs, t);
1704 } else {
1705 setErrorEndPos(token.pos);
1706 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
1707 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1708 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1709 }
1710 }
1712 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1713 */
1714 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1715 JCExpression t = toP(F.at(token.pos).Ident(ident()));
1716 if (token.kind == LT) {
1717 int oldmode = mode;
1718 checkGenerics();
1719 t = typeArguments(t, true);
1720 mode = oldmode;
1721 }
1722 return classCreatorRest(newpos, encl, typeArgs, t);
1723 }
1725 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1726 * | Expression "]" {"[" Expression "]"} BracketsOpt )
1727 */
1728 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1729 accept(LBRACKET);
1730 if (token.kind == RBRACKET) {
1731 accept(RBRACKET);
1732 elemtype = bracketsOpt(elemtype);
1733 if (token.kind == LBRACE) {
1734 return arrayInitializer(newpos, elemtype);
1735 } else {
1736 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
1737 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
1738 }
1739 } else {
1740 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1741 dims.append(parseExpression());
1742 accept(RBRACKET);
1743 while (token.kind == LBRACKET) {
1744 int pos = token.pos;
1745 nextToken();
1746 if (token.kind == RBRACKET) {
1747 elemtype = bracketsOptCont(elemtype, pos);
1748 } else {
1749 dims.append(parseExpression());
1750 accept(RBRACKET);
1751 }
1752 }
1753 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1754 }
1755 }
1757 /** ClassCreatorRest = Arguments [ClassBody]
1758 */
1759 JCNewClass classCreatorRest(int newpos,
1760 JCExpression encl,
1761 List<JCExpression> typeArgs,
1762 JCExpression t)
1763 {
1764 List<JCExpression> args = arguments();
1765 JCClassDecl body = null;
1766 if (token.kind == LBRACE) {
1767 int pos = token.pos;
1768 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1769 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1770 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1771 }
1772 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1773 }
1775 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1776 */
1777 JCExpression arrayInitializer(int newpos, JCExpression t) {
1778 accept(LBRACE);
1779 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1780 if (token.kind == COMMA) {
1781 nextToken();
1782 } else if (token.kind != RBRACE) {
1783 elems.append(variableInitializer());
1784 while (token.kind == COMMA) {
1785 nextToken();
1786 if (token.kind == RBRACE) break;
1787 elems.append(variableInitializer());
1788 }
1789 }
1790 accept(RBRACE);
1791 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1792 }
1794 /** VariableInitializer = ArrayInitializer | Expression
1795 */
1796 public JCExpression variableInitializer() {
1797 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
1798 }
1800 /** ParExpression = "(" Expression ")"
1801 */
1802 JCExpression parExpression() {
1803 int pos = token.pos;
1804 accept(LPAREN);
1805 JCExpression t = parseExpression();
1806 accept(RPAREN);
1807 return toP(F.at(pos).Parens(t));
1808 }
1810 /** Block = "{" BlockStatements "}"
1811 */
1812 JCBlock block(int pos, long flags) {
1813 accept(LBRACE);
1814 List<JCStatement> stats = blockStatements();
1815 JCBlock t = F.at(pos).Block(flags, stats);
1816 while (token.kind == CASE || token.kind == DEFAULT) {
1817 syntaxError("orphaned", token.kind);
1818 switchBlockStatementGroups();
1819 }
1820 // the Block node has a field "endpos" for first char of last token, which is
1821 // usually but not necessarily the last char of the last token.
1822 t.endpos = token.pos;
1823 accept(RBRACE);
1824 return toP(t);
1825 }
1827 public JCBlock block() {
1828 return block(token.pos, 0);
1829 }
1831 /** BlockStatements = { BlockStatement }
1832 * BlockStatement = LocalVariableDeclarationStatement
1833 * | ClassOrInterfaceOrEnumDeclaration
1834 * | [Ident ":"] Statement
1835 * LocalVariableDeclarationStatement
1836 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1837 */
1838 @SuppressWarnings("fallthrough")
1839 List<JCStatement> blockStatements() {
1840 //todo: skip to anchor on error(?)
1841 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1842 while (true) {
1843 List<JCStatement> stat = blockStatement();
1844 if (stat.isEmpty()) {
1845 return stats.toList();
1846 } else {
1847 if (token.pos <= endPosTable.errorEndPos) {
1848 skip(false, true, true, true);
1849 }
1850 stats.addAll(stat);
1851 }
1852 }
1853 }
1855 /*
1856 * This method parses a statement treating it as a block, relaxing the
1857 * JLS restrictions, allows us to parse more faulty code, doing so
1858 * enables us to provide better and accurate diagnostics to the user.
1859 */
1860 JCStatement parseStatementAsBlock() {
1861 int pos = token.pos;
1862 List<JCStatement> stats = blockStatement();
1863 if (stats.isEmpty()) {
1864 JCErroneous e = F.at(pos).Erroneous();
1865 error(e, "illegal.start.of.stmt");
1866 return F.at(pos).Exec(e);
1867 } else {
1868 JCStatement first = stats.head;
1869 String error = null;
1870 switch (first.getTag()) {
1871 case CLASSDEF:
1872 error = "class.not.allowed";
1873 break;
1874 case VARDEF:
1875 error = "variable.not.allowed";
1876 break;
1877 }
1878 if (error != null) {
1879 error(first, error);
1880 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
1881 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
1882 }
1883 return first;
1884 }
1885 }
1887 @SuppressWarnings("fallthrough")
1888 List<JCStatement> blockStatement() {
1889 //todo: skip to anchor on error(?)
1890 int pos = token.pos;
1891 switch (token.kind) {
1892 case RBRACE: case CASE: case DEFAULT: case EOF:
1893 return List.nil();
1894 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1895 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1896 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1897 return List.of(parseStatement());
1898 case MONKEYS_AT:
1899 case FINAL: {
1900 Comment dc = token.comment(CommentStyle.JAVADOC);
1901 JCModifiers mods = modifiersOpt();
1902 if (token.kind == INTERFACE ||
1903 token.kind == CLASS ||
1904 allowEnums && token.kind == ENUM) {
1905 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
1906 } else {
1907 JCExpression t = parseType();
1908 ListBuffer<JCStatement> stats =
1909 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
1910 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1911 storeEnd(stats.elems.last(), token.endPos);
1912 accept(SEMI);
1913 return stats.toList();
1914 }
1915 }
1916 case ABSTRACT: case STRICTFP: {
1917 Comment dc = token.comment(CommentStyle.JAVADOC);
1918 JCModifiers mods = modifiersOpt();
1919 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
1920 }
1921 case INTERFACE:
1922 case CLASS:
1923 Comment dc = token.comment(CommentStyle.JAVADOC);
1924 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
1925 case ENUM:
1926 case ASSERT:
1927 if (allowEnums && token.kind == ENUM) {
1928 error(token.pos, "local.enum");
1929 dc = token.comment(CommentStyle.JAVADOC);
1930 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
1931 } else if (allowAsserts && token.kind == ASSERT) {
1932 return List.of(parseStatement());
1933 }
1934 /* fall through to default */
1935 default:
1936 Token prevToken = token;
1937 JCExpression t = term(EXPR | TYPE);
1938 if (token.kind == COLON && t.hasTag(IDENT)) {
1939 nextToken();
1940 JCStatement stat = parseStatement();
1941 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
1942 } else if ((lastmode & TYPE) != 0 &&
1943 (token.kind == IDENTIFIER ||
1944 token.kind == ASSERT ||
1945 token.kind == ENUM)) {
1946 pos = token.pos;
1947 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1948 F.at(pos);
1949 ListBuffer<JCStatement> stats =
1950 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
1951 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1952 storeEnd(stats.elems.last(), token.endPos);
1953 accept(SEMI);
1954 return stats.toList();
1955 } else {
1956 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1957 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
1958 accept(SEMI);
1959 return List.<JCStatement>of(expr);
1960 }
1961 }
1962 }
1964 /** Statement =
1965 * Block
1966 * | IF ParExpression Statement [ELSE Statement]
1967 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1968 * | FOR "(" FormalParameter : Expression ")" Statement
1969 * | WHILE ParExpression Statement
1970 * | DO Statement WHILE ParExpression ";"
1971 * | TRY Block ( Catches | [Catches] FinallyPart )
1972 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
1973 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1974 * | SYNCHRONIZED ParExpression Block
1975 * | RETURN [Expression] ";"
1976 * | THROW Expression ";"
1977 * | BREAK [Ident] ";"
1978 * | CONTINUE [Ident] ";"
1979 * | ASSERT Expression [ ":" Expression ] ";"
1980 * | ";"
1981 * | ExpressionStatement
1982 * | Ident ":" Statement
1983 */
1984 @SuppressWarnings("fallthrough")
1985 public JCStatement parseStatement() {
1986 int pos = token.pos;
1987 switch (token.kind) {
1988 case LBRACE:
1989 return block();
1990 case IF: {
1991 nextToken();
1992 JCExpression cond = parExpression();
1993 JCStatement thenpart = parseStatementAsBlock();
1994 JCStatement elsepart = null;
1995 if (token.kind == ELSE) {
1996 nextToken();
1997 elsepart = parseStatementAsBlock();
1998 }
1999 return F.at(pos).If(cond, thenpart, elsepart);
2000 }
2001 case FOR: {
2002 nextToken();
2003 accept(LPAREN);
2004 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
2005 if (inits.length() == 1 &&
2006 inits.head.hasTag(VARDEF) &&
2007 ((JCVariableDecl) inits.head).init == null &&
2008 token.kind == COLON) {
2009 checkForeach();
2010 JCVariableDecl var = (JCVariableDecl)inits.head;
2011 accept(COLON);
2012 JCExpression expr = parseExpression();
2013 accept(RPAREN);
2014 JCStatement body = parseStatementAsBlock();
2015 return F.at(pos).ForeachLoop(var, expr, body);
2016 } else {
2017 accept(SEMI);
2018 JCExpression cond = token.kind == SEMI ? null : parseExpression();
2019 accept(SEMI);
2020 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
2021 accept(RPAREN);
2022 JCStatement body = parseStatementAsBlock();
2023 return F.at(pos).ForLoop(inits, cond, steps, body);
2024 }
2025 }
2026 case WHILE: {
2027 nextToken();
2028 JCExpression cond = parExpression();
2029 JCStatement body = parseStatementAsBlock();
2030 return F.at(pos).WhileLoop(cond, body);
2031 }
2032 case DO: {
2033 nextToken();
2034 JCStatement body = parseStatementAsBlock();
2035 accept(WHILE);
2036 JCExpression cond = parExpression();
2037 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
2038 accept(SEMI);
2039 return t;
2040 }
2041 case TRY: {
2042 nextToken();
2043 List<JCTree> resources = List.<JCTree>nil();
2044 if (token.kind == LPAREN) {
2045 checkTryWithResources();
2046 nextToken();
2047 resources = resources();
2048 accept(RPAREN);
2049 }
2050 JCBlock body = block();
2051 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
2052 JCBlock finalizer = null;
2053 if (token.kind == CATCH || token.kind == FINALLY) {
2054 while (token.kind == CATCH) catchers.append(catchClause());
2055 if (token.kind == FINALLY) {
2056 nextToken();
2057 finalizer = block();
2058 }
2059 } else {
2060 if (allowTWR) {
2061 if (resources.isEmpty())
2062 error(pos, "try.without.catch.finally.or.resource.decls");
2063 } else
2064 error(pos, "try.without.catch.or.finally");
2065 }
2066 return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
2067 }
2068 case SWITCH: {
2069 nextToken();
2070 JCExpression selector = parExpression();
2071 accept(LBRACE);
2072 List<JCCase> cases = switchBlockStatementGroups();
2073 JCSwitch t = to(F.at(pos).Switch(selector, cases));
2074 accept(RBRACE);
2075 return t;
2076 }
2077 case SYNCHRONIZED: {
2078 nextToken();
2079 JCExpression lock = parExpression();
2080 JCBlock body = block();
2081 return F.at(pos).Synchronized(lock, body);
2082 }
2083 case RETURN: {
2084 nextToken();
2085 JCExpression result = token.kind == SEMI ? null : parseExpression();
2086 JCReturn t = to(F.at(pos).Return(result));
2087 accept(SEMI);
2088 return t;
2089 }
2090 case THROW: {
2091 nextToken();
2092 JCExpression exc = parseExpression();
2093 JCThrow t = to(F.at(pos).Throw(exc));
2094 accept(SEMI);
2095 return t;
2096 }
2097 case BREAK: {
2098 nextToken();
2099 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
2100 JCBreak t = to(F.at(pos).Break(label));
2101 accept(SEMI);
2102 return t;
2103 }
2104 case CONTINUE: {
2105 nextToken();
2106 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
2107 JCContinue t = to(F.at(pos).Continue(label));
2108 accept(SEMI);
2109 return t;
2110 }
2111 case SEMI:
2112 nextToken();
2113 return toP(F.at(pos).Skip());
2114 case ELSE:
2115 int elsePos = token.pos;
2116 nextToken();
2117 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
2118 case FINALLY:
2119 int finallyPos = token.pos;
2120 nextToken();
2121 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
2122 case CATCH:
2123 return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
2124 case ASSERT: {
2125 if (allowAsserts && token.kind == ASSERT) {
2126 nextToken();
2127 JCExpression assertion = parseExpression();
2128 JCExpression message = null;
2129 if (token.kind == COLON) {
2130 nextToken();
2131 message = parseExpression();
2132 }
2133 JCAssert t = to(F.at(pos).Assert(assertion, message));
2134 accept(SEMI);
2135 return t;
2136 }
2137 /* else fall through to default case */
2138 }
2139 case ENUM:
2140 default:
2141 Token prevToken = token;
2142 JCExpression expr = parseExpression();
2143 if (token.kind == COLON && expr.hasTag(IDENT)) {
2144 nextToken();
2145 JCStatement stat = parseStatement();
2146 return F.at(pos).Labelled(prevToken.name(), stat);
2147 } else {
2148 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2149 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
2150 accept(SEMI);
2151 return stat;
2152 }
2153 }
2154 }
2156 private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
2157 int errPos = S.errPos();
2158 JCTree stm = action.doRecover(this);
2159 S.errPos(errPos);
2160 return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
2161 }
2163 /** CatchClause = CATCH "(" FormalParameter ")" Block
2164 */
2165 protected JCCatch catchClause() {
2166 int pos = token.pos;
2167 accept(CATCH);
2168 accept(LPAREN);
2169 JCModifiers mods = optFinal(Flags.PARAMETER);
2170 List<JCExpression> catchTypes = catchTypes();
2171 JCExpression paramType = catchTypes.size() > 1 ?
2172 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
2173 catchTypes.head;
2174 JCVariableDecl formal = variableDeclaratorId(mods, paramType);
2175 accept(RPAREN);
2176 JCBlock body = block();
2177 return F.at(pos).Catch(formal, body);
2178 }
2180 List<JCExpression> catchTypes() {
2181 ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
2182 catchTypes.add(parseType());
2183 while (token.kind == BAR) {
2184 checkMulticatch();
2185 nextToken();
2186 catchTypes.add(qualident());
2187 }
2188 return catchTypes.toList();
2189 }
2191 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2192 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
2193 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2194 */
2195 List<JCCase> switchBlockStatementGroups() {
2196 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2197 while (true) {
2198 int pos = token.pos;
2199 switch (token.kind) {
2200 case CASE:
2201 case DEFAULT:
2202 cases.append(switchBlockStatementGroup());
2203 break;
2204 case RBRACE: case EOF:
2205 return cases.toList();
2206 default:
2207 nextToken(); // to ensure progress
2208 syntaxError(pos, "expected3",
2209 CASE, DEFAULT, RBRACE);
2210 }
2211 }
2212 }
2214 protected JCCase switchBlockStatementGroup() {
2215 int pos = token.pos;
2216 List<JCStatement> stats;
2217 JCCase c;
2218 switch (token.kind) {
2219 case CASE:
2220 nextToken();
2221 JCExpression pat = parseExpression();
2222 accept(COLON);
2223 stats = blockStatements();
2224 c = F.at(pos).Case(pat, stats);
2225 if (stats.isEmpty())
2226 storeEnd(c, S.prevToken().endPos);
2227 return c;
2228 case DEFAULT:
2229 nextToken();
2230 accept(COLON);
2231 stats = blockStatements();
2232 c = F.at(pos).Case(null, stats);
2233 if (stats.isEmpty())
2234 storeEnd(c, S.prevToken().endPos);
2235 return c;
2236 }
2237 throw new AssertionError("should not reach here");
2238 }
2240 /** MoreStatementExpressions = { COMMA StatementExpression }
2241 */
2242 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2243 JCExpression first,
2244 T stats) {
2245 // This Exec is a "StatementExpression"; it subsumes no terminating token
2246 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2247 while (token.kind == COMMA) {
2248 nextToken();
2249 pos = token.pos;
2250 JCExpression t = parseExpression();
2251 // This Exec is a "StatementExpression"; it subsumes no terminating token
2252 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2253 }
2254 return stats;
2255 }
2257 /** ForInit = StatementExpression MoreStatementExpressions
2258 * | { FINAL | '@' Annotation } Type VariableDeclarators
2259 */
2260 List<JCStatement> forInit() {
2261 ListBuffer<JCStatement> stats = lb();
2262 int pos = token.pos;
2263 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
2264 return variableDeclarators(optFinal(0), parseType(), stats).toList();
2265 } else {
2266 JCExpression t = term(EXPR | TYPE);
2267 if ((lastmode & TYPE) != 0 &&
2268 (token.kind == IDENTIFIER || token.kind == ASSERT ||
2269 token.kind == ENUM)) {
2270 return variableDeclarators(modifiersOpt(), t, stats).toList();
2271 } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
2272 error(pos, "bad.initializer", "for-loop");
2273 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
2274 } else {
2275 return moreStatementExpressions(pos, t, stats).toList();
2276 }
2277 }
2278 }
2280 /** ForUpdate = StatementExpression MoreStatementExpressions
2281 */
2282 List<JCExpressionStatement> forUpdate() {
2283 return moreStatementExpressions(token.pos,
2284 parseExpression(),
2285 new ListBuffer<JCExpressionStatement>()).toList();
2286 }
2288 /** AnnotationsOpt = { '@' Annotation }
2289 */
2290 List<JCAnnotation> annotationsOpt() {
2291 if (token.kind != MONKEYS_AT) return List.nil(); // optimization
2292 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
2293 while (token.kind == MONKEYS_AT) {
2294 int pos = token.pos;
2295 nextToken();
2296 buf.append(annotation(pos));
2297 }
2298 return buf.toList();
2299 }
2301 /** ModifiersOpt = { Modifier }
2302 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
2303 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
2304 * | "@" Annotation
2305 */
2306 JCModifiers modifiersOpt() {
2307 return modifiersOpt(null);
2308 }
2309 protected JCModifiers modifiersOpt(JCModifiers partial) {
2310 long flags;
2311 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
2312 int pos;
2313 if (partial == null) {
2314 flags = 0;
2315 pos = token.pos;
2316 } else {
2317 flags = partial.flags;
2318 annotations.appendList(partial.annotations);
2319 pos = partial.pos;
2320 }
2321 if (token.deprecatedFlag()) {
2322 flags |= Flags.DEPRECATED;
2323 }
2324 int lastPos = Position.NOPOS;
2325 loop:
2326 while (true) {
2327 long flag;
2328 switch (token.kind) {
2329 case PRIVATE : flag = Flags.PRIVATE; break;
2330 case PROTECTED : flag = Flags.PROTECTED; break;
2331 case PUBLIC : flag = Flags.PUBLIC; break;
2332 case STATIC : flag = Flags.STATIC; break;
2333 case TRANSIENT : flag = Flags.TRANSIENT; break;
2334 case FINAL : flag = Flags.FINAL; break;
2335 case ABSTRACT : flag = Flags.ABSTRACT; break;
2336 case NATIVE : flag = Flags.NATIVE; break;
2337 case VOLATILE : flag = Flags.VOLATILE; break;
2338 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
2339 case STRICTFP : flag = Flags.STRICTFP; break;
2340 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
2341 case DEFAULT : checkDefaultMethods(); flag = Flags.DEFAULT; break;
2342 case ERROR : flag = 0; nextToken(); break;
2343 default: break loop;
2344 }
2345 if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
2346 lastPos = token.pos;
2347 nextToken();
2348 if (flag == Flags.ANNOTATION) {
2349 checkAnnotations();
2350 if (token.kind != INTERFACE) {
2351 JCAnnotation ann = annotation(lastPos);
2352 // if first modifier is an annotation, set pos to annotation's.
2353 if (flags == 0 && annotations.isEmpty())
2354 pos = ann.pos;
2355 annotations.append(ann);
2356 lastPos = ann.pos;
2357 flag = 0;
2358 }
2359 }
2360 flags |= flag;
2361 }
2362 switch (token.kind) {
2363 case ENUM: flags |= Flags.ENUM; break;
2364 case INTERFACE: flags |= Flags.INTERFACE; break;
2365 default: break;
2366 }
2368 /* A modifiers tree with no modifier tokens or annotations
2369 * has no text position. */
2370 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
2371 pos = Position.NOPOS;
2373 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
2374 if (pos != Position.NOPOS)
2375 storeEnd(mods, S.prevToken().endPos);
2376 return mods;
2377 }
2379 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2380 * @param pos position of "@" token
2381 */
2382 JCAnnotation annotation(int pos) {
2383 // accept(AT); // AT consumed by caller
2384 checkAnnotations();
2385 JCTree ident = qualident();
2386 List<JCExpression> fieldValues = annotationFieldValuesOpt();
2387 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
2388 storeEnd(ann, S.prevToken().endPos);
2389 return ann;
2390 }
2392 List<JCExpression> annotationFieldValuesOpt() {
2393 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2394 }
2396 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2397 List<JCExpression> annotationFieldValues() {
2398 accept(LPAREN);
2399 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2400 if (token.kind != RPAREN) {
2401 buf.append(annotationFieldValue());
2402 while (token.kind == COMMA) {
2403 nextToken();
2404 buf.append(annotationFieldValue());
2405 }
2406 }
2407 accept(RPAREN);
2408 return buf.toList();
2409 }
2411 /** AnnotationFieldValue = AnnotationValue
2412 * | Identifier "=" AnnotationValue
2413 */
2414 JCExpression annotationFieldValue() {
2415 if (token.kind == IDENTIFIER) {
2416 mode = EXPR;
2417 JCExpression t1 = term1();
2418 if (t1.hasTag(IDENT) && token.kind == EQ) {
2419 int pos = token.pos;
2420 accept(EQ);
2421 JCExpression v = annotationValue();
2422 return toP(F.at(pos).Assign(t1, v));
2423 } else {
2424 return t1;
2425 }
2426 }
2427 return annotationValue();
2428 }
2430 /* AnnotationValue = ConditionalExpression
2431 * | Annotation
2432 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2433 */
2434 JCExpression annotationValue() {
2435 int pos;
2436 switch (token.kind) {
2437 case MONKEYS_AT:
2438 pos = token.pos;
2439 nextToken();
2440 return annotation(pos);
2441 case LBRACE:
2442 pos = token.pos;
2443 accept(LBRACE);
2444 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2445 if (token.kind != RBRACE) {
2446 buf.append(annotationValue());
2447 while (token.kind == COMMA) {
2448 nextToken();
2449 if (token.kind == RBRACE) break;
2450 buf.append(annotationValue());
2451 }
2452 }
2453 accept(RBRACE);
2454 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2455 default:
2456 mode = EXPR;
2457 return term1();
2458 }
2459 }
2461 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2462 */
2463 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2464 JCExpression type,
2465 T vdefs)
2466 {
2467 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
2468 }
2470 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2471 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2472 *
2473 * @param reqInit Is an initializer always required?
2474 * @param dc The documentation comment for the variable declarations, or null.
2475 */
2476 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2477 JCModifiers mods,
2478 JCExpression type,
2479 Name name,
2480 boolean reqInit,
2481 Comment dc,
2482 T vdefs)
2483 {
2484 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2485 while (token.kind == COMMA) {
2486 // All but last of multiple declarators subsume a comma
2487 storeEnd((JCTree)vdefs.elems.last(), token.endPos);
2488 nextToken();
2489 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2490 }
2491 return vdefs;
2492 }
2494 /** VariableDeclarator = Ident VariableDeclaratorRest
2495 * ConstantDeclarator = Ident ConstantDeclaratorRest
2496 */
2497 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
2498 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
2499 }
2501 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2502 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2503 *
2504 * @param reqInit Is an initializer always required?
2505 * @param dc The documentation comment for the variable declarations, or null.
2506 */
2507 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2508 boolean reqInit, Comment dc) {
2509 type = bracketsOpt(type);
2510 JCExpression init = null;
2511 if (token.kind == EQ) {
2512 nextToken();
2513 init = variableInitializer();
2514 }
2515 else if (reqInit) syntaxError(token.pos, "expected", EQ);
2516 JCVariableDecl result =
2517 toP(F.at(pos).VarDef(mods, name, type, init));
2518 attach(result, dc);
2519 return result;
2520 }
2522 /** VariableDeclaratorId = Ident BracketsOpt
2523 */
2524 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2525 int pos = token.pos;
2526 Name name = ident();
2527 if ((mods.flags & Flags.VARARGS) != 0 &&
2528 token.kind == LBRACKET) {
2529 log.error(token.pos, "varargs.and.old.array.syntax");
2530 }
2531 type = bracketsOpt(type);
2532 return toP(F.at(pos).VarDef(mods, name, type, null));
2533 }
2535 /** Resources = Resource { ";" Resources }
2536 */
2537 List<JCTree> resources() {
2538 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2539 defs.append(resource());
2540 while (token.kind == SEMI) {
2541 // All but last of multiple declarators must subsume a semicolon
2542 storeEnd(defs.elems.last(), token.endPos);
2543 int semiColonPos = token.pos;
2544 nextToken();
2545 if (token.kind == RPAREN) { // Optional trailing semicolon
2546 // after last resource
2547 break;
2548 }
2549 defs.append(resource());
2550 }
2551 return defs.toList();
2552 }
2554 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
2555 */
2556 protected JCTree resource() {
2557 JCModifiers optFinal = optFinal(Flags.FINAL);
2558 JCExpression type = parseType();
2559 int pos = token.pos;
2560 Name ident = ident();
2561 return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
2562 }
2564 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2565 */
2566 public JCTree.JCCompilationUnit parseCompilationUnit() {
2567 Token firstToken = token;
2568 JCExpression pid = null;
2569 JCModifiers mods = null;
2570 boolean consumedToplevelDoc = false;
2571 boolean seenImport = false;
2572 boolean seenPackage = false;
2573 List<JCAnnotation> packageAnnotations = List.nil();
2574 if (token.kind == MONKEYS_AT)
2575 mods = modifiersOpt();
2577 if (token.kind == PACKAGE) {
2578 seenPackage = true;
2579 if (mods != null) {
2580 checkNoMods(mods.flags);
2581 packageAnnotations = mods.annotations;
2582 mods = null;
2583 }
2584 nextToken();
2585 pid = qualident();
2586 accept(SEMI);
2587 }
2588 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2589 boolean checkForImports = true;
2590 boolean firstTypeDecl = true;
2591 while (token.kind != EOF) {
2592 if (token.pos <= endPosTable.errorEndPos) {
2593 // error recovery
2594 skip(checkForImports, false, false, false);
2595 if (token.kind == EOF)
2596 break;
2597 }
2598 if (checkForImports && mods == null && token.kind == IMPORT) {
2599 seenImport = true;
2600 defs.append(importDeclaration());
2601 } else {
2602 Comment docComment = token.comment(CommentStyle.JAVADOC);
2603 if (firstTypeDecl && !seenImport && !seenPackage) {
2604 docComment = firstToken.comment(CommentStyle.JAVADOC);
2605 consumedToplevelDoc = true;
2606 }
2607 JCTree def = typeDeclaration(mods, docComment);
2608 if (def instanceof JCExpressionStatement)
2609 def = ((JCExpressionStatement)def).expr;
2610 defs.append(def);
2611 if (def instanceof JCClassDecl)
2612 checkForImports = false;
2613 mods = null;
2614 firstTypeDecl = false;
2615 }
2616 }
2617 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
2618 if (!consumedToplevelDoc)
2619 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
2620 if (defs.elems.isEmpty())
2621 storeEnd(toplevel, S.prevToken().endPos);
2622 if (keepDocComments)
2623 toplevel.docComments = docComments;
2624 if (keepLineMap)
2625 toplevel.lineMap = S.getLineMap();
2626 toplevel.endPositions = this.endPosTable;
2627 return toplevel;
2628 }
2630 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2631 */
2632 JCTree importDeclaration() {
2633 int pos = token.pos;
2634 nextToken();
2635 boolean importStatic = false;
2636 if (token.kind == STATIC) {
2637 checkStaticImports();
2638 importStatic = true;
2639 nextToken();
2640 }
2641 JCExpression pid = toP(F.at(token.pos).Ident(ident()));
2642 do {
2643 int pos1 = token.pos;
2644 accept(DOT);
2645 if (token.kind == STAR) {
2646 pid = to(F.at(pos1).Select(pid, names.asterisk));
2647 nextToken();
2648 break;
2649 } else {
2650 pid = toP(F.at(pos1).Select(pid, ident()));
2651 }
2652 } while (token.kind == DOT);
2653 accept(SEMI);
2654 return toP(F.at(pos).Import(pid, importStatic));
2655 }
2657 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2658 * | ";"
2659 */
2660 JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
2661 int pos = token.pos;
2662 if (mods == null && token.kind == SEMI) {
2663 nextToken();
2664 return toP(F.at(pos).Skip());
2665 } else {
2666 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
2667 }
2668 }
2670 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2671 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2672 * @param mods Any modifiers starting the class or interface declaration
2673 * @param dc The documentation comment for the class, or null.
2674 */
2675 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
2676 if (token.kind == CLASS) {
2677 return classDeclaration(mods, dc);
2678 } else if (token.kind == INTERFACE) {
2679 return interfaceDeclaration(mods, dc);
2680 } else if (allowEnums) {
2681 if (token.kind == ENUM) {
2682 return enumDeclaration(mods, dc);
2683 } else {
2684 int pos = token.pos;
2685 List<JCTree> errs;
2686 if (token.kind == IDENTIFIER) {
2687 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2688 setErrorEndPos(token.pos);
2689 } else {
2690 errs = List.<JCTree>of(mods);
2691 }
2692 return toP(F.Exec(syntaxError(pos, errs, "expected3",
2693 CLASS, INTERFACE, ENUM)));
2694 }
2695 } else {
2696 if (token.kind == ENUM) {
2697 error(token.pos, "enums.not.supported.in.source", source.name);
2698 allowEnums = true;
2699 return enumDeclaration(mods, dc);
2700 }
2701 int pos = token.pos;
2702 List<JCTree> errs;
2703 if (token.kind == IDENTIFIER) {
2704 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2705 setErrorEndPos(token.pos);
2706 } else {
2707 errs = List.<JCTree>of(mods);
2708 }
2709 return toP(F.Exec(syntaxError(pos, errs, "expected2",
2710 CLASS, INTERFACE)));
2711 }
2712 }
2714 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2715 * [IMPLEMENTS TypeList] ClassBody
2716 * @param mods The modifiers starting the class declaration
2717 * @param dc The documentation comment for the class, or null.
2718 */
2719 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
2720 int pos = token.pos;
2721 accept(CLASS);
2722 Name name = ident();
2724 List<JCTypeParameter> typarams = typeParametersOpt();
2726 JCExpression extending = null;
2727 if (token.kind == EXTENDS) {
2728 nextToken();
2729 extending = parseType();
2730 }
2731 List<JCExpression> implementing = List.nil();
2732 if (token.kind == IMPLEMENTS) {
2733 nextToken();
2734 implementing = typeList();
2735 }
2736 List<JCTree> defs = classOrInterfaceBody(name, false);
2737 JCClassDecl result = toP(F.at(pos).ClassDef(
2738 mods, name, typarams, extending, implementing, defs));
2739 attach(result, dc);
2740 return result;
2741 }
2743 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2744 * [EXTENDS TypeList] InterfaceBody
2745 * @param mods The modifiers starting the interface declaration
2746 * @param dc The documentation comment for the interface, or null.
2747 */
2748 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
2749 int pos = token.pos;
2750 accept(INTERFACE);
2751 Name name = ident();
2753 List<JCTypeParameter> typarams = typeParametersOpt();
2755 List<JCExpression> extending = List.nil();
2756 if (token.kind == EXTENDS) {
2757 nextToken();
2758 extending = typeList();
2759 }
2760 List<JCTree> defs = classOrInterfaceBody(name, true);
2761 JCClassDecl result = toP(F.at(pos).ClassDef(
2762 mods, name, typarams, null, extending, defs));
2763 attach(result, dc);
2764 return result;
2765 }
2767 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2768 * @param mods The modifiers starting the enum declaration
2769 * @param dc The documentation comment for the enum, or null.
2770 */
2771 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
2772 int pos = token.pos;
2773 accept(ENUM);
2774 Name name = ident();
2776 List<JCExpression> implementing = List.nil();
2777 if (token.kind == IMPLEMENTS) {
2778 nextToken();
2779 implementing = typeList();
2780 }
2782 List<JCTree> defs = enumBody(name);
2783 mods.flags |= Flags.ENUM;
2784 JCClassDecl result = toP(F.at(pos).
2785 ClassDef(mods, name, List.<JCTypeParameter>nil(),
2786 null, implementing, defs));
2787 attach(result, dc);
2788 return result;
2789 }
2791 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2792 * [ ";" {ClassBodyDeclaration} ] "}"
2793 */
2794 List<JCTree> enumBody(Name enumName) {
2795 accept(LBRACE);
2796 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2797 if (token.kind == COMMA) {
2798 nextToken();
2799 } else if (token.kind != RBRACE && token.kind != SEMI) {
2800 defs.append(enumeratorDeclaration(enumName));
2801 while (token.kind == COMMA) {
2802 nextToken();
2803 if (token.kind == RBRACE || token.kind == SEMI) break;
2804 defs.append(enumeratorDeclaration(enumName));
2805 }
2806 if (token.kind != SEMI && token.kind != RBRACE) {
2807 defs.append(syntaxError(token.pos, "expected3",
2808 COMMA, RBRACE, SEMI));
2809 nextToken();
2810 }
2811 }
2812 if (token.kind == SEMI) {
2813 nextToken();
2814 while (token.kind != RBRACE && token.kind != EOF) {
2815 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2816 false));
2817 if (token.pos <= endPosTable.errorEndPos) {
2818 // error recovery
2819 skip(false, true, true, false);
2820 }
2821 }
2822 }
2823 accept(RBRACE);
2824 return defs.toList();
2825 }
2827 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2828 */
2829 JCTree enumeratorDeclaration(Name enumName) {
2830 Comment dc = token.comment(CommentStyle.JAVADOC);
2831 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2832 if (token.deprecatedFlag()) {
2833 flags |= Flags.DEPRECATED;
2834 }
2835 int pos = token.pos;
2836 List<JCAnnotation> annotations = annotationsOpt();
2837 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2838 List<JCExpression> typeArgs = typeArgumentsOpt();
2839 int identPos = token.pos;
2840 Name name = ident();
2841 int createPos = token.pos;
2842 List<JCExpression> args = (token.kind == LPAREN)
2843 ? arguments() : List.<JCExpression>nil();
2844 JCClassDecl body = null;
2845 if (token.kind == LBRACE) {
2846 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2847 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2848 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2849 }
2850 if (args.isEmpty() && body == null)
2851 createPos = identPos;
2852 JCIdent ident = F.at(identPos).Ident(enumName);
2853 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2854 if (createPos != identPos)
2855 storeEnd(create, S.prevToken().endPos);
2856 ident = F.at(identPos).Ident(enumName);
2857 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2858 attach(result, dc);
2859 return result;
2860 }
2862 /** TypeList = Type {"," Type}
2863 */
2864 List<JCExpression> typeList() {
2865 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2866 ts.append(parseType());
2867 while (token.kind == COMMA) {
2868 nextToken();
2869 ts.append(parseType());
2870 }
2871 return ts.toList();
2872 }
2874 /** ClassBody = "{" {ClassBodyDeclaration} "}"
2875 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2876 */
2877 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2878 accept(LBRACE);
2879 if (token.pos <= endPosTable.errorEndPos) {
2880 // error recovery
2881 skip(false, true, false, false);
2882 if (token.kind == LBRACE)
2883 nextToken();
2884 }
2885 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2886 while (token.kind != RBRACE && token.kind != EOF) {
2887 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2888 if (token.pos <= endPosTable.errorEndPos) {
2889 // error recovery
2890 skip(false, true, true, false);
2891 }
2892 }
2893 accept(RBRACE);
2894 return defs.toList();
2895 }
2897 /** ClassBodyDeclaration =
2898 * ";"
2899 * | [STATIC] Block
2900 * | ModifiersOpt
2901 * ( Type Ident
2902 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2903 * | VOID Ident MethodDeclaratorRest
2904 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2905 * | Ident ConstructorDeclaratorRest
2906 * | TypeParameters Ident ConstructorDeclaratorRest
2907 * | ClassOrInterfaceOrEnumDeclaration
2908 * )
2909 * InterfaceBodyDeclaration =
2910 * ";"
2911 * | ModifiersOpt Type Ident
2912 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2913 */
2914 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2915 if (token.kind == SEMI) {
2916 nextToken();
2917 return List.<JCTree>nil();
2918 } else {
2919 Comment dc = token.comment(CommentStyle.JAVADOC);
2920 int pos = token.pos;
2921 JCModifiers mods = modifiersOpt();
2922 if (token.kind == CLASS ||
2923 token.kind == INTERFACE ||
2924 allowEnums && token.kind == ENUM) {
2925 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2926 } else if (token.kind == LBRACE && !isInterface &&
2927 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2928 mods.annotations.isEmpty()) {
2929 return List.<JCTree>of(block(pos, mods.flags));
2930 } else {
2931 pos = token.pos;
2932 List<JCTypeParameter> typarams = typeParametersOpt();
2933 // if there are type parameters but no modifiers, save the start
2934 // position of the method in the modifiers.
2935 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
2936 mods.pos = pos;
2937 storeEnd(mods, pos);
2938 }
2939 Token tk = token;
2940 pos = token.pos;
2941 JCExpression type;
2942 boolean isVoid = token.kind == VOID;
2943 if (isVoid) {
2944 type = to(F.at(pos).TypeIdent(TypeTag.VOID));
2945 nextToken();
2946 } else {
2947 type = parseType();
2948 }
2949 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
2950 if (isInterface || tk.name() != className)
2951 error(pos, "invalid.meth.decl.ret.type.req");
2952 return List.of(methodDeclaratorRest(
2953 pos, mods, null, names.init, typarams,
2954 isInterface, true, dc));
2955 } else {
2956 pos = token.pos;
2957 Name name = ident();
2958 if (token.kind == LPAREN) {
2959 return List.of(methodDeclaratorRest(
2960 pos, mods, type, name, typarams,
2961 isInterface, isVoid, dc));
2962 } else if (!isVoid && typarams.isEmpty()) {
2963 List<JCTree> defs =
2964 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2965 new ListBuffer<JCTree>()).toList();
2966 storeEnd(defs.last(), token.endPos);
2967 accept(SEMI);
2968 return defs;
2969 } else {
2970 pos = token.pos;
2971 List<JCTree> err = isVoid
2972 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2973 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2974 : null;
2975 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
2976 }
2977 }
2978 }
2979 }
2980 }
2982 /** MethodDeclaratorRest =
2983 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2984 * VoidMethodDeclaratorRest =
2985 * FormalParameters [Throws TypeList] ( MethodBody | ";")
2986 * InterfaceMethodDeclaratorRest =
2987 * FormalParameters BracketsOpt [THROWS TypeList] ";"
2988 * VoidInterfaceMethodDeclaratorRest =
2989 * FormalParameters [THROWS TypeList] ";"
2990 * ConstructorDeclaratorRest =
2991 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2992 */
2993 protected JCTree methodDeclaratorRest(int pos,
2994 JCModifiers mods,
2995 JCExpression type,
2996 Name name,
2997 List<JCTypeParameter> typarams,
2998 boolean isInterface, boolean isVoid,
2999 Comment dc) {
3000 List<JCVariableDecl> params = formalParameters();
3001 if (!isVoid) type = bracketsOpt(type);
3002 List<JCExpression> thrown = List.nil();
3003 if (token.kind == THROWS) {
3004 nextToken();
3005 thrown = qualidentList();
3006 }
3007 JCBlock body = null;
3008 JCExpression defaultValue;
3009 if (token.kind == LBRACE) {
3010 body = block();
3011 defaultValue = null;
3012 } else {
3013 if (token.kind == DEFAULT) {
3014 accept(DEFAULT);
3015 defaultValue = annotationValue();
3016 } else {
3017 defaultValue = null;
3018 }
3019 accept(SEMI);
3020 if (token.pos <= endPosTable.errorEndPos) {
3021 // error recovery
3022 skip(false, true, false, false);
3023 if (token.kind == LBRACE) {
3024 body = block();
3025 }
3026 }
3027 }
3029 JCMethodDecl result =
3030 toP(F.at(pos).MethodDef(mods, name, type, typarams,
3031 params, thrown,
3032 body, defaultValue));
3033 attach(result, dc);
3034 return result;
3035 }
3037 /** QualidentList = Qualident {"," Qualident}
3038 */
3039 List<JCExpression> qualidentList() {
3040 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
3041 ts.append(qualident());
3042 while (token.kind == COMMA) {
3043 nextToken();
3044 ts.append(qualident());
3045 }
3046 return ts.toList();
3047 }
3049 /**
3050 * {@literal
3051 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
3052 * }
3053 */
3054 List<JCTypeParameter> typeParametersOpt() {
3055 if (token.kind == LT) {
3056 checkGenerics();
3057 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
3058 nextToken();
3059 typarams.append(typeParameter());
3060 while (token.kind == COMMA) {
3061 nextToken();
3062 typarams.append(typeParameter());
3063 }
3064 accept(GT);
3065 return typarams.toList();
3066 } else {
3067 return List.nil();
3068 }
3069 }
3071 /**
3072 * {@literal
3073 * TypeParameter = TypeVariable [TypeParameterBound]
3074 * TypeParameterBound = EXTENDS Type {"&" Type}
3075 * TypeVariable = Ident
3076 * }
3077 */
3078 JCTypeParameter typeParameter() {
3079 int pos = token.pos;
3080 Name name = ident();
3081 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
3082 if (token.kind == EXTENDS) {
3083 nextToken();
3084 bounds.append(parseType());
3085 while (token.kind == AMP) {
3086 nextToken();
3087 bounds.append(parseType());
3088 }
3089 }
3090 return toP(F.at(pos).TypeParameter(name, bounds.toList()));
3091 }
3093 /** FormalParameters = "(" [ FormalParameterList ] ")"
3094 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
3095 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
3096 */
3097 List<JCVariableDecl> formalParameters() {
3098 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3099 JCVariableDecl lastParam = null;
3100 accept(LPAREN);
3101 if (token.kind != RPAREN) {
3102 params.append(lastParam = formalParameter());
3103 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
3104 nextToken();
3105 params.append(lastParam = formalParameter());
3106 }
3107 }
3108 accept(RPAREN);
3109 return params.toList();
3110 }
3112 List<JCVariableDecl> implicitParameters(boolean hasParens) {
3113 if (hasParens) {
3114 accept(LPAREN);
3115 }
3116 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3117 if (token.kind != RPAREN && token.kind != ARROW) {
3118 params.append(implicitParameter());
3119 while (token.kind == COMMA) {
3120 nextToken();
3121 params.append(implicitParameter());
3122 }
3123 }
3124 if (hasParens) {
3125 accept(RPAREN);
3126 }
3127 return params.toList();
3128 }
3130 JCModifiers optFinal(long flags) {
3131 JCModifiers mods = modifiersOpt();
3132 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
3133 mods.flags |= flags;
3134 return mods;
3135 }
3137 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
3138 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
3139 */
3140 protected JCVariableDecl formalParameter() {
3141 JCModifiers mods = optFinal(Flags.PARAMETER);
3142 JCExpression type = parseType();
3143 if (token.kind == ELLIPSIS) {
3144 checkVarargs();
3145 mods.flags |= Flags.VARARGS;
3146 type = to(F.at(token.pos).TypeArray(type));
3147 nextToken();
3148 }
3149 return variableDeclaratorId(mods, type);
3150 }
3152 protected JCVariableDecl implicitParameter() {
3153 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
3154 return variableDeclaratorId(mods, null);
3155 }
3157 /* ---------- auxiliary methods -------------- */
3159 void error(int pos, String key, Object ... args) {
3160 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3161 }
3163 void error(DiagnosticPosition pos, String key, Object ... args) {
3164 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3165 }
3167 void warning(int pos, String key, Object ... args) {
3168 log.warning(pos, key, args);
3169 }
3171 /** Check that given tree is a legal expression statement.
3172 */
3173 protected JCExpression checkExprStat(JCExpression t) {
3174 if (!TreeInfo.isExpressionStatement(t)) {
3175 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
3176 error(ret, "not.stmt");
3177 return ret;
3178 } else {
3179 return t;
3180 }
3181 }
3183 /** Return precedence of operator represented by token,
3184 * -1 if token is not a binary operator. @see TreeInfo.opPrec
3185 */
3186 static int prec(TokenKind token) {
3187 JCTree.Tag oc = optag(token);
3188 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
3189 }
3191 /**
3192 * Return the lesser of two positions, making allowance for either one
3193 * being unset.
3194 */
3195 static int earlier(int pos1, int pos2) {
3196 if (pos1 == Position.NOPOS)
3197 return pos2;
3198 if (pos2 == Position.NOPOS)
3199 return pos1;
3200 return (pos1 < pos2 ? pos1 : pos2);
3201 }
3203 /** Return operation tag of binary operator represented by token,
3204 * No_TAG if token is not a binary operator.
3205 */
3206 static JCTree.Tag optag(TokenKind token) {
3207 switch (token) {
3208 case BARBAR:
3209 return OR;
3210 case AMPAMP:
3211 return AND;
3212 case BAR:
3213 return BITOR;
3214 case BAREQ:
3215 return BITOR_ASG;
3216 case CARET:
3217 return BITXOR;
3218 case CARETEQ:
3219 return BITXOR_ASG;
3220 case AMP:
3221 return BITAND;
3222 case AMPEQ:
3223 return BITAND_ASG;
3224 case EQEQ:
3225 return JCTree.Tag.EQ;
3226 case BANGEQ:
3227 return NE;
3228 case LT:
3229 return JCTree.Tag.LT;
3230 case GT:
3231 return JCTree.Tag.GT;
3232 case LTEQ:
3233 return LE;
3234 case GTEQ:
3235 return GE;
3236 case LTLT:
3237 return SL;
3238 case LTLTEQ:
3239 return SL_ASG;
3240 case GTGT:
3241 return SR;
3242 case GTGTEQ:
3243 return SR_ASG;
3244 case GTGTGT:
3245 return USR;
3246 case GTGTGTEQ:
3247 return USR_ASG;
3248 case PLUS:
3249 return JCTree.Tag.PLUS;
3250 case PLUSEQ:
3251 return PLUS_ASG;
3252 case SUB:
3253 return MINUS;
3254 case SUBEQ:
3255 return MINUS_ASG;
3256 case STAR:
3257 return MUL;
3258 case STAREQ:
3259 return MUL_ASG;
3260 case SLASH:
3261 return DIV;
3262 case SLASHEQ:
3263 return DIV_ASG;
3264 case PERCENT:
3265 return MOD;
3266 case PERCENTEQ:
3267 return MOD_ASG;
3268 case INSTANCEOF:
3269 return TYPETEST;
3270 default:
3271 return NO_TAG;
3272 }
3273 }
3275 /** Return operation tag of unary operator represented by token,
3276 * No_TAG if token is not a binary operator.
3277 */
3278 static JCTree.Tag unoptag(TokenKind token) {
3279 switch (token) {
3280 case PLUS:
3281 return POS;
3282 case SUB:
3283 return NEG;
3284 case BANG:
3285 return NOT;
3286 case TILDE:
3287 return COMPL;
3288 case PLUSPLUS:
3289 return PREINC;
3290 case SUBSUB:
3291 return PREDEC;
3292 default:
3293 return NO_TAG;
3294 }
3295 }
3297 /** Return type tag of basic type represented by token,
3298 * NONE if token is not a basic type identifier.
3299 */
3300 static TypeTag typetag(TokenKind token) {
3301 switch (token) {
3302 case BYTE:
3303 return TypeTag.BYTE;
3304 case CHAR:
3305 return TypeTag.CHAR;
3306 case SHORT:
3307 return TypeTag.SHORT;
3308 case INT:
3309 return TypeTag.INT;
3310 case LONG:
3311 return TypeTag.LONG;
3312 case FLOAT:
3313 return TypeTag.FLOAT;
3314 case DOUBLE:
3315 return TypeTag.DOUBLE;
3316 case BOOLEAN:
3317 return TypeTag.BOOLEAN;
3318 default:
3319 return TypeTag.NONE;
3320 }
3321 }
3323 void checkGenerics() {
3324 if (!allowGenerics) {
3325 error(token.pos, "generics.not.supported.in.source", source.name);
3326 allowGenerics = true;
3327 }
3328 }
3329 void checkVarargs() {
3330 if (!allowVarargs) {
3331 error(token.pos, "varargs.not.supported.in.source", source.name);
3332 allowVarargs = true;
3333 }
3334 }
3335 void checkForeach() {
3336 if (!allowForeach) {
3337 error(token.pos, "foreach.not.supported.in.source", source.name);
3338 allowForeach = true;
3339 }
3340 }
3341 void checkStaticImports() {
3342 if (!allowStaticImport) {
3343 error(token.pos, "static.import.not.supported.in.source", source.name);
3344 allowStaticImport = true;
3345 }
3346 }
3347 void checkAnnotations() {
3348 if (!allowAnnotations) {
3349 error(token.pos, "annotations.not.supported.in.source", source.name);
3350 allowAnnotations = true;
3351 }
3352 }
3353 void checkDiamond() {
3354 if (!allowDiamond) {
3355 error(token.pos, "diamond.not.supported.in.source", source.name);
3356 allowDiamond = true;
3357 }
3358 }
3359 void checkMulticatch() {
3360 if (!allowMulticatch) {
3361 error(token.pos, "multicatch.not.supported.in.source", source.name);
3362 allowMulticatch = true;
3363 }
3364 }
3365 void checkTryWithResources() {
3366 if (!allowTWR) {
3367 error(token.pos, "try.with.resources.not.supported.in.source", source.name);
3368 allowTWR = true;
3369 }
3370 }
3371 void checkLambda() {
3372 if (!allowLambda) {
3373 log.error(token.pos, "lambda.not.supported.in.source", source.name);
3374 allowLambda = true;
3375 }
3376 }
3377 void checkMethodReferences() {
3378 if (!allowMethodReferences) {
3379 log.error(token.pos, "method.references.not.supported.in.source", source.name);
3380 allowMethodReferences = true;
3381 }
3382 }
3383 void checkDefaultMethods() {
3384 if (!allowDefaultMethods) {
3385 log.error(token.pos, "default.methods.not.supported.in.source", source.name);
3386 allowDefaultMethods = true;
3387 }
3388 }
3390 /*
3391 * a functional source tree and end position mappings
3392 */
3393 protected class SimpleEndPosTable extends AbstractEndPosTable {
3395 private final Map<JCTree, Integer> endPosMap;
3397 SimpleEndPosTable() {
3398 endPosMap = new HashMap<JCTree, Integer>();
3399 }
3401 protected void storeEnd(JCTree tree, int endpos) {
3402 endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
3403 }
3405 protected <T extends JCTree> T to(T t) {
3406 storeEnd(t, token.endPos);
3407 return t;
3408 }
3410 protected <T extends JCTree> T toP(T t) {
3411 storeEnd(t, S.prevToken().endPos);
3412 return t;
3413 }
3415 public int getEndPos(JCTree tree) {
3416 Integer value = endPosMap.get(tree);
3417 return (value == null) ? Position.NOPOS : value;
3418 }
3420 public int replaceTree(JCTree oldTree, JCTree newTree) {
3421 Integer pos = endPosMap.remove(oldTree);
3422 if (pos != null) {
3423 endPosMap.put(newTree, pos);
3424 return pos;
3425 }
3426 return Position.NOPOS;
3427 }
3428 }
3430 /*
3431 * a default skeletal implementation without any mapping overhead.
3432 */
3433 protected class EmptyEndPosTable extends AbstractEndPosTable {
3435 protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
3437 protected <T extends JCTree> T to(T t) {
3438 return t;
3439 }
3441 protected <T extends JCTree> T toP(T t) {
3442 return t;
3443 }
3445 public int getEndPos(JCTree tree) {
3446 return Position.NOPOS;
3447 }
3449 public int replaceTree(JCTree oldTree, JCTree newTree) {
3450 return Position.NOPOS;
3451 }
3453 }
3455 protected abstract class AbstractEndPosTable implements EndPosTable {
3457 /**
3458 * Store the last error position.
3459 */
3460 protected int errorEndPos;
3462 /**
3463 * Store ending position for a tree, the value of which is the greater
3464 * of last error position and the given ending position.
3465 * @param tree The tree.
3466 * @param endpos The ending position to associate with the tree.
3467 */
3468 protected abstract void storeEnd(JCTree tree, int endpos);
3470 /**
3471 * Store current token's ending position for a tree, the value of which
3472 * will be the greater of last error position and the ending position of
3473 * the current token.
3474 * @param t The tree.
3475 */
3476 protected abstract <T extends JCTree> T to(T t);
3478 /**
3479 * Store current token's ending position for a tree, the value of which
3480 * will be the greater of last error position and the ending position of
3481 * the previous token.
3482 * @param t The tree.
3483 */
3484 protected abstract <T extends JCTree> T toP(T t);
3486 /**
3487 * Set the error position during the parsing phases, the value of which
3488 * will be set only if it is greater than the last stored error position.
3489 * @param errPos The error position
3490 */
3491 protected void setErrorEndPos(int errPos) {
3492 if (errPos > errorEndPos) {
3493 errorEndPos = errPos;
3494 }
3495 }
3496 }
3497 }