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