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