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