Wed, 21 Jan 2015 10:42:49 +0000
8069181: java.lang.AssertionError when compiling JDK 1.4 code in JDK 8
Summary: remove erroneous call to modifiersOpt() in variable parsing
Reviewed-by: jfranck, jlahoda
1 /*
2 * Copyright (c) 1999, 2013, 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.*;
52 /** The parser maps a token sequence into an abstract syntax
53 * tree. It operates by recursive descent, with code derived
54 * systematically from an LL(1) grammar. For efficiency reasons, an
55 * operator precedence scheme is used for parsing binary operation
56 * expressions.
57 *
58 * <p><b>This is NOT part of any supported API.
59 * If you write code that depends on this, you do so at your own risk.
60 * This code and its internal interfaces are subject to change or
61 * deletion without notice.</b>
62 */
63 public class JavacParser implements Parser {
65 /** The number of precedence levels of infix operators.
66 */
67 private static final int infixPrecedenceLevels = 10;
69 /** The scanner used for lexical analysis.
70 */
71 protected Lexer S;
73 /** The factory to be used for abstract syntax tree construction.
74 */
75 protected TreeMaker F;
77 /** The log to be used for error diagnostics.
78 */
79 private Log log;
81 /** The Source language setting. */
82 private Source source;
84 /** The name table. */
85 private Names names;
87 /** End position mappings container */
88 private final AbstractEndPosTable endPosTable;
90 // Because of javac's limited lookahead, some contexts are ambiguous in
91 // the presence of type annotations even though they are not ambiguous
92 // in the absence of type annotations. Consider this code:
93 // void m(String [] m) { }
94 // void m(String ... m) { }
95 // After parsing "String", javac calls bracketsOpt which immediately
96 // returns if the next character is not '['. Similarly, javac can see
97 // if the next token is ... and in that case parse an ellipsis. But in
98 // the presence of type annotations:
99 // void m(String @A [] m) { }
100 // void m(String @A ... m) { }
101 // no finite lookahead is enough to determine whether to read array
102 // levels or an ellipsis. Furthermore, if you call bracketsOpt, then
103 // bracketsOpt first reads all the leading annotations and only then
104 // discovers that it needs to fail. bracketsOpt needs a way to push
105 // back the extra annotations that it read. (But, bracketsOpt should
106 // not *always* be allowed to push back extra annotations that it finds
107 // -- in most contexts, any such extra annotation is an error.
108 //
109 // The following two variables permit type annotations that have
110 // already been read to be stored for later use. Alternate
111 // implementations are possible but would cause much larger changes to
112 // the parser.
114 /** Type annotations that have already been read but have not yet been used. **/
115 private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
117 /**
118 * If the parser notices extra annotations, then it either immediately
119 * issues an error (if this variable is false) or places the extra
120 * annotations in variable typeAnnotationsPushedBack (if this variable
121 * is true).
122 */
123 private boolean permitTypeAnnotationsPushBack = false;
125 interface ErrorRecoveryAction {
126 JCTree doRecover(JavacParser parser);
127 }
129 enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
130 BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
131 CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
132 }
134 /** Construct a parser from a given scanner, tree factory and log.
135 */
136 protected JavacParser(ParserFactory fac,
137 Lexer S,
138 boolean keepDocComments,
139 boolean keepLineMap,
140 boolean keepEndPositions) {
141 this.S = S;
142 nextToken(); // prime the pump
143 this.F = fac.F;
144 this.log = fac.log;
145 this.names = fac.names;
146 this.source = fac.source;
147 this.allowGenerics = source.allowGenerics();
148 this.allowVarargs = source.allowVarargs();
149 this.allowAsserts = source.allowAsserts();
150 this.allowEnums = source.allowEnums();
151 this.allowForeach = source.allowForeach();
152 this.allowStaticImport = source.allowStaticImport();
153 this.allowAnnotations = source.allowAnnotations();
154 this.allowTWR = source.allowTryWithResources();
155 this.allowDiamond = source.allowDiamond();
156 this.allowMulticatch = source.allowMulticatch();
157 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
158 this.allowLambda = source.allowLambda();
159 this.allowMethodReferences = source.allowMethodReferences();
160 this.allowDefaultMethods = source.allowDefaultMethods();
161 this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
162 this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
163 this.allowTypeAnnotations = source.allowTypeAnnotations();
164 this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams();
165 this.keepDocComments = keepDocComments;
166 docComments = newDocCommentTable(keepDocComments, fac);
167 this.keepLineMap = keepLineMap;
168 this.errorTree = F.Erroneous();
169 endPosTable = newEndPosTable(keepEndPositions);
170 }
172 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
173 return keepEndPositions
174 ? new SimpleEndPosTable(this)
175 : new EmptyEndPosTable(this);
176 }
178 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
179 return keepDocComments ? new LazyDocCommentTable(fac) : null;
180 }
182 /** Switch: Should generics be recognized?
183 */
184 boolean allowGenerics;
186 /** Switch: Should diamond operator be recognized?
187 */
188 boolean allowDiamond;
190 /** Switch: Should multicatch clause be accepted?
191 */
192 boolean allowMulticatch;
194 /** Switch: Should varargs be recognized?
195 */
196 boolean allowVarargs;
198 /** Switch: should we recognize assert statements, or just give a warning?
199 */
200 boolean allowAsserts;
202 /** Switch: should we recognize enums, or just give a warning?
203 */
204 boolean allowEnums;
206 /** Switch: should we recognize foreach?
207 */
208 boolean allowForeach;
210 /** Switch: should we recognize foreach?
211 */
212 boolean allowStaticImport;
214 /** Switch: should we recognize annotations?
215 */
216 boolean allowAnnotations;
218 /** Switch: should we recognize try-with-resources?
219 */
220 boolean allowTWR;
222 /** Switch: should we fold strings?
223 */
224 boolean allowStringFolding;
226 /** Switch: should we recognize lambda expressions?
227 */
228 boolean allowLambda;
230 /** Switch: should we allow method/constructor references?
231 */
232 boolean allowMethodReferences;
234 /** Switch: should we allow default methods in interfaces?
235 */
236 boolean allowDefaultMethods;
238 /** Switch: should we allow static methods in interfaces?
239 */
240 boolean allowStaticInterfaceMethods;
242 /** Switch: should we allow intersection types in cast?
243 */
244 boolean allowIntersectionTypesInCast;
246 /** Switch: should we keep docComments?
247 */
248 boolean keepDocComments;
250 /** Switch: should we keep line table?
251 */
252 boolean keepLineMap;
254 /** Switch: should we recognize type annotations?
255 */
256 boolean allowTypeAnnotations;
258 /** Switch: should we allow annotations after the method type parameters?
259 */
260 boolean allowAnnotationsAfterTypeParams;
262 /** Switch: is "this" allowed as an identifier?
263 * This is needed to parse receiver types.
264 */
265 boolean allowThisIdent;
267 /** The type of the method receiver, as specified by a first "this" parameter.
268 */
269 JCVariableDecl receiverParam;
272 /** When terms are parsed, the mode determines which is expected:
273 * mode = EXPR : an expression
274 * mode = TYPE : a type
275 * mode = NOPARAMS : no parameters allowed for type
276 * mode = TYPEARG : type argument
277 */
278 static final int EXPR = 0x1;
279 static final int TYPE = 0x2;
280 static final int NOPARAMS = 0x4;
281 static final int TYPEARG = 0x8;
282 static final int DIAMOND = 0x10;
284 /** The current mode.
285 */
286 private int mode = 0;
288 /** The mode of the term that was parsed last.
289 */
290 private int lastmode = 0;
292 /* ---------- token management -------------- */
294 protected Token token;
296 public Token token() {
297 return token;
298 }
300 public void nextToken() {
301 S.nextToken();
302 token = S.token();
303 }
305 protected boolean peekToken(Filter<TokenKind> tk) {
306 return peekToken(0, tk);
307 }
309 protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
310 return tk.accepts(S.token(lookahead + 1).kind);
311 }
313 protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
314 return peekToken(0, tk1, tk2);
315 }
317 protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
318 return tk1.accepts(S.token(lookahead + 1).kind) &&
319 tk2.accepts(S.token(lookahead + 2).kind);
320 }
322 protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
323 return peekToken(0, tk1, tk2, tk3);
324 }
326 protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
327 return tk1.accepts(S.token(lookahead + 1).kind) &&
328 tk2.accepts(S.token(lookahead + 2).kind) &&
329 tk3.accepts(S.token(lookahead + 3).kind);
330 }
332 @SuppressWarnings("unchecked")
333 protected boolean peekToken(Filter<TokenKind>... kinds) {
334 return peekToken(0, kinds);
335 }
337 @SuppressWarnings("unchecked")
338 protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
339 for (; lookahead < kinds.length ; lookahead++) {
340 if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
341 return false;
342 }
343 }
344 return true;
345 }
347 /* ---------- error recovery -------------- */
349 private JCErroneous errorTree;
351 /** Skip forward until a suitable stop token is found.
352 */
353 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
354 while (true) {
355 switch (token.kind) {
356 case SEMI:
357 nextToken();
358 return;
359 case PUBLIC:
360 case FINAL:
361 case ABSTRACT:
362 case MONKEYS_AT:
363 case EOF:
364 case CLASS:
365 case INTERFACE:
366 case ENUM:
367 return;
368 case IMPORT:
369 if (stopAtImport)
370 return;
371 break;
372 case LBRACE:
373 case RBRACE:
374 case PRIVATE:
375 case PROTECTED:
376 case STATIC:
377 case TRANSIENT:
378 case NATIVE:
379 case VOLATILE:
380 case SYNCHRONIZED:
381 case STRICTFP:
382 case LT:
383 case BYTE:
384 case SHORT:
385 case CHAR:
386 case INT:
387 case LONG:
388 case FLOAT:
389 case DOUBLE:
390 case BOOLEAN:
391 case VOID:
392 if (stopAtMemberDecl)
393 return;
394 break;
395 case UNDERSCORE:
396 case IDENTIFIER:
397 if (stopAtIdentifier)
398 return;
399 break;
400 case CASE:
401 case DEFAULT:
402 case IF:
403 case FOR:
404 case WHILE:
405 case DO:
406 case TRY:
407 case SWITCH:
408 case RETURN:
409 case THROW:
410 case BREAK:
411 case CONTINUE:
412 case ELSE:
413 case FINALLY:
414 case CATCH:
415 if (stopAtStatement)
416 return;
417 break;
418 }
419 nextToken();
420 }
421 }
423 private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
424 return syntaxError(pos, List.<JCTree>nil(), key, args);
425 }
427 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
428 setErrorEndPos(pos);
429 JCErroneous err = F.at(pos).Erroneous(errs);
430 reportSyntaxError(err, key, (Object[])args);
431 if (errs != null) {
432 JCTree last = errs.last();
433 if (last != null)
434 storeEnd(last, pos);
435 }
436 return toP(err);
437 }
439 private int errorPos = Position.NOPOS;
441 /**
442 * Report a syntax using the given the position parameter and arguments,
443 * unless one was already reported at the same position.
444 */
445 private void reportSyntaxError(int pos, String key, Object... args) {
446 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
447 reportSyntaxError(diag, key, args);
448 }
450 /**
451 * Report a syntax error using the given DiagnosticPosition object and
452 * arguments, unless one was already reported at the same position.
453 */
454 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
455 int pos = diagPos.getPreferredPosition();
456 if (pos > S.errPos() || pos == Position.NOPOS) {
457 if (token.kind == EOF) {
458 error(diagPos, "premature.eof");
459 } else {
460 error(diagPos, key, args);
461 }
462 }
463 S.errPos(pos);
464 if (token.pos == errorPos)
465 nextToken(); // guarantee progress
466 errorPos = token.pos;
467 }
470 /** Generate a syntax error at current position unless one was already
471 * reported at the same position.
472 */
473 private JCErroneous syntaxError(String key) {
474 return syntaxError(token.pos, key);
475 }
477 /** Generate a syntax error at current position unless one was
478 * already reported at the same position.
479 */
480 private JCErroneous syntaxError(String key, TokenKind arg) {
481 return syntaxError(token.pos, key, arg);
482 }
484 /** If next input token matches given token, skip it, otherwise report
485 * an error.
486 */
487 public void accept(TokenKind tk) {
488 if (token.kind == tk) {
489 nextToken();
490 } else {
491 setErrorEndPos(token.pos);
492 reportSyntaxError(S.prevToken().endPos, "expected", tk);
493 }
494 }
496 /** Report an illegal start of expression/type error at given position.
497 */
498 JCExpression illegal(int pos) {
499 setErrorEndPos(pos);
500 if ((mode & EXPR) != 0)
501 return syntaxError(pos, "illegal.start.of.expr");
502 else
503 return syntaxError(pos, "illegal.start.of.type");
505 }
507 /** Report an illegal start of expression/type error at current position.
508 */
509 JCExpression illegal() {
510 return illegal(token.pos);
511 }
513 /** Diagnose a modifier flag from the set, if any. */
514 void checkNoMods(long mods) {
515 if (mods != 0) {
516 long lowestMod = mods & -mods;
517 error(token.pos, "mod.not.allowed.here",
518 Flags.asFlagSet(lowestMod));
519 }
520 }
522 /* ---------- doc comments --------- */
524 /** A table to store all documentation comments
525 * indexed by the tree nodes they refer to.
526 * defined only if option flag keepDocComment is set.
527 */
528 private final DocCommentTable docComments;
530 /** Make an entry into docComments hashtable,
531 * provided flag keepDocComments is set and given doc comment is non-null.
532 * @param tree The tree to be used as index in the hashtable
533 * @param dc The doc comment to associate with the tree, or null.
534 */
535 void attach(JCTree tree, Comment dc) {
536 if (keepDocComments && dc != null) {
537 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
538 docComments.putComment(tree, dc);
539 }
540 }
542 /* -------- source positions ------- */
544 private void setErrorEndPos(int errPos) {
545 endPosTable.setErrorEndPos(errPos);
546 }
548 private void storeEnd(JCTree tree, int endpos) {
549 endPosTable.storeEnd(tree, endpos);
550 }
552 private <T extends JCTree> T to(T t) {
553 return endPosTable.to(t);
554 }
556 private <T extends JCTree> T toP(T t) {
557 return endPosTable.toP(t);
558 }
560 /** Get the start position for a tree node. The start position is
561 * defined to be the position of the first character of the first
562 * token of the node's source text.
563 * @param tree The tree node
564 */
565 public int getStartPos(JCTree tree) {
566 return TreeInfo.getStartPos(tree);
567 }
569 /**
570 * Get the end position for a tree node. The end position is
571 * defined to be the position of the last character of the last
572 * token of the node's source text. Returns Position.NOPOS if end
573 * positions are not generated or the position is otherwise not
574 * found.
575 * @param tree The tree node
576 */
577 public int getEndPos(JCTree tree) {
578 return endPosTable.getEndPos(tree);
579 }
583 /* ---------- parsing -------------- */
585 /**
586 * Ident = IDENTIFIER
587 */
588 Name ident() {
589 if (token.kind == IDENTIFIER) {
590 Name name = token.name();
591 nextToken();
592 return name;
593 } else if (token.kind == ASSERT) {
594 if (allowAsserts) {
595 error(token.pos, "assert.as.identifier");
596 nextToken();
597 return names.error;
598 } else {
599 warning(token.pos, "assert.as.identifier");
600 Name name = token.name();
601 nextToken();
602 return name;
603 }
604 } else if (token.kind == ENUM) {
605 if (allowEnums) {
606 error(token.pos, "enum.as.identifier");
607 nextToken();
608 return names.error;
609 } else {
610 warning(token.pos, "enum.as.identifier");
611 Name name = token.name();
612 nextToken();
613 return name;
614 }
615 } else if (token.kind == THIS) {
616 if (allowThisIdent) {
617 // Make sure we're using a supported source version.
618 checkTypeAnnotations();
619 Name name = token.name();
620 nextToken();
621 return name;
622 } else {
623 error(token.pos, "this.as.identifier");
624 nextToken();
625 return names.error;
626 }
627 } else if (token.kind == UNDERSCORE) {
628 warning(token.pos, "underscore.as.identifier");
629 Name name = token.name();
630 nextToken();
631 return name;
632 } else {
633 accept(IDENTIFIER);
634 return names.error;
635 }
636 }
638 /**
639 * Qualident = Ident { DOT [Annotations] Ident }
640 */
641 public JCExpression qualident(boolean allowAnnos) {
642 JCExpression t = toP(F.at(token.pos).Ident(ident()));
643 while (token.kind == DOT) {
644 int pos = token.pos;
645 nextToken();
646 List<JCAnnotation> tyannos = null;
647 if (allowAnnos) {
648 tyannos = typeAnnotationsOpt();
649 }
650 t = toP(F.at(pos).Select(t, ident()));
651 if (tyannos != null && tyannos.nonEmpty()) {
652 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
653 }
654 }
655 return t;
656 }
658 JCExpression literal(Name prefix) {
659 return literal(prefix, token.pos);
660 }
662 /**
663 * Literal =
664 * INTLITERAL
665 * | LONGLITERAL
666 * | FLOATLITERAL
667 * | DOUBLELITERAL
668 * | CHARLITERAL
669 * | STRINGLITERAL
670 * | TRUE
671 * | FALSE
672 * | NULL
673 */
674 JCExpression literal(Name prefix, int pos) {
675 JCExpression t = errorTree;
676 switch (token.kind) {
677 case INTLITERAL:
678 try {
679 t = F.at(pos).Literal(
680 TypeTag.INT,
681 Convert.string2int(strval(prefix), token.radix()));
682 } catch (NumberFormatException ex) {
683 error(token.pos, "int.number.too.large", strval(prefix));
684 }
685 break;
686 case LONGLITERAL:
687 try {
688 t = F.at(pos).Literal(
689 TypeTag.LONG,
690 new Long(Convert.string2long(strval(prefix), token.radix())));
691 } catch (NumberFormatException ex) {
692 error(token.pos, "int.number.too.large", strval(prefix));
693 }
694 break;
695 case FLOATLITERAL: {
696 String proper = token.radix() == 16 ?
697 ("0x"+ token.stringVal()) :
698 token.stringVal();
699 Float n;
700 try {
701 n = Float.valueOf(proper);
702 } catch (NumberFormatException ex) {
703 // error already reported in scanner
704 n = Float.NaN;
705 }
706 if (n.floatValue() == 0.0f && !isZero(proper))
707 error(token.pos, "fp.number.too.small");
708 else if (n.floatValue() == Float.POSITIVE_INFINITY)
709 error(token.pos, "fp.number.too.large");
710 else
711 t = F.at(pos).Literal(TypeTag.FLOAT, n);
712 break;
713 }
714 case DOUBLELITERAL: {
715 String proper = token.radix() == 16 ?
716 ("0x"+ token.stringVal()) :
717 token.stringVal();
718 Double n;
719 try {
720 n = Double.valueOf(proper);
721 } catch (NumberFormatException ex) {
722 // error already reported in scanner
723 n = Double.NaN;
724 }
725 if (n.doubleValue() == 0.0d && !isZero(proper))
726 error(token.pos, "fp.number.too.small");
727 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
728 error(token.pos, "fp.number.too.large");
729 else
730 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
731 break;
732 }
733 case CHARLITERAL:
734 t = F.at(pos).Literal(
735 TypeTag.CHAR,
736 token.stringVal().charAt(0) + 0);
737 break;
738 case STRINGLITERAL:
739 t = F.at(pos).Literal(
740 TypeTag.CLASS,
741 token.stringVal());
742 break;
743 case TRUE: case FALSE:
744 t = F.at(pos).Literal(
745 TypeTag.BOOLEAN,
746 (token.kind == TRUE ? 1 : 0));
747 break;
748 case NULL:
749 t = F.at(pos).Literal(
750 TypeTag.BOT,
751 null);
752 break;
753 default:
754 Assert.error();
755 }
756 if (t == errorTree)
757 t = F.at(pos).Erroneous();
758 storeEnd(t, token.endPos);
759 nextToken();
760 return t;
761 }
762 //where
763 boolean isZero(String s) {
764 char[] cs = s.toCharArray();
765 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
766 int i = ((base==16) ? 2 : 0);
767 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
768 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
769 }
771 String strval(Name prefix) {
772 String s = token.stringVal();
773 return prefix.isEmpty() ? s : prefix + s;
774 }
776 /** terms can be either expressions or types.
777 */
778 public JCExpression parseExpression() {
779 return term(EXPR);
780 }
782 /**
783 * parses (optional) type annotations followed by a type. If the
784 * annotations are present before the type and are not consumed during array
785 * parsing, this method returns a {@link JCAnnotatedType} consisting of
786 * these annotations and the underlying type. Otherwise, it returns the
787 * underlying type.
788 *
789 * <p>
790 *
791 * Note that this method sets {@code mode} to {@code TYPE} first, before
792 * parsing annotations.
793 */
794 public JCExpression parseType() {
795 List<JCAnnotation> annotations = typeAnnotationsOpt();
796 return parseType(annotations);
797 }
799 public JCExpression parseType(List<JCAnnotation> annotations) {
800 JCExpression result = unannotatedType();
802 if (annotations.nonEmpty()) {
803 result = insertAnnotationsToMostInner(result, annotations, false);
804 }
806 return result;
807 }
809 public JCExpression unannotatedType() {
810 return term(TYPE);
811 }
813 JCExpression term(int newmode) {
814 int prevmode = mode;
815 mode = newmode;
816 JCExpression t = term();
817 lastmode = mode;
818 mode = prevmode;
819 return t;
820 }
822 /**
823 * {@literal
824 * Expression = Expression1 [ExpressionRest]
825 * ExpressionRest = [AssignmentOperator Expression1]
826 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
827 * "&=" | "|=" | "^=" |
828 * "%=" | "<<=" | ">>=" | ">>>="
829 * Type = Type1
830 * TypeNoParams = TypeNoParams1
831 * StatementExpression = Expression
832 * ConstantExpression = Expression
833 * }
834 */
835 JCExpression term() {
836 JCExpression t = term1();
837 if ((mode & EXPR) != 0 &&
838 token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
839 return termRest(t);
840 else
841 return t;
842 }
844 JCExpression termRest(JCExpression t) {
845 switch (token.kind) {
846 case EQ: {
847 int pos = token.pos;
848 nextToken();
849 mode = EXPR;
850 JCExpression t1 = term();
851 return toP(F.at(pos).Assign(t, t1));
852 }
853 case PLUSEQ:
854 case SUBEQ:
855 case STAREQ:
856 case SLASHEQ:
857 case PERCENTEQ:
858 case AMPEQ:
859 case BAREQ:
860 case CARETEQ:
861 case LTLTEQ:
862 case GTGTEQ:
863 case GTGTGTEQ:
864 int pos = token.pos;
865 TokenKind tk = token.kind;
866 nextToken();
867 mode = EXPR;
868 JCExpression t1 = term();
869 return F.at(pos).Assignop(optag(tk), t, t1);
870 default:
871 return t;
872 }
873 }
875 /** Expression1 = Expression2 [Expression1Rest]
876 * Type1 = Type2
877 * TypeNoParams1 = TypeNoParams2
878 */
879 JCExpression term1() {
880 JCExpression t = term2();
881 if ((mode & EXPR) != 0 && token.kind == QUES) {
882 mode = EXPR;
883 return term1Rest(t);
884 } else {
885 return t;
886 }
887 }
889 /** Expression1Rest = ["?" Expression ":" Expression1]
890 */
891 JCExpression term1Rest(JCExpression t) {
892 if (token.kind == QUES) {
893 int pos = token.pos;
894 nextToken();
895 JCExpression t1 = term();
896 accept(COLON);
897 JCExpression t2 = term1();
898 return F.at(pos).Conditional(t, t1, t2);
899 } else {
900 return t;
901 }
902 }
904 /** Expression2 = Expression3 [Expression2Rest]
905 * Type2 = Type3
906 * TypeNoParams2 = TypeNoParams3
907 */
908 JCExpression term2() {
909 JCExpression t = term3();
910 if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
911 mode = EXPR;
912 return term2Rest(t, TreeInfo.orPrec);
913 } else {
914 return t;
915 }
916 }
918 /* Expression2Rest = {infixop Expression3}
919 * | Expression3 instanceof Type
920 * infixop = "||"
921 * | "&&"
922 * | "|"
923 * | "^"
924 * | "&"
925 * | "==" | "!="
926 * | "<" | ">" | "<=" | ">="
927 * | "<<" | ">>" | ">>>"
928 * | "+" | "-"
929 * | "*" | "/" | "%"
930 */
931 JCExpression term2Rest(JCExpression t, int minprec) {
932 JCExpression[] odStack = newOdStack();
933 Token[] opStack = newOpStack();
935 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
936 int top = 0;
937 odStack[0] = t;
938 int startPos = token.pos;
939 Token topOp = Tokens.DUMMY;
940 while (prec(token.kind) >= minprec) {
941 opStack[top] = topOp;
942 top++;
943 topOp = token;
944 nextToken();
945 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
946 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
947 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
948 odStack[top]);
949 top--;
950 topOp = opStack[top];
951 }
952 }
953 Assert.check(top == 0);
954 t = odStack[0];
956 if (t.hasTag(JCTree.Tag.PLUS)) {
957 StringBuilder buf = foldStrings(t);
958 if (buf != null) {
959 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
960 }
961 }
963 odStackSupply.add(odStack);
964 opStackSupply.add(opStack);
965 return t;
966 }
967 //where
968 /** Construct a binary or type test node.
969 */
970 private JCExpression makeOp(int pos,
971 TokenKind topOp,
972 JCExpression od1,
973 JCExpression od2)
974 {
975 if (topOp == INSTANCEOF) {
976 return F.at(pos).TypeTest(od1, od2);
977 } else {
978 return F.at(pos).Binary(optag(topOp), od1, od2);
979 }
980 }
981 /** If tree is a concatenation of string literals, replace it
982 * by a single literal representing the concatenated string.
983 */
984 protected StringBuilder foldStrings(JCTree tree) {
985 if (!allowStringFolding)
986 return null;
987 List<String> buf = List.nil();
988 while (true) {
989 if (tree.hasTag(LITERAL)) {
990 JCLiteral lit = (JCLiteral) tree;
991 if (lit.typetag == TypeTag.CLASS) {
992 StringBuilder sbuf =
993 new StringBuilder((String)lit.value);
994 while (buf.nonEmpty()) {
995 sbuf.append(buf.head);
996 buf = buf.tail;
997 }
998 return sbuf;
999 }
1000 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
1001 JCBinary op = (JCBinary)tree;
1002 if (op.rhs.hasTag(LITERAL)) {
1003 JCLiteral lit = (JCLiteral) op.rhs;
1004 if (lit.typetag == TypeTag.CLASS) {
1005 buf = buf.prepend((String) lit.value);
1006 tree = op.lhs;
1007 continue;
1008 }
1009 }
1010 }
1011 return null;
1012 }
1013 }
1015 /** optimization: To save allocating a new operand/operator stack
1016 * for every binary operation, we use supplys.
1017 */
1018 ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
1019 ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
1021 private JCExpression[] newOdStack() {
1022 if (odStackSupply.isEmpty())
1023 return new JCExpression[infixPrecedenceLevels + 1];
1024 return odStackSupply.remove(odStackSupply.size() - 1);
1025 }
1027 private Token[] newOpStack() {
1028 if (opStackSupply.isEmpty())
1029 return new Token[infixPrecedenceLevels + 1];
1030 return opStackSupply.remove(opStackSupply.size() - 1);
1031 }
1033 /**
1034 * Expression3 = PrefixOp Expression3
1035 * | "(" Expr | TypeNoParams ")" Expression3
1036 * | Primary {Selector} {PostfixOp}
1037 *
1038 * {@literal
1039 * Primary = "(" Expression ")"
1040 * | Literal
1041 * | [TypeArguments] THIS [Arguments]
1042 * | [TypeArguments] SUPER SuperSuffix
1043 * | NEW [TypeArguments] Creator
1044 * | "(" Arguments ")" "->" ( Expression | Block )
1045 * | Ident "->" ( Expression | Block )
1046 * | [Annotations] Ident { "." [Annotations] Ident }
1047 * | Expression3 MemberReferenceSuffix
1048 * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
1049 * | Arguments
1050 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
1051 * ]
1052 * | BasicType BracketsOpt "." CLASS
1053 * }
1054 *
1055 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
1056 * PostfixOp = "++" | "--"
1057 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
1058 * | BasicType
1059 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
1060 * Selector = "." [TypeArguments] Ident [Arguments]
1061 * | "." THIS
1062 * | "." [TypeArguments] SUPER SuperSuffix
1063 * | "." NEW [TypeArguments] InnerCreator
1064 * | "[" Expression "]"
1065 * TypeSelector = "." Ident [TypeArguments]
1066 * SuperSuffix = Arguments | "." Ident [Arguments]
1067 */
1068 protected JCExpression term3() {
1069 int pos = token.pos;
1070 JCExpression t;
1071 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
1072 switch (token.kind) {
1073 case QUES:
1074 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
1075 mode = TYPE;
1076 return typeArgument();
1077 } else
1078 return illegal();
1079 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
1080 if (typeArgs == null && (mode & EXPR) != 0) {
1081 TokenKind tk = token.kind;
1082 nextToken();
1083 mode = EXPR;
1084 if (tk == SUB &&
1085 (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
1086 token.radix() == 10) {
1087 mode = EXPR;
1088 t = literal(names.hyphen, pos);
1089 } else {
1090 t = term3();
1091 return F.at(pos).Unary(unoptag(tk), t);
1092 }
1093 } else return illegal();
1094 break;
1095 case LPAREN:
1096 if (typeArgs == null && (mode & EXPR) != 0) {
1097 ParensResult pres = analyzeParens();
1098 switch (pres) {
1099 case CAST:
1100 accept(LPAREN);
1101 mode = TYPE;
1102 int pos1 = pos;
1103 List<JCExpression> targets = List.of(t = term3());
1104 while (token.kind == AMP) {
1105 checkIntersectionTypesInCast();
1106 accept(AMP);
1107 targets = targets.prepend(term3());
1108 }
1109 if (targets.length() > 1) {
1110 t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
1111 }
1112 accept(RPAREN);
1113 mode = EXPR;
1114 JCExpression t1 = term3();
1115 return F.at(pos).TypeCast(t, t1);
1116 case IMPLICIT_LAMBDA:
1117 case EXPLICIT_LAMBDA:
1118 t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
1119 break;
1120 default: //PARENS
1121 accept(LPAREN);
1122 mode = EXPR;
1123 t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
1124 accept(RPAREN);
1125 t = toP(F.at(pos).Parens(t));
1126 break;
1127 }
1128 } else {
1129 return illegal();
1130 }
1131 break;
1132 case THIS:
1133 if ((mode & EXPR) != 0) {
1134 mode = EXPR;
1135 t = to(F.at(pos).Ident(names._this));
1136 nextToken();
1137 if (typeArgs == null)
1138 t = argumentsOpt(null, t);
1139 else
1140 t = arguments(typeArgs, t);
1141 typeArgs = null;
1142 } else return illegal();
1143 break;
1144 case SUPER:
1145 if ((mode & EXPR) != 0) {
1146 mode = EXPR;
1147 t = to(F.at(pos).Ident(names._super));
1148 t = superSuffix(typeArgs, t);
1149 typeArgs = null;
1150 } else return illegal();
1151 break;
1152 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1153 case CHARLITERAL: case STRINGLITERAL:
1154 case TRUE: case FALSE: case NULL:
1155 if (typeArgs == null && (mode & EXPR) != 0) {
1156 mode = EXPR;
1157 t = literal(names.empty);
1158 } else return illegal();
1159 break;
1160 case NEW:
1161 if (typeArgs != null) return illegal();
1162 if ((mode & EXPR) != 0) {
1163 mode = EXPR;
1164 nextToken();
1165 if (token.kind == LT) typeArgs = typeArguments(false);
1166 t = creator(pos, typeArgs);
1167 typeArgs = null;
1168 } else return illegal();
1169 break;
1170 case MONKEYS_AT:
1171 // Only annotated cast types and method references are valid
1172 List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
1173 if (typeAnnos.isEmpty()) {
1174 // else there would be no '@'
1175 throw new AssertionError("Expected type annotations, but found none!");
1176 }
1178 JCExpression expr = term3();
1180 if ((mode & TYPE) == 0) {
1181 // Type annotations on class literals no longer legal
1182 switch (expr.getTag()) {
1183 case REFERENCE: {
1184 JCMemberReference mref = (JCMemberReference) expr;
1185 mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
1186 t = mref;
1187 break;
1188 }
1189 case SELECT: {
1190 JCFieldAccess sel = (JCFieldAccess) expr;
1192 if (sel.name != names._class) {
1193 return illegal();
1194 } else {
1195 log.error(token.pos, "no.annotations.on.dot.class");
1196 return expr;
1197 }
1198 }
1199 default:
1200 return illegal(typeAnnos.head.pos);
1201 }
1203 } else {
1204 // Type annotations targeting a cast
1205 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1206 }
1207 break;
1208 case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1209 if (typeArgs != null) return illegal();
1210 if ((mode & EXPR) != 0 && peekToken(ARROW)) {
1211 t = lambdaExpressionOrStatement(false, false, pos);
1212 } else {
1213 t = toP(F.at(token.pos).Ident(ident()));
1214 loop: while (true) {
1215 pos = token.pos;
1216 final List<JCAnnotation> annos = typeAnnotationsOpt();
1218 // need to report an error later if LBRACKET is for array
1219 // index access rather than array creation level
1220 if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1221 return illegal(annos.head.pos);
1223 switch (token.kind) {
1224 case LBRACKET:
1225 nextToken();
1226 if (token.kind == RBRACKET) {
1227 nextToken();
1228 t = bracketsOpt(t);
1229 t = toP(F.at(pos).TypeArray(t));
1230 if (annos.nonEmpty()) {
1231 t = toP(F.at(pos).AnnotatedType(annos, t));
1232 }
1233 // .class is only allowed if there were no annotations
1234 JCExpression nt = bracketsSuffix(t);
1235 if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) {
1236 // t and nt are different if bracketsSuffix parsed a .class.
1237 // The check for nonEmpty covers the case when the whole array is annotated.
1238 // Helper method isAnnotated looks for annos deeply within t.
1239 syntaxError("no.annotations.on.dot.class");
1240 }
1241 t = nt;
1242 } else {
1243 if ((mode & EXPR) != 0) {
1244 mode = EXPR;
1245 JCExpression t1 = term();
1246 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1247 t = to(F.at(pos).Indexed(t, t1));
1248 }
1249 accept(RBRACKET);
1250 }
1251 break loop;
1252 case LPAREN:
1253 if ((mode & EXPR) != 0) {
1254 mode = EXPR;
1255 t = arguments(typeArgs, t);
1256 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1257 typeArgs = null;
1258 }
1259 break loop;
1260 case DOT:
1261 nextToken();
1262 int oldmode = mode;
1263 mode &= ~NOPARAMS;
1264 typeArgs = typeArgumentsOpt(EXPR);
1265 mode = oldmode;
1266 if ((mode & EXPR) != 0) {
1267 switch (token.kind) {
1268 case CLASS:
1269 if (typeArgs != null) return illegal();
1270 mode = EXPR;
1271 t = to(F.at(pos).Select(t, names._class));
1272 nextToken();
1273 break loop;
1274 case THIS:
1275 if (typeArgs != null) return illegal();
1276 mode = EXPR;
1277 t = to(F.at(pos).Select(t, names._this));
1278 nextToken();
1279 break loop;
1280 case SUPER:
1281 mode = EXPR;
1282 t = to(F.at(pos).Select(t, names._super));
1283 t = superSuffix(typeArgs, t);
1284 typeArgs = null;
1285 break loop;
1286 case NEW:
1287 if (typeArgs != null) return illegal();
1288 mode = EXPR;
1289 int pos1 = token.pos;
1290 nextToken();
1291 if (token.kind == LT) typeArgs = typeArguments(false);
1292 t = innerCreator(pos1, typeArgs, t);
1293 typeArgs = null;
1294 break loop;
1295 }
1296 }
1298 List<JCAnnotation> tyannos = null;
1299 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
1300 tyannos = typeAnnotationsOpt();
1301 }
1302 // typeArgs saved for next loop iteration.
1303 t = toP(F.at(pos).Select(t, ident()));
1304 if (tyannos != null && tyannos.nonEmpty()) {
1305 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1306 }
1307 break;
1308 case ELLIPSIS:
1309 if (this.permitTypeAnnotationsPushBack) {
1310 this.typeAnnotationsPushedBack = annos;
1311 } else if (annos.nonEmpty()) {
1312 // Don't return here -- error recovery attempt
1313 illegal(annos.head.pos);
1314 }
1315 break loop;
1316 case LT:
1317 if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
1318 //this is an unbound method reference whose qualifier
1319 //is a generic type i.e. A<S>::m
1320 int pos1 = token.pos;
1321 accept(LT);
1322 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
1323 args.append(typeArgument());
1324 while (token.kind == COMMA) {
1325 nextToken();
1326 args.append(typeArgument());
1327 }
1328 accept(GT);
1329 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1330 checkGenerics();
1331 while (token.kind == DOT) {
1332 nextToken();
1333 mode = TYPE;
1334 t = toP(F.at(token.pos).Select(t, ident()));
1335 t = typeArgumentsOpt(t);
1336 }
1337 t = bracketsOpt(t);
1338 if (token.kind != COLCOL) {
1339 //method reference expected here
1340 t = illegal();
1341 }
1342 mode = EXPR;
1343 return term3Rest(t, typeArgs);
1344 }
1345 break loop;
1346 default:
1347 break loop;
1348 }
1349 }
1350 }
1351 if (typeArgs != null) illegal();
1352 t = typeArgumentsOpt(t);
1353 break;
1354 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1355 case DOUBLE: case BOOLEAN:
1356 if (typeArgs != null) illegal();
1357 t = bracketsSuffix(bracketsOpt(basicType()));
1358 break;
1359 case VOID:
1360 if (typeArgs != null) illegal();
1361 if ((mode & EXPR) != 0) {
1362 nextToken();
1363 if (token.kind == DOT) {
1364 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1365 t = bracketsSuffix(ti);
1366 } else {
1367 return illegal(pos);
1368 }
1369 } else {
1370 // Support the corner case of myMethodHandle.<void>invoke() by passing
1371 // a void type (like other primitive types) to the next phase.
1372 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1373 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1374 nextToken();
1375 return ti;
1376 //return illegal();
1377 }
1378 break;
1379 default:
1380 return illegal();
1381 }
1382 return term3Rest(t, typeArgs);
1383 }
1385 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1386 if (typeArgs != null) illegal();
1387 while (true) {
1388 int pos1 = token.pos;
1389 final List<JCAnnotation> annos = typeAnnotationsOpt();
1391 if (token.kind == LBRACKET) {
1392 nextToken();
1393 if ((mode & TYPE) != 0) {
1394 int oldmode = mode;
1395 mode = TYPE;
1396 if (token.kind == RBRACKET) {
1397 nextToken();
1398 t = bracketsOpt(t);
1399 t = toP(F.at(pos1).TypeArray(t));
1400 if (token.kind == COLCOL) {
1401 mode = EXPR;
1402 continue;
1403 }
1404 if (annos.nonEmpty()) {
1405 t = toP(F.at(pos1).AnnotatedType(annos, t));
1406 }
1407 return t;
1408 }
1409 mode = oldmode;
1410 }
1411 if ((mode & EXPR) != 0) {
1412 mode = EXPR;
1413 JCExpression t1 = term();
1414 t = to(F.at(pos1).Indexed(t, t1));
1415 }
1416 accept(RBRACKET);
1417 } else if (token.kind == DOT) {
1418 nextToken();
1419 typeArgs = typeArgumentsOpt(EXPR);
1420 if (token.kind == SUPER && (mode & EXPR) != 0) {
1421 mode = EXPR;
1422 t = to(F.at(pos1).Select(t, names._super));
1423 nextToken();
1424 t = arguments(typeArgs, t);
1425 typeArgs = null;
1426 } else if (token.kind == NEW && (mode & EXPR) != 0) {
1427 if (typeArgs != null) return illegal();
1428 mode = EXPR;
1429 int pos2 = token.pos;
1430 nextToken();
1431 if (token.kind == LT) typeArgs = typeArguments(false);
1432 t = innerCreator(pos2, typeArgs, t);
1433 typeArgs = null;
1434 } else {
1435 List<JCAnnotation> tyannos = null;
1436 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
1437 // is the mode check needed?
1438 tyannos = typeAnnotationsOpt();
1439 }
1440 t = toP(F.at(pos1).Select(t, ident()));
1441 if (tyannos != null && tyannos.nonEmpty()) {
1442 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1443 }
1444 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1445 typeArgs = null;
1446 }
1447 } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
1448 mode = EXPR;
1449 if (typeArgs != null) return illegal();
1450 accept(COLCOL);
1451 t = memberReferenceSuffix(pos1, t);
1452 } else {
1453 if (!annos.isEmpty()) {
1454 if (permitTypeAnnotationsPushBack)
1455 typeAnnotationsPushedBack = annos;
1456 else
1457 return illegal(annos.head.pos);
1458 }
1459 break;
1460 }
1461 }
1462 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
1463 mode = EXPR;
1464 t = to(F.at(token.pos).Unary(
1465 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1466 nextToken();
1467 }
1468 return toP(t);
1469 }
1471 /**
1472 * If we see an identifier followed by a '<' it could be an unbound
1473 * method reference or a binary expression. To disambiguate, look for a
1474 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1475 */
1476 @SuppressWarnings("fallthrough")
1477 boolean isUnboundMemberRef() {
1478 int pos = 0, depth = 0;
1479 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1480 switch (t.kind) {
1481 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1482 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1483 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1484 case DOUBLE: case BOOLEAN: case CHAR:
1485 case MONKEYS_AT:
1486 break;
1488 case LPAREN:
1489 // skip annotation values
1490 int nesting = 0;
1491 for (; ; pos++) {
1492 TokenKind tk2 = S.token(pos).kind;
1493 switch (tk2) {
1494 case EOF:
1495 return false;
1496 case LPAREN:
1497 nesting++;
1498 break;
1499 case RPAREN:
1500 nesting--;
1501 if (nesting == 0) {
1502 continue outer;
1503 }
1504 break;
1505 }
1506 }
1508 case LT:
1509 depth++; break;
1510 case GTGTGT:
1511 depth--;
1512 case GTGT:
1513 depth--;
1514 case GT:
1515 depth--;
1516 if (depth == 0) {
1517 TokenKind nextKind = S.token(pos + 1).kind;
1518 return
1519 nextKind == TokenKind.DOT ||
1520 nextKind == TokenKind.LBRACKET ||
1521 nextKind == TokenKind.COLCOL;
1522 }
1523 break;
1524 default:
1525 return false;
1526 }
1527 }
1528 }
1530 /**
1531 * If we see an identifier followed by a '<' it could be an unbound
1532 * method reference or a binary expression. To disambiguate, look for a
1533 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1534 */
1535 @SuppressWarnings("fallthrough")
1536 ParensResult analyzeParens() {
1537 int depth = 0;
1538 boolean type = false;
1539 outer: for (int lookahead = 0 ; ; lookahead++) {
1540 TokenKind tk = S.token(lookahead).kind;
1541 switch (tk) {
1542 case COMMA:
1543 type = true;
1544 case EXTENDS: case SUPER: case DOT: case AMP:
1545 //skip
1546 break;
1547 case QUES:
1548 if (peekToken(lookahead, EXTENDS) ||
1549 peekToken(lookahead, SUPER)) {
1550 //wildcards
1551 type = true;
1552 }
1553 break;
1554 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1555 case DOUBLE: case BOOLEAN: case CHAR:
1556 if (peekToken(lookahead, RPAREN)) {
1557 //Type, ')' -> cast
1558 return ParensResult.CAST;
1559 } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
1560 //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
1561 return ParensResult.EXPLICIT_LAMBDA;
1562 }
1563 break;
1564 case LPAREN:
1565 if (lookahead != 0) {
1566 // '(' in a non-starting position -> parens
1567 return ParensResult.PARENS;
1568 } else if (peekToken(lookahead, RPAREN)) {
1569 // '(', ')' -> explicit lambda
1570 return ParensResult.EXPLICIT_LAMBDA;
1571 }
1572 break;
1573 case RPAREN:
1574 // if we have seen something that looks like a type,
1575 // then it's a cast expression
1576 if (type) return ParensResult.CAST;
1577 // otherwise, disambiguate cast vs. parenthesized expression
1578 // based on subsequent token.
1579 switch (S.token(lookahead + 1).kind) {
1580 /*case PLUSPLUS: case SUBSUB: */
1581 case BANG: case TILDE:
1582 case LPAREN: case THIS: case SUPER:
1583 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
1584 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
1585 case TRUE: case FALSE: case NULL:
1586 case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
1587 case BYTE: case SHORT: case CHAR: case INT:
1588 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
1589 return ParensResult.CAST;
1590 default:
1591 return ParensResult.PARENS;
1592 }
1593 case UNDERSCORE:
1594 case ASSERT:
1595 case ENUM:
1596 case IDENTIFIER:
1597 if (peekToken(lookahead, LAX_IDENTIFIER)) {
1598 // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
1599 return ParensResult.EXPLICIT_LAMBDA;
1600 } else if (peekToken(lookahead, RPAREN, ARROW)) {
1601 // Identifier, ')' '->' -> implicit lambda
1602 return ParensResult.IMPLICIT_LAMBDA;
1603 }
1604 type = false;
1605 break;
1606 case FINAL:
1607 case ELLIPSIS:
1608 //those can only appear in explicit lambdas
1609 return ParensResult.EXPLICIT_LAMBDA;
1610 case MONKEYS_AT:
1611 type = true;
1612 lookahead += 1; //skip '@'
1613 while (peekToken(lookahead, DOT)) {
1614 lookahead += 2;
1615 }
1616 if (peekToken(lookahead, LPAREN)) {
1617 lookahead++;
1618 //skip annotation values
1619 int nesting = 0;
1620 for (; ; lookahead++) {
1621 TokenKind tk2 = S.token(lookahead).kind;
1622 switch (tk2) {
1623 case EOF:
1624 return ParensResult.PARENS;
1625 case LPAREN:
1626 nesting++;
1627 break;
1628 case RPAREN:
1629 nesting--;
1630 if (nesting == 0) {
1631 continue outer;
1632 }
1633 break;
1634 }
1635 }
1636 }
1637 break;
1638 case LBRACKET:
1639 if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
1640 // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
1641 return ParensResult.EXPLICIT_LAMBDA;
1642 } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
1643 peekToken(lookahead, RBRACKET, AMP)) {
1644 // '[', ']', ')' -> cast
1645 // '[', ']', '&' -> cast (intersection type)
1646 return ParensResult.CAST;
1647 } else if (peekToken(lookahead, RBRACKET)) {
1648 //consume the ']' and skip
1649 type = true;
1650 lookahead++;
1651 break;
1652 } else {
1653 return ParensResult.PARENS;
1654 }
1655 case LT:
1656 depth++; break;
1657 case GTGTGT:
1658 depth--;
1659 case GTGT:
1660 depth--;
1661 case GT:
1662 depth--;
1663 if (depth == 0) {
1664 if (peekToken(lookahead, RPAREN) ||
1665 peekToken(lookahead, AMP)) {
1666 // '>', ')' -> cast
1667 // '>', '&' -> cast
1668 return ParensResult.CAST;
1669 } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
1670 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
1671 peekToken(lookahead, ELLIPSIS)) {
1672 // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
1673 // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
1674 // '>', '...' -> explicit lambda
1675 return ParensResult.EXPLICIT_LAMBDA;
1676 }
1677 //it looks a type, but could still be (i) a cast to generic type,
1678 //(ii) an unbound method reference or (iii) an explicit lambda
1679 type = true;
1680 break;
1681 } else if (depth < 0) {
1682 //unbalanced '<', '>' - not a generic type
1683 return ParensResult.PARENS;
1684 }
1685 break;
1686 default:
1687 //this includes EOF
1688 return ParensResult.PARENS;
1689 }
1690 }
1691 }
1693 /** Accepts all identifier-like tokens */
1694 Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
1695 public boolean accepts(TokenKind t) {
1696 return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
1697 }
1698 };
1700 enum ParensResult {
1701 CAST,
1702 EXPLICIT_LAMBDA,
1703 IMPLICIT_LAMBDA,
1704 PARENS;
1705 }
1707 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
1708 List<JCVariableDecl> params = explicitParams ?
1709 formalParameters(true) :
1710 implicitParameters(hasParens);
1712 return lambdaExpressionOrStatementRest(params, pos);
1713 }
1715 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
1716 checkLambda();
1717 accept(ARROW);
1719 return token.kind == LBRACE ?
1720 lambdaStatement(args, pos, pos) :
1721 lambdaExpression(args, pos);
1722 }
1724 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
1725 JCBlock block = block(pos2, 0);
1726 return toP(F.at(pos).Lambda(args, block));
1727 }
1729 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
1730 JCTree expr = parseExpression();
1731 return toP(F.at(pos).Lambda(args, expr));
1732 }
1734 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1735 */
1736 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1737 nextToken();
1738 if (token.kind == LPAREN || typeArgs != null) {
1739 t = arguments(typeArgs, t);
1740 } else if (token.kind == COLCOL) {
1741 if (typeArgs != null) return illegal();
1742 t = memberReferenceSuffix(t);
1743 } else {
1744 int pos = token.pos;
1745 accept(DOT);
1746 typeArgs = (token.kind == LT) ? typeArguments(false) : null;
1747 t = toP(F.at(pos).Select(t, ident()));
1748 t = argumentsOpt(typeArgs, t);
1749 }
1750 return t;
1751 }
1753 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1754 */
1755 JCPrimitiveTypeTree basicType() {
1756 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
1757 nextToken();
1758 return t;
1759 }
1761 /** ArgumentsOpt = [ Arguments ]
1762 */
1763 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1764 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
1765 mode = EXPR;
1766 return arguments(typeArgs, t);
1767 } else {
1768 return t;
1769 }
1770 }
1772 /** Arguments = "(" [Expression { COMMA Expression }] ")"
1773 */
1774 List<JCExpression> arguments() {
1775 ListBuffer<JCExpression> args = new ListBuffer<>();
1776 if (token.kind == LPAREN) {
1777 nextToken();
1778 if (token.kind != RPAREN) {
1779 args.append(parseExpression());
1780 while (token.kind == COMMA) {
1781 nextToken();
1782 args.append(parseExpression());
1783 }
1784 }
1785 accept(RPAREN);
1786 } else {
1787 syntaxError(token.pos, "expected", LPAREN);
1788 }
1789 return args.toList();
1790 }
1792 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1793 int pos = token.pos;
1794 List<JCExpression> args = arguments();
1795 return toP(F.at(pos).Apply(typeArgs, t, args));
1796 }
1798 /** TypeArgumentsOpt = [ TypeArguments ]
1799 */
1800 JCExpression typeArgumentsOpt(JCExpression t) {
1801 if (token.kind == LT &&
1802 (mode & TYPE) != 0 &&
1803 (mode & NOPARAMS) == 0) {
1804 mode = TYPE;
1805 checkGenerics();
1806 return typeArguments(t, false);
1807 } else {
1808 return t;
1809 }
1810 }
1811 List<JCExpression> typeArgumentsOpt() {
1812 return typeArgumentsOpt(TYPE);
1813 }
1815 List<JCExpression> typeArgumentsOpt(int useMode) {
1816 if (token.kind == LT) {
1817 checkGenerics();
1818 if ((mode & useMode) == 0 ||
1819 (mode & NOPARAMS) != 0) {
1820 illegal();
1821 }
1822 mode = useMode;
1823 return typeArguments(false);
1824 }
1825 return null;
1826 }
1828 /**
1829 * {@literal
1830 * TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1831 * }
1832 */
1833 List<JCExpression> typeArguments(boolean diamondAllowed) {
1834 if (token.kind == LT) {
1835 nextToken();
1836 if (token.kind == GT && diamondAllowed) {
1837 checkDiamond();
1838 mode |= DIAMOND;
1839 nextToken();
1840 return List.nil();
1841 } else {
1842 ListBuffer<JCExpression> args = new ListBuffer<>();
1843 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1844 while (token.kind == COMMA) {
1845 nextToken();
1846 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1847 }
1848 switch (token.kind) {
1850 case GTGTGTEQ: case GTGTEQ: case GTEQ:
1851 case GTGTGT: case GTGT:
1852 token = S.split();
1853 break;
1854 case GT:
1855 nextToken();
1856 break;
1857 default:
1858 args.append(syntaxError(token.pos, "expected", GT));
1859 break;
1860 }
1861 return args.toList();
1862 }
1863 } else {
1864 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
1865 }
1866 }
1868 /**
1869 * {@literal
1870 * TypeArgument = Type
1871 * | [Annotations] "?"
1872 * | [Annotations] "?" EXTENDS Type {"&" Type}
1873 * | [Annotations] "?" SUPER Type
1874 * }
1875 */
1876 JCExpression typeArgument() {
1877 List<JCAnnotation> annotations = typeAnnotationsOpt();
1878 if (token.kind != QUES) return parseType(annotations);
1879 int pos = token.pos;
1880 nextToken();
1881 JCExpression result;
1882 if (token.kind == EXTENDS) {
1883 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
1884 nextToken();
1885 JCExpression bound = parseType();
1886 result = F.at(pos).Wildcard(t, bound);
1887 } else if (token.kind == SUPER) {
1888 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
1889 nextToken();
1890 JCExpression bound = parseType();
1891 result = F.at(pos).Wildcard(t, bound);
1892 } else if (LAX_IDENTIFIER.accepts(token.kind)) {
1893 //error recovery
1894 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1895 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1896 JCIdent id = toP(F.at(token.pos).Ident(ident()));
1897 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1898 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
1899 result = err;
1900 } else {
1901 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
1902 result = toP(F.at(pos).Wildcard(t, null));
1903 }
1904 if (!annotations.isEmpty()) {
1905 result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
1906 }
1907 return result;
1908 }
1910 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
1911 int pos = token.pos;
1912 List<JCExpression> args = typeArguments(diamondAllowed);
1913 return toP(F.at(pos).TypeApply(t, args));
1914 }
1916 /**
1917 * BracketsOpt = { [Annotations] "[" "]" }*
1918 *
1919 * <p>
1920 *
1921 * <code>annotations</code> is the list of annotations targeting
1922 * the expression <code>t</code>.
1923 */
1924 private JCExpression bracketsOpt(JCExpression t,
1925 List<JCAnnotation> annotations) {
1926 List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
1928 if (token.kind == LBRACKET) {
1929 int pos = token.pos;
1930 nextToken();
1931 t = bracketsOptCont(t, pos, nextLevelAnnotations);
1932 } else if (!nextLevelAnnotations.isEmpty()) {
1933 if (permitTypeAnnotationsPushBack) {
1934 this.typeAnnotationsPushedBack = nextLevelAnnotations;
1935 } else {
1936 return illegal(nextLevelAnnotations.head.pos);
1937 }
1938 }
1940 if (!annotations.isEmpty()) {
1941 t = toP(F.at(token.pos).AnnotatedType(annotations, t));
1942 }
1943 return t;
1944 }
1946 /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ]
1947 */
1948 private JCExpression bracketsOpt(JCExpression t) {
1949 return bracketsOpt(t, List.<JCAnnotation>nil());
1950 }
1952 private JCExpression bracketsOptCont(JCExpression t, int pos,
1953 List<JCAnnotation> annotations) {
1954 accept(RBRACKET);
1955 t = bracketsOpt(t);
1956 t = toP(F.at(pos).TypeArray(t));
1957 if (annotations.nonEmpty()) {
1958 t = toP(F.at(pos).AnnotatedType(annotations, t));
1959 }
1960 return t;
1961 }
1963 /** BracketsSuffixExpr = "." CLASS
1964 * BracketsSuffixType =
1965 */
1966 JCExpression bracketsSuffix(JCExpression t) {
1967 if ((mode & EXPR) != 0 && token.kind == DOT) {
1968 mode = EXPR;
1969 int pos = token.pos;
1970 nextToken();
1971 accept(CLASS);
1972 if (token.pos == endPosTable.errorEndPos) {
1973 // error recovery
1974 Name name;
1975 if (LAX_IDENTIFIER.accepts(token.kind)) {
1976 name = token.name();
1977 nextToken();
1978 } else {
1979 name = names.error;
1980 }
1981 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1982 } else {
1983 t = toP(F.at(pos).Select(t, names._class));
1984 }
1985 } else if ((mode & TYPE) != 0) {
1986 if (token.kind != COLCOL) {
1987 mode = TYPE;
1988 }
1989 } else if (token.kind != COLCOL) {
1990 syntaxError(token.pos, "dot.class.expected");
1991 }
1992 return t;
1993 }
1995 /**
1996 * MemberReferenceSuffix = "::" [TypeArguments] Ident
1997 * | "::" [TypeArguments] "new"
1998 */
1999 JCExpression memberReferenceSuffix(JCExpression t) {
2000 int pos1 = token.pos;
2001 accept(COLCOL);
2002 return memberReferenceSuffix(pos1, t);
2003 }
2005 JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
2006 checkMethodReferences();
2007 mode = EXPR;
2008 List<JCExpression> typeArgs = null;
2009 if (token.kind == LT) {
2010 typeArgs = typeArguments(false);
2011 }
2012 Name refName;
2013 ReferenceMode refMode;
2014 if (token.kind == NEW) {
2015 refMode = ReferenceMode.NEW;
2016 refName = names.init;
2017 nextToken();
2018 } else {
2019 refMode = ReferenceMode.INVOKE;
2020 refName = ident();
2021 }
2022 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2023 }
2025 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2026 */
2027 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2028 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2030 switch (token.kind) {
2031 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2032 case DOUBLE: case BOOLEAN:
2033 if (typeArgs == null) {
2034 if (newAnnotations.isEmpty()) {
2035 return arrayCreatorRest(newpos, basicType());
2036 } else {
2037 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2038 }
2039 }
2040 break;
2041 default:
2042 }
2043 JCExpression t = qualident(true);
2045 int oldmode = mode;
2046 mode = TYPE;
2047 boolean diamondFound = false;
2048 int lastTypeargsPos = -1;
2049 if (token.kind == LT) {
2050 checkGenerics();
2051 lastTypeargsPos = token.pos;
2052 t = typeArguments(t, true);
2053 diamondFound = (mode & DIAMOND) != 0;
2054 }
2055 while (token.kind == DOT) {
2056 if (diamondFound) {
2057 //cannot select after a diamond
2058 illegal();
2059 }
2060 int pos = token.pos;
2061 nextToken();
2062 List<JCAnnotation> tyannos = typeAnnotationsOpt();
2063 t = toP(F.at(pos).Select(t, ident()));
2065 if (tyannos != null && tyannos.nonEmpty()) {
2066 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
2067 }
2069 if (token.kind == LT) {
2070 lastTypeargsPos = token.pos;
2071 checkGenerics();
2072 t = typeArguments(t, true);
2073 diamondFound = (mode & DIAMOND) != 0;
2074 }
2075 }
2076 mode = oldmode;
2077 if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
2078 // handle type annotations for non primitive arrays
2079 if (newAnnotations.nonEmpty()) {
2080 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2081 }
2083 JCExpression e = arrayCreatorRest(newpos, t);
2084 if (diamondFound) {
2085 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
2086 return toP(F.at(newpos).Erroneous(List.of(e)));
2087 }
2088 else if (typeArgs != null) {
2089 int pos = newpos;
2090 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2091 // note: this should always happen but we should
2092 // not rely on this as the parser is continuously
2093 // modified to improve error recovery.
2094 pos = typeArgs.head.pos;
2095 }
2096 setErrorEndPos(S.prevToken().endPos);
2097 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2098 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
2099 return toP(err);
2100 }
2101 return e;
2102 } else if (token.kind == LPAREN) {
2103 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
2104 if (newClass.def != null) {
2105 assert newClass.def.mods.annotations.isEmpty();
2106 if (newAnnotations.nonEmpty()) {
2107 // Add type and declaration annotations to the new class;
2108 // com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitNewClass(JCNewClass)
2109 // will later remove all type annotations and only leave the
2110 // declaration annotations.
2111 newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
2112 newClass.def.mods.annotations = newAnnotations;
2113 }
2114 } else {
2115 // handle type annotations for instantiations
2116 if (newAnnotations.nonEmpty()) {
2117 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2118 newClass.clazz = t;
2119 }
2120 }
2121 return newClass;
2122 } else {
2123 setErrorEndPos(token.pos);
2124 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
2125 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
2126 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2127 }
2128 }
2130 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2131 */
2132 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2133 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2135 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2137 if (newAnnotations.nonEmpty()) {
2138 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2139 }
2141 if (token.kind == LT) {
2142 int oldmode = mode;
2143 checkGenerics();
2144 t = typeArguments(t, true);
2145 mode = oldmode;
2146 }
2147 return classCreatorRest(newpos, encl, typeArgs, t);
2148 }
2150 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2151 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2152 */
2153 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2154 List<JCAnnotation> annos = typeAnnotationsOpt();
2156 accept(LBRACKET);
2157 if (token.kind == RBRACKET) {
2158 accept(RBRACKET);
2159 elemtype = bracketsOpt(elemtype, annos);
2160 if (token.kind == LBRACE) {
2161 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2162 if (annos.nonEmpty()) {
2163 // when an array initializer is present then
2164 // the parsed annotations should target the
2165 // new array tree
2166 // bracketsOpt inserts the annotation in
2167 // elemtype, and it needs to be corrected
2168 //
2169 JCAnnotatedType annotated = (JCAnnotatedType)elemtype;
2170 assert annotated.annotations == annos;
2171 na.annotations = annotated.annotations;
2172 na.elemtype = annotated.underlyingType;
2173 }
2174 return na;
2175 } else {
2176 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
2177 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
2178 }
2179 } else {
2180 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
2182 // maintain array dimension type annotations
2183 ListBuffer<List<JCAnnotation>> dimAnnotations = new ListBuffer<>();
2184 dimAnnotations.append(annos);
2186 dims.append(parseExpression());
2187 accept(RBRACKET);
2188 while (token.kind == LBRACKET
2189 || token.kind == MONKEYS_AT) {
2190 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt();
2191 int pos = token.pos;
2192 nextToken();
2193 if (token.kind == RBRACKET) {
2194 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
2195 } else {
2196 if (token.kind == RBRACKET) { // no dimension
2197 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
2198 } else {
2199 dimAnnotations.append(maybeDimAnnos);
2200 dims.append(parseExpression());
2201 accept(RBRACKET);
2202 }
2203 }
2204 }
2206 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
2207 na.dimAnnotations = dimAnnotations.toList();
2208 return na;
2209 }
2210 }
2212 /** ClassCreatorRest = Arguments [ClassBody]
2213 */
2214 JCNewClass classCreatorRest(int newpos,
2215 JCExpression encl,
2216 List<JCExpression> typeArgs,
2217 JCExpression t)
2218 {
2219 List<JCExpression> args = arguments();
2220 JCClassDecl body = null;
2221 if (token.kind == LBRACE) {
2222 int pos = token.pos;
2223 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2224 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2225 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2226 }
2227 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2228 }
2230 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2231 */
2232 JCExpression arrayInitializer(int newpos, JCExpression t) {
2233 accept(LBRACE);
2234 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
2235 if (token.kind == COMMA) {
2236 nextToken();
2237 } else if (token.kind != RBRACE) {
2238 elems.append(variableInitializer());
2239 while (token.kind == COMMA) {
2240 nextToken();
2241 if (token.kind == RBRACE) break;
2242 elems.append(variableInitializer());
2243 }
2244 }
2245 accept(RBRACE);
2246 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
2247 }
2249 /** VariableInitializer = ArrayInitializer | Expression
2250 */
2251 public JCExpression variableInitializer() {
2252 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
2253 }
2255 /** ParExpression = "(" Expression ")"
2256 */
2257 JCExpression parExpression() {
2258 int pos = token.pos;
2259 accept(LPAREN);
2260 JCExpression t = parseExpression();
2261 accept(RPAREN);
2262 return toP(F.at(pos).Parens(t));
2263 }
2265 /** Block = "{" BlockStatements "}"
2266 */
2267 JCBlock block(int pos, long flags) {
2268 accept(LBRACE);
2269 List<JCStatement> stats = blockStatements();
2270 JCBlock t = F.at(pos).Block(flags, stats);
2271 while (token.kind == CASE || token.kind == DEFAULT) {
2272 syntaxError("orphaned", token.kind);
2273 switchBlockStatementGroups();
2274 }
2275 // the Block node has a field "endpos" for first char of last token, which is
2276 // usually but not necessarily the last char of the last token.
2277 t.endpos = token.pos;
2278 accept(RBRACE);
2279 return toP(t);
2280 }
2282 public JCBlock block() {
2283 return block(token.pos, 0);
2284 }
2286 /** BlockStatements = { BlockStatement }
2287 * BlockStatement = LocalVariableDeclarationStatement
2288 * | ClassOrInterfaceOrEnumDeclaration
2289 * | [Ident ":"] Statement
2290 * LocalVariableDeclarationStatement
2291 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
2292 */
2293 @SuppressWarnings("fallthrough")
2294 List<JCStatement> blockStatements() {
2295 //todo: skip to anchor on error(?)
2296 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
2297 while (true) {
2298 List<JCStatement> stat = blockStatement();
2299 if (stat.isEmpty()) {
2300 return stats.toList();
2301 } else {
2302 if (token.pos <= endPosTable.errorEndPos) {
2303 skip(false, true, true, true);
2304 }
2305 stats.addAll(stat);
2306 }
2307 }
2308 }
2310 /*
2311 * This method parses a statement treating it as a block, relaxing the
2312 * JLS restrictions, allows us to parse more faulty code, doing so
2313 * enables us to provide better and accurate diagnostics to the user.
2314 */
2315 JCStatement parseStatementAsBlock() {
2316 int pos = token.pos;
2317 List<JCStatement> stats = blockStatement();
2318 if (stats.isEmpty()) {
2319 JCErroneous e = F.at(pos).Erroneous();
2320 error(e, "illegal.start.of.stmt");
2321 return F.at(pos).Exec(e);
2322 } else {
2323 JCStatement first = stats.head;
2324 String error = null;
2325 switch (first.getTag()) {
2326 case CLASSDEF:
2327 error = "class.not.allowed";
2328 break;
2329 case VARDEF:
2330 error = "variable.not.allowed";
2331 break;
2332 }
2333 if (error != null) {
2334 error(first, error);
2335 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
2336 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
2337 }
2338 return first;
2339 }
2340 }
2342 @SuppressWarnings("fallthrough")
2343 List<JCStatement> blockStatement() {
2344 //todo: skip to anchor on error(?)
2345 int pos = token.pos;
2346 switch (token.kind) {
2347 case RBRACE: case CASE: case DEFAULT: case EOF:
2348 return List.nil();
2349 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
2350 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
2351 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
2352 return List.of(parseStatement());
2353 case MONKEYS_AT:
2354 case FINAL: {
2355 Comment dc = token.comment(CommentStyle.JAVADOC);
2356 JCModifiers mods = modifiersOpt();
2357 if (token.kind == INTERFACE ||
2358 token.kind == CLASS ||
2359 allowEnums && token.kind == ENUM) {
2360 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
2361 } else {
2362 JCExpression t = parseType();
2363 ListBuffer<JCStatement> stats =
2364 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
2365 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
2366 storeEnd(stats.last(), token.endPos);
2367 accept(SEMI);
2368 return stats.toList();
2369 }
2370 }
2371 case ABSTRACT: case STRICTFP: {
2372 Comment dc = token.comment(CommentStyle.JAVADOC);
2373 JCModifiers mods = modifiersOpt();
2374 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
2375 }
2376 case INTERFACE:
2377 case CLASS:
2378 Comment dc = token.comment(CommentStyle.JAVADOC);
2379 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2380 case ENUM:
2381 case ASSERT:
2382 if (allowEnums && token.kind == ENUM) {
2383 error(token.pos, "local.enum");
2384 dc = token.comment(CommentStyle.JAVADOC);
2385 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2386 } else if (allowAsserts && token.kind == ASSERT) {
2387 return List.of(parseStatement());
2388 }
2389 /* fall through to default */
2390 default:
2391 Token prevToken = token;
2392 JCExpression t = term(EXPR | TYPE);
2393 if (token.kind == COLON && t.hasTag(IDENT)) {
2394 nextToken();
2395 JCStatement stat = parseStatement();
2396 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
2397 } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
2398 pos = token.pos;
2399 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2400 F.at(pos);
2401 ListBuffer<JCStatement> stats =
2402 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
2403 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
2404 storeEnd(stats.last(), token.endPos);
2405 accept(SEMI);
2406 return stats.toList();
2407 } else {
2408 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2409 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
2410 accept(SEMI);
2411 return List.<JCStatement>of(expr);
2412 }
2413 }
2414 }
2416 /** Statement =
2417 * Block
2418 * | IF ParExpression Statement [ELSE Statement]
2419 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
2420 * | FOR "(" FormalParameter : Expression ")" Statement
2421 * | WHILE ParExpression Statement
2422 * | DO Statement WHILE ParExpression ";"
2423 * | TRY Block ( Catches | [Catches] FinallyPart )
2424 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
2425 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
2426 * | SYNCHRONIZED ParExpression Block
2427 * | RETURN [Expression] ";"
2428 * | THROW Expression ";"
2429 * | BREAK [Ident] ";"
2430 * | CONTINUE [Ident] ";"
2431 * | ASSERT Expression [ ":" Expression ] ";"
2432 * | ";"
2433 * | ExpressionStatement
2434 * | Ident ":" Statement
2435 */
2436 @SuppressWarnings("fallthrough")
2437 public JCStatement parseStatement() {
2438 int pos = token.pos;
2439 switch (token.kind) {
2440 case LBRACE:
2441 return block();
2442 case IF: {
2443 nextToken();
2444 JCExpression cond = parExpression();
2445 JCStatement thenpart = parseStatementAsBlock();
2446 JCStatement elsepart = null;
2447 if (token.kind == ELSE) {
2448 nextToken();
2449 elsepart = parseStatementAsBlock();
2450 }
2451 return F.at(pos).If(cond, thenpart, elsepart);
2452 }
2453 case FOR: {
2454 nextToken();
2455 accept(LPAREN);
2456 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
2457 if (inits.length() == 1 &&
2458 inits.head.hasTag(VARDEF) &&
2459 ((JCVariableDecl) inits.head).init == null &&
2460 token.kind == COLON) {
2461 checkForeach();
2462 JCVariableDecl var = (JCVariableDecl)inits.head;
2463 accept(COLON);
2464 JCExpression expr = parseExpression();
2465 accept(RPAREN);
2466 JCStatement body = parseStatementAsBlock();
2467 return F.at(pos).ForeachLoop(var, expr, body);
2468 } else {
2469 accept(SEMI);
2470 JCExpression cond = token.kind == SEMI ? null : parseExpression();
2471 accept(SEMI);
2472 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
2473 accept(RPAREN);
2474 JCStatement body = parseStatementAsBlock();
2475 return F.at(pos).ForLoop(inits, cond, steps, body);
2476 }
2477 }
2478 case WHILE: {
2479 nextToken();
2480 JCExpression cond = parExpression();
2481 JCStatement body = parseStatementAsBlock();
2482 return F.at(pos).WhileLoop(cond, body);
2483 }
2484 case DO: {
2485 nextToken();
2486 JCStatement body = parseStatementAsBlock();
2487 accept(WHILE);
2488 JCExpression cond = parExpression();
2489 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
2490 accept(SEMI);
2491 return t;
2492 }
2493 case TRY: {
2494 nextToken();
2495 List<JCTree> resources = List.<JCTree>nil();
2496 if (token.kind == LPAREN) {
2497 checkTryWithResources();
2498 nextToken();
2499 resources = resources();
2500 accept(RPAREN);
2501 }
2502 JCBlock body = block();
2503 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
2504 JCBlock finalizer = null;
2505 if (token.kind == CATCH || token.kind == FINALLY) {
2506 while (token.kind == CATCH) catchers.append(catchClause());
2507 if (token.kind == FINALLY) {
2508 nextToken();
2509 finalizer = block();
2510 }
2511 } else {
2512 if (allowTWR) {
2513 if (resources.isEmpty())
2514 error(pos, "try.without.catch.finally.or.resource.decls");
2515 } else
2516 error(pos, "try.without.catch.or.finally");
2517 }
2518 return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
2519 }
2520 case SWITCH: {
2521 nextToken();
2522 JCExpression selector = parExpression();
2523 accept(LBRACE);
2524 List<JCCase> cases = switchBlockStatementGroups();
2525 JCSwitch t = to(F.at(pos).Switch(selector, cases));
2526 accept(RBRACE);
2527 return t;
2528 }
2529 case SYNCHRONIZED: {
2530 nextToken();
2531 JCExpression lock = parExpression();
2532 JCBlock body = block();
2533 return F.at(pos).Synchronized(lock, body);
2534 }
2535 case RETURN: {
2536 nextToken();
2537 JCExpression result = token.kind == SEMI ? null : parseExpression();
2538 JCReturn t = to(F.at(pos).Return(result));
2539 accept(SEMI);
2540 return t;
2541 }
2542 case THROW: {
2543 nextToken();
2544 JCExpression exc = parseExpression();
2545 JCThrow t = to(F.at(pos).Throw(exc));
2546 accept(SEMI);
2547 return t;
2548 }
2549 case BREAK: {
2550 nextToken();
2551 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2552 JCBreak t = to(F.at(pos).Break(label));
2553 accept(SEMI);
2554 return t;
2555 }
2556 case CONTINUE: {
2557 nextToken();
2558 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
2559 JCContinue t = to(F.at(pos).Continue(label));
2560 accept(SEMI);
2561 return t;
2562 }
2563 case SEMI:
2564 nextToken();
2565 return toP(F.at(pos).Skip());
2566 case ELSE:
2567 int elsePos = token.pos;
2568 nextToken();
2569 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
2570 case FINALLY:
2571 int finallyPos = token.pos;
2572 nextToken();
2573 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
2574 case CATCH:
2575 return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
2576 case ASSERT: {
2577 if (allowAsserts && token.kind == ASSERT) {
2578 nextToken();
2579 JCExpression assertion = parseExpression();
2580 JCExpression message = null;
2581 if (token.kind == COLON) {
2582 nextToken();
2583 message = parseExpression();
2584 }
2585 JCAssert t = to(F.at(pos).Assert(assertion, message));
2586 accept(SEMI);
2587 return t;
2588 }
2589 /* else fall through to default case */
2590 }
2591 case ENUM:
2592 default:
2593 Token prevToken = token;
2594 JCExpression expr = parseExpression();
2595 if (token.kind == COLON && expr.hasTag(IDENT)) {
2596 nextToken();
2597 JCStatement stat = parseStatement();
2598 return F.at(pos).Labelled(prevToken.name(), stat);
2599 } else {
2600 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2601 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
2602 accept(SEMI);
2603 return stat;
2604 }
2605 }
2606 }
2608 private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
2609 int errPos = S.errPos();
2610 JCTree stm = action.doRecover(this);
2611 S.errPos(errPos);
2612 return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
2613 }
2615 /** CatchClause = CATCH "(" FormalParameter ")" Block
2616 * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below.
2617 */
2618 protected JCCatch catchClause() {
2619 int pos = token.pos;
2620 accept(CATCH);
2621 accept(LPAREN);
2622 JCModifiers mods = optFinal(Flags.PARAMETER);
2623 List<JCExpression> catchTypes = catchTypes();
2624 JCExpression paramType = catchTypes.size() > 1 ?
2625 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
2626 catchTypes.head;
2627 JCVariableDecl formal = variableDeclaratorId(mods, paramType);
2628 accept(RPAREN);
2629 JCBlock body = block();
2630 return F.at(pos).Catch(formal, body);
2631 }
2633 List<JCExpression> catchTypes() {
2634 ListBuffer<JCExpression> catchTypes = new ListBuffer<>();
2635 catchTypes.add(parseType());
2636 while (token.kind == BAR) {
2637 checkMulticatch();
2638 nextToken();
2639 // Instead of qualident this is now parseType.
2640 // But would that allow too much, e.g. arrays or generics?
2641 catchTypes.add(parseType());
2642 }
2643 return catchTypes.toList();
2644 }
2646 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2647 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
2648 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2649 */
2650 List<JCCase> switchBlockStatementGroups() {
2651 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2652 while (true) {
2653 int pos = token.pos;
2654 switch (token.kind) {
2655 case CASE:
2656 case DEFAULT:
2657 cases.append(switchBlockStatementGroup());
2658 break;
2659 case RBRACE: case EOF:
2660 return cases.toList();
2661 default:
2662 nextToken(); // to ensure progress
2663 syntaxError(pos, "expected3",
2664 CASE, DEFAULT, RBRACE);
2665 }
2666 }
2667 }
2669 protected JCCase switchBlockStatementGroup() {
2670 int pos = token.pos;
2671 List<JCStatement> stats;
2672 JCCase c;
2673 switch (token.kind) {
2674 case CASE:
2675 nextToken();
2676 JCExpression pat = parseExpression();
2677 accept(COLON);
2678 stats = blockStatements();
2679 c = F.at(pos).Case(pat, stats);
2680 if (stats.isEmpty())
2681 storeEnd(c, S.prevToken().endPos);
2682 return c;
2683 case DEFAULT:
2684 nextToken();
2685 accept(COLON);
2686 stats = blockStatements();
2687 c = F.at(pos).Case(null, stats);
2688 if (stats.isEmpty())
2689 storeEnd(c, S.prevToken().endPos);
2690 return c;
2691 }
2692 throw new AssertionError("should not reach here");
2693 }
2695 /** MoreStatementExpressions = { COMMA StatementExpression }
2696 */
2697 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2698 JCExpression first,
2699 T stats) {
2700 // This Exec is a "StatementExpression"; it subsumes no terminating token
2701 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2702 while (token.kind == COMMA) {
2703 nextToken();
2704 pos = token.pos;
2705 JCExpression t = parseExpression();
2706 // This Exec is a "StatementExpression"; it subsumes no terminating token
2707 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2708 }
2709 return stats;
2710 }
2712 /** ForInit = StatementExpression MoreStatementExpressions
2713 * | { FINAL | '@' Annotation } Type VariableDeclarators
2714 */
2715 List<JCStatement> forInit() {
2716 ListBuffer<JCStatement> stats = new ListBuffer<>();
2717 int pos = token.pos;
2718 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
2719 return variableDeclarators(optFinal(0), parseType(), stats).toList();
2720 } else {
2721 JCExpression t = term(EXPR | TYPE);
2722 if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
2723 return variableDeclarators(mods(pos, 0, List.<JCAnnotation>nil()), t, stats).toList();
2724 } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
2725 error(pos, "bad.initializer", "for-loop");
2726 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
2727 } else {
2728 return moreStatementExpressions(pos, t, stats).toList();
2729 }
2730 }
2731 }
2733 /** ForUpdate = StatementExpression MoreStatementExpressions
2734 */
2735 List<JCExpressionStatement> forUpdate() {
2736 return moreStatementExpressions(token.pos,
2737 parseExpression(),
2738 new ListBuffer<JCExpressionStatement>()).toList();
2739 }
2741 /** AnnotationsOpt = { '@' Annotation }
2742 *
2743 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
2744 */
2745 List<JCAnnotation> annotationsOpt(Tag kind) {
2746 if (token.kind != MONKEYS_AT) return List.nil(); // optimization
2747 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
2748 int prevmode = mode;
2749 while (token.kind == MONKEYS_AT) {
2750 int pos = token.pos;
2751 nextToken();
2752 buf.append(annotation(pos, kind));
2753 }
2754 lastmode = mode;
2755 mode = prevmode;
2756 List<JCAnnotation> annotations = buf.toList();
2758 return annotations;
2759 }
2761 List<JCAnnotation> typeAnnotationsOpt() {
2762 List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
2763 return annotations;
2764 }
2766 /** ModifiersOpt = { Modifier }
2767 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
2768 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
2769 * | "@" Annotation
2770 */
2771 JCModifiers modifiersOpt() {
2772 return modifiersOpt(null);
2773 }
2774 protected JCModifiers modifiersOpt(JCModifiers partial) {
2775 long flags;
2776 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
2777 int pos;
2778 if (partial == null) {
2779 flags = 0;
2780 pos = token.pos;
2781 } else {
2782 flags = partial.flags;
2783 annotations.appendList(partial.annotations);
2784 pos = partial.pos;
2785 }
2786 if (token.deprecatedFlag()) {
2787 flags |= Flags.DEPRECATED;
2788 }
2789 int lastPos;
2790 loop:
2791 while (true) {
2792 long flag;
2793 switch (token.kind) {
2794 case PRIVATE : flag = Flags.PRIVATE; break;
2795 case PROTECTED : flag = Flags.PROTECTED; break;
2796 case PUBLIC : flag = Flags.PUBLIC; break;
2797 case STATIC : flag = Flags.STATIC; break;
2798 case TRANSIENT : flag = Flags.TRANSIENT; break;
2799 case FINAL : flag = Flags.FINAL; break;
2800 case ABSTRACT : flag = Flags.ABSTRACT; break;
2801 case NATIVE : flag = Flags.NATIVE; break;
2802 case VOLATILE : flag = Flags.VOLATILE; break;
2803 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
2804 case STRICTFP : flag = Flags.STRICTFP; break;
2805 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
2806 case DEFAULT : checkDefaultMethods(); flag = Flags.DEFAULT; break;
2807 case ERROR : flag = 0; nextToken(); break;
2808 default: break loop;
2809 }
2810 if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
2811 lastPos = token.pos;
2812 nextToken();
2813 if (flag == Flags.ANNOTATION) {
2814 checkAnnotations();
2815 if (token.kind != INTERFACE) {
2816 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
2817 // if first modifier is an annotation, set pos to annotation's.
2818 if (flags == 0 && annotations.isEmpty())
2819 pos = ann.pos;
2820 annotations.append(ann);
2821 flag = 0;
2822 }
2823 }
2824 flags |= flag;
2825 }
2826 switch (token.kind) {
2827 case ENUM: flags |= Flags.ENUM; break;
2828 case INTERFACE: flags |= Flags.INTERFACE; break;
2829 default: break;
2830 }
2832 return mods(pos, flags, annotations.toList());
2833 }
2834 //where
2835 JCModifiers mods(int pos, long flags, List<JCAnnotation> annotations) {
2836 /* A modifiers tree with no modifier tokens or annotations
2837 * has no text position. */
2838 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
2839 pos = Position.NOPOS;
2841 JCModifiers mods = F.at(pos).Modifiers(flags, annotations);
2842 if (pos != Position.NOPOS)
2843 storeEnd(mods, S.prevToken().endPos);
2844 return mods;
2845 }
2847 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2848 *
2849 * @param pos position of "@" token
2850 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
2851 */
2852 JCAnnotation annotation(int pos, Tag kind) {
2853 // accept(AT); // AT consumed by caller
2854 checkAnnotations();
2855 if (kind == Tag.TYPE_ANNOTATION) {
2856 checkTypeAnnotations();
2857 }
2858 JCTree ident = qualident(false);
2859 List<JCExpression> fieldValues = annotationFieldValuesOpt();
2860 JCAnnotation ann;
2861 if (kind == Tag.ANNOTATION) {
2862 ann = F.at(pos).Annotation(ident, fieldValues);
2863 } else if (kind == Tag.TYPE_ANNOTATION) {
2864 ann = F.at(pos).TypeAnnotation(ident, fieldValues);
2865 } else {
2866 throw new AssertionError("Unhandled annotation kind: " + kind);
2867 }
2869 storeEnd(ann, S.prevToken().endPos);
2870 return ann;
2871 }
2873 List<JCExpression> annotationFieldValuesOpt() {
2874 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2875 }
2877 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2878 List<JCExpression> annotationFieldValues() {
2879 accept(LPAREN);
2880 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2881 if (token.kind != RPAREN) {
2882 buf.append(annotationFieldValue());
2883 while (token.kind == COMMA) {
2884 nextToken();
2885 buf.append(annotationFieldValue());
2886 }
2887 }
2888 accept(RPAREN);
2889 return buf.toList();
2890 }
2892 /** AnnotationFieldValue = AnnotationValue
2893 * | Identifier "=" AnnotationValue
2894 */
2895 JCExpression annotationFieldValue() {
2896 if (LAX_IDENTIFIER.accepts(token.kind)) {
2897 mode = EXPR;
2898 JCExpression t1 = term1();
2899 if (t1.hasTag(IDENT) && token.kind == EQ) {
2900 int pos = token.pos;
2901 accept(EQ);
2902 JCExpression v = annotationValue();
2903 return toP(F.at(pos).Assign(t1, v));
2904 } else {
2905 return t1;
2906 }
2907 }
2908 return annotationValue();
2909 }
2911 /* AnnotationValue = ConditionalExpression
2912 * | Annotation
2913 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2914 */
2915 JCExpression annotationValue() {
2916 int pos;
2917 switch (token.kind) {
2918 case MONKEYS_AT:
2919 pos = token.pos;
2920 nextToken();
2921 return annotation(pos, Tag.ANNOTATION);
2922 case LBRACE:
2923 pos = token.pos;
2924 accept(LBRACE);
2925 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2926 if (token.kind == COMMA) {
2927 nextToken();
2928 } else if (token.kind != RBRACE) {
2929 buf.append(annotationValue());
2930 while (token.kind == COMMA) {
2931 nextToken();
2932 if (token.kind == RBRACE) break;
2933 buf.append(annotationValue());
2934 }
2935 }
2936 accept(RBRACE);
2937 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2938 default:
2939 mode = EXPR;
2940 return term1();
2941 }
2942 }
2944 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2945 */
2946 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2947 JCExpression type,
2948 T vdefs)
2949 {
2950 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
2951 }
2953 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2954 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2955 *
2956 * @param reqInit Is an initializer always required?
2957 * @param dc The documentation comment for the variable declarations, or null.
2958 */
2959 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2960 JCModifiers mods,
2961 JCExpression type,
2962 Name name,
2963 boolean reqInit,
2964 Comment dc,
2965 T vdefs)
2966 {
2967 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2968 while (token.kind == COMMA) {
2969 // All but last of multiple declarators subsume a comma
2970 storeEnd((JCTree)vdefs.last(), token.endPos);
2971 nextToken();
2972 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2973 }
2974 return vdefs;
2975 }
2977 /** VariableDeclarator = Ident VariableDeclaratorRest
2978 * ConstantDeclarator = Ident ConstantDeclaratorRest
2979 */
2980 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
2981 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
2982 }
2984 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2985 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2986 *
2987 * @param reqInit Is an initializer always required?
2988 * @param dc The documentation comment for the variable declarations, or null.
2989 */
2990 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2991 boolean reqInit, Comment dc) {
2992 type = bracketsOpt(type);
2993 JCExpression init = null;
2994 if (token.kind == EQ) {
2995 nextToken();
2996 init = variableInitializer();
2997 }
2998 else if (reqInit) syntaxError(token.pos, "expected", EQ);
2999 JCVariableDecl result =
3000 toP(F.at(pos).VarDef(mods, name, type, init));
3001 attach(result, dc);
3002 return result;
3003 }
3005 /** VariableDeclaratorId = Ident BracketsOpt
3006 */
3007 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
3008 return variableDeclaratorId(mods, type, false);
3009 }
3010 //where
3011 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
3012 int pos = token.pos;
3013 Name name;
3014 if (lambdaParameter && token.kind == UNDERSCORE) {
3015 log.error(pos, "underscore.as.identifier.in.lambda");
3016 name = token.name();
3017 nextToken();
3018 } else {
3019 if (allowThisIdent) {
3020 JCExpression pn = qualident(false);
3021 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3022 name = ((JCIdent)pn).name;
3023 } else {
3024 if ((mods.flags & Flags.VARARGS) != 0) {
3025 log.error(token.pos, "varargs.and.receiver");
3026 }
3027 if (token.kind == LBRACKET) {
3028 log.error(token.pos, "array.and.receiver");
3029 }
3030 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3031 }
3032 } else {
3033 name = ident();
3034 }
3035 }
3036 if ((mods.flags & Flags.VARARGS) != 0 &&
3037 token.kind == LBRACKET) {
3038 log.error(token.pos, "varargs.and.old.array.syntax");
3039 }
3040 type = bracketsOpt(type);
3041 return toP(F.at(pos).VarDef(mods, name, type, null));
3042 }
3044 /** Resources = Resource { ";" Resources }
3045 */
3046 List<JCTree> resources() {
3047 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3048 defs.append(resource());
3049 while (token.kind == SEMI) {
3050 // All but last of multiple declarators must subsume a semicolon
3051 storeEnd(defs.last(), token.endPos);
3052 int semiColonPos = token.pos;
3053 nextToken();
3054 if (token.kind == RPAREN) { // Optional trailing semicolon
3055 // after last resource
3056 break;
3057 }
3058 defs.append(resource());
3059 }
3060 return defs.toList();
3061 }
3063 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
3064 */
3065 protected JCTree resource() {
3066 JCModifiers optFinal = optFinal(Flags.FINAL);
3067 JCExpression type = parseType();
3068 int pos = token.pos;
3069 Name ident = ident();
3070 return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
3071 }
3073 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
3074 */
3075 public JCTree.JCCompilationUnit parseCompilationUnit() {
3076 Token firstToken = token;
3077 JCExpression pid = null;
3078 JCModifiers mods = null;
3079 boolean consumedToplevelDoc = false;
3080 boolean seenImport = false;
3081 boolean seenPackage = false;
3082 List<JCAnnotation> packageAnnotations = List.nil();
3083 if (token.kind == MONKEYS_AT)
3084 mods = modifiersOpt();
3086 if (token.kind == PACKAGE) {
3087 seenPackage = true;
3088 if (mods != null) {
3089 checkNoMods(mods.flags);
3090 packageAnnotations = mods.annotations;
3091 mods = null;
3092 }
3093 nextToken();
3094 pid = qualident(false);
3095 accept(SEMI);
3096 }
3097 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3098 boolean checkForImports = true;
3099 boolean firstTypeDecl = true;
3100 while (token.kind != EOF) {
3101 if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
3102 // error recovery
3103 skip(checkForImports, false, false, false);
3104 if (token.kind == EOF)
3105 break;
3106 }
3107 if (checkForImports && mods == null && token.kind == IMPORT) {
3108 seenImport = true;
3109 defs.append(importDeclaration());
3110 } else {
3111 Comment docComment = token.comment(CommentStyle.JAVADOC);
3112 if (firstTypeDecl && !seenImport && !seenPackage) {
3113 docComment = firstToken.comment(CommentStyle.JAVADOC);
3114 consumedToplevelDoc = true;
3115 }
3116 JCTree def = typeDeclaration(mods, docComment);
3117 if (def instanceof JCExpressionStatement)
3118 def = ((JCExpressionStatement)def).expr;
3119 defs.append(def);
3120 if (def instanceof JCClassDecl)
3121 checkForImports = false;
3122 mods = null;
3123 firstTypeDecl = false;
3124 }
3125 }
3126 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
3127 if (!consumedToplevelDoc)
3128 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
3129 if (defs.isEmpty())
3130 storeEnd(toplevel, S.prevToken().endPos);
3131 if (keepDocComments)
3132 toplevel.docComments = docComments;
3133 if (keepLineMap)
3134 toplevel.lineMap = S.getLineMap();
3135 this.endPosTable.setParser(null); // remove reference to parser
3136 toplevel.endPositions = this.endPosTable;
3137 return toplevel;
3138 }
3140 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
3141 */
3142 JCTree importDeclaration() {
3143 int pos = token.pos;
3144 nextToken();
3145 boolean importStatic = false;
3146 if (token.kind == STATIC) {
3147 checkStaticImports();
3148 importStatic = true;
3149 nextToken();
3150 }
3151 JCExpression pid = toP(F.at(token.pos).Ident(ident()));
3152 do {
3153 int pos1 = token.pos;
3154 accept(DOT);
3155 if (token.kind == STAR) {
3156 pid = to(F.at(pos1).Select(pid, names.asterisk));
3157 nextToken();
3158 break;
3159 } else {
3160 pid = toP(F.at(pos1).Select(pid, ident()));
3161 }
3162 } while (token.kind == DOT);
3163 accept(SEMI);
3164 return toP(F.at(pos).Import(pid, importStatic));
3165 }
3167 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
3168 * | ";"
3169 */
3170 JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
3171 int pos = token.pos;
3172 if (mods == null && token.kind == SEMI) {
3173 nextToken();
3174 return toP(F.at(pos).Skip());
3175 } else {
3176 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
3177 }
3178 }
3180 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
3181 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
3182 * @param mods Any modifiers starting the class or interface declaration
3183 * @param dc The documentation comment for the class, or null.
3184 */
3185 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
3186 if (token.kind == CLASS) {
3187 return classDeclaration(mods, dc);
3188 } else if (token.kind == INTERFACE) {
3189 return interfaceDeclaration(mods, dc);
3190 } else if (allowEnums) {
3191 if (token.kind == ENUM) {
3192 return enumDeclaration(mods, dc);
3193 } else {
3194 int pos = token.pos;
3195 List<JCTree> errs;
3196 if (LAX_IDENTIFIER.accepts(token.kind)) {
3197 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
3198 setErrorEndPos(token.pos);
3199 } else {
3200 errs = List.<JCTree>of(mods);
3201 }
3202 return toP(F.Exec(syntaxError(pos, errs, "expected3",
3203 CLASS, INTERFACE, ENUM)));
3204 }
3205 } else {
3206 if (token.kind == ENUM) {
3207 error(token.pos, "enums.not.supported.in.source", source.name);
3208 allowEnums = true;
3209 return enumDeclaration(mods, dc);
3210 }
3211 int pos = token.pos;
3212 List<JCTree> errs;
3213 if (LAX_IDENTIFIER.accepts(token.kind)) {
3214 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
3215 setErrorEndPos(token.pos);
3216 } else {
3217 errs = List.<JCTree>of(mods);
3218 }
3219 return toP(F.Exec(syntaxError(pos, errs, "expected2",
3220 CLASS, INTERFACE)));
3221 }
3222 }
3224 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
3225 * [IMPLEMENTS TypeList] ClassBody
3226 * @param mods The modifiers starting the class declaration
3227 * @param dc The documentation comment for the class, or null.
3228 */
3229 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
3230 int pos = token.pos;
3231 accept(CLASS);
3232 Name name = ident();
3234 List<JCTypeParameter> typarams = typeParametersOpt();
3236 JCExpression extending = null;
3237 if (token.kind == EXTENDS) {
3238 nextToken();
3239 extending = parseType();
3240 }
3241 List<JCExpression> implementing = List.nil();
3242 if (token.kind == IMPLEMENTS) {
3243 nextToken();
3244 implementing = typeList();
3245 }
3246 List<JCTree> defs = classOrInterfaceBody(name, false);
3247 JCClassDecl result = toP(F.at(pos).ClassDef(
3248 mods, name, typarams, extending, implementing, defs));
3249 attach(result, dc);
3250 return result;
3251 }
3253 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
3254 * [EXTENDS TypeList] InterfaceBody
3255 * @param mods The modifiers starting the interface declaration
3256 * @param dc The documentation comment for the interface, or null.
3257 */
3258 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
3259 int pos = token.pos;
3260 accept(INTERFACE);
3261 Name name = ident();
3263 List<JCTypeParameter> typarams = typeParametersOpt();
3265 List<JCExpression> extending = List.nil();
3266 if (token.kind == EXTENDS) {
3267 nextToken();
3268 extending = typeList();
3269 }
3270 List<JCTree> defs = classOrInterfaceBody(name, true);
3271 JCClassDecl result = toP(F.at(pos).ClassDef(
3272 mods, name, typarams, null, extending, defs));
3273 attach(result, dc);
3274 return result;
3275 }
3277 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
3278 * @param mods The modifiers starting the enum declaration
3279 * @param dc The documentation comment for the enum, or null.
3280 */
3281 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
3282 int pos = token.pos;
3283 accept(ENUM);
3284 Name name = ident();
3286 List<JCExpression> implementing = List.nil();
3287 if (token.kind == IMPLEMENTS) {
3288 nextToken();
3289 implementing = typeList();
3290 }
3292 List<JCTree> defs = enumBody(name);
3293 mods.flags |= Flags.ENUM;
3294 JCClassDecl result = toP(F.at(pos).
3295 ClassDef(mods, name, List.<JCTypeParameter>nil(),
3296 null, implementing, defs));
3297 attach(result, dc);
3298 return result;
3299 }
3301 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
3302 * [ ";" {ClassBodyDeclaration} ] "}"
3303 */
3304 List<JCTree> enumBody(Name enumName) {
3305 accept(LBRACE);
3306 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3307 if (token.kind == COMMA) {
3308 nextToken();
3309 } else if (token.kind != RBRACE && token.kind != SEMI) {
3310 defs.append(enumeratorDeclaration(enumName));
3311 while (token.kind == COMMA) {
3312 nextToken();
3313 if (token.kind == RBRACE || token.kind == SEMI) break;
3314 defs.append(enumeratorDeclaration(enumName));
3315 }
3316 if (token.kind != SEMI && token.kind != RBRACE) {
3317 defs.append(syntaxError(token.pos, "expected3",
3318 COMMA, RBRACE, SEMI));
3319 nextToken();
3320 }
3321 }
3322 if (token.kind == SEMI) {
3323 nextToken();
3324 while (token.kind != RBRACE && token.kind != EOF) {
3325 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
3326 false));
3327 if (token.pos <= endPosTable.errorEndPos) {
3328 // error recovery
3329 skip(false, true, true, false);
3330 }
3331 }
3332 }
3333 accept(RBRACE);
3334 return defs.toList();
3335 }
3337 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
3338 */
3339 JCTree enumeratorDeclaration(Name enumName) {
3340 Comment dc = token.comment(CommentStyle.JAVADOC);
3341 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
3342 if (token.deprecatedFlag()) {
3343 flags |= Flags.DEPRECATED;
3344 }
3345 int pos = token.pos;
3346 List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
3347 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
3348 List<JCExpression> typeArgs = typeArgumentsOpt();
3349 int identPos = token.pos;
3350 Name name = ident();
3351 int createPos = token.pos;
3352 List<JCExpression> args = (token.kind == LPAREN)
3353 ? arguments() : List.<JCExpression>nil();
3354 JCClassDecl body = null;
3355 if (token.kind == LBRACE) {
3356 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
3357 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
3358 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
3359 }
3360 if (args.isEmpty() && body == null)
3361 createPos = identPos;
3362 JCIdent ident = F.at(identPos).Ident(enumName);
3363 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
3364 if (createPos != identPos)
3365 storeEnd(create, S.prevToken().endPos);
3366 ident = F.at(identPos).Ident(enumName);
3367 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
3368 attach(result, dc);
3369 return result;
3370 }
3372 /** TypeList = Type {"," Type}
3373 */
3374 List<JCExpression> typeList() {
3375 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
3376 ts.append(parseType());
3377 while (token.kind == COMMA) {
3378 nextToken();
3379 ts.append(parseType());
3380 }
3381 return ts.toList();
3382 }
3384 /** ClassBody = "{" {ClassBodyDeclaration} "}"
3385 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
3386 */
3387 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
3388 accept(LBRACE);
3389 if (token.pos <= endPosTable.errorEndPos) {
3390 // error recovery
3391 skip(false, true, false, false);
3392 if (token.kind == LBRACE)
3393 nextToken();
3394 }
3395 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3396 while (token.kind != RBRACE && token.kind != EOF) {
3397 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
3398 if (token.pos <= endPosTable.errorEndPos) {
3399 // error recovery
3400 skip(false, true, true, false);
3401 }
3402 }
3403 accept(RBRACE);
3404 return defs.toList();
3405 }
3407 /** ClassBodyDeclaration =
3408 * ";"
3409 * | [STATIC] Block
3410 * | ModifiersOpt
3411 * ( Type Ident
3412 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
3413 * | VOID Ident VoidMethodDeclaratorRest
3414 * | TypeParameters [Annotations]
3415 * ( Type Ident MethodDeclaratorRest
3416 * | VOID Ident VoidMethodDeclaratorRest
3417 * )
3418 * | Ident ConstructorDeclaratorRest
3419 * | TypeParameters Ident ConstructorDeclaratorRest
3420 * | ClassOrInterfaceOrEnumDeclaration
3421 * )
3422 * InterfaceBodyDeclaration =
3423 * ";"
3424 * | ModifiersOpt
3425 * ( Type Ident
3426 * ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
3427 * | VOID Ident MethodDeclaratorRest
3428 * | TypeParameters [Annotations]
3429 * ( Type Ident MethodDeclaratorRest
3430 * | VOID Ident VoidMethodDeclaratorRest
3431 * )
3432 * | ClassOrInterfaceOrEnumDeclaration
3433 * )
3434 *
3435 */
3436 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
3437 if (token.kind == SEMI) {
3438 nextToken();
3439 return List.<JCTree>nil();
3440 } else {
3441 Comment dc = token.comment(CommentStyle.JAVADOC);
3442 int pos = token.pos;
3443 JCModifiers mods = modifiersOpt();
3444 if (token.kind == CLASS ||
3445 token.kind == INTERFACE ||
3446 allowEnums && token.kind == ENUM) {
3447 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
3448 } else if (token.kind == LBRACE && !isInterface &&
3449 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
3450 mods.annotations.isEmpty()) {
3451 return List.<JCTree>of(block(pos, mods.flags));
3452 } else {
3453 pos = token.pos;
3454 List<JCTypeParameter> typarams = typeParametersOpt();
3455 // if there are type parameters but no modifiers, save the start
3456 // position of the method in the modifiers.
3457 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
3458 mods.pos = pos;
3459 storeEnd(mods, pos);
3460 }
3461 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
3463 if (annosAfterParams.nonEmpty()) {
3464 checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
3465 mods.annotations = mods.annotations.appendList(annosAfterParams);
3466 if (mods.pos == Position.NOPOS)
3467 mods.pos = mods.annotations.head.pos;
3468 }
3470 Token tk = token;
3471 pos = token.pos;
3472 JCExpression type;
3473 boolean isVoid = token.kind == VOID;
3474 if (isVoid) {
3475 type = to(F.at(pos).TypeIdent(TypeTag.VOID));
3476 nextToken();
3477 } else {
3478 // method returns types are un-annotated types
3479 type = unannotatedType();
3480 }
3481 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
3482 if (isInterface || tk.name() != className)
3483 error(pos, "invalid.meth.decl.ret.type.req");
3484 else if (annosAfterParams.nonEmpty())
3485 illegal(annosAfterParams.head.pos);
3486 return List.of(methodDeclaratorRest(
3487 pos, mods, null, names.init, typarams,
3488 isInterface, true, dc));
3489 } else {
3490 pos = token.pos;
3491 Name name = ident();
3492 if (token.kind == LPAREN) {
3493 return List.of(methodDeclaratorRest(
3494 pos, mods, type, name, typarams,
3495 isInterface, isVoid, dc));
3496 } else if (!isVoid && typarams.isEmpty()) {
3497 List<JCTree> defs =
3498 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
3499 new ListBuffer<JCTree>()).toList();
3500 storeEnd(defs.last(), token.endPos);
3501 accept(SEMI);
3502 return defs;
3503 } else {
3504 pos = token.pos;
3505 List<JCTree> err = isVoid
3506 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
3507 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
3508 : null;
3509 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
3510 }
3511 }
3512 }
3513 }
3514 }
3516 /** MethodDeclaratorRest =
3517 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
3518 * VoidMethodDeclaratorRest =
3519 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
3520 * ConstructorDeclaratorRest =
3521 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
3522 */
3523 protected JCTree methodDeclaratorRest(int pos,
3524 JCModifiers mods,
3525 JCExpression type,
3526 Name name,
3527 List<JCTypeParameter> typarams,
3528 boolean isInterface, boolean isVoid,
3529 Comment dc) {
3530 if (isInterface && (mods.flags & Flags.STATIC) != 0) {
3531 checkStaticInterfaceMethods();
3532 }
3533 JCVariableDecl prevReceiverParam = this.receiverParam;
3534 try {
3535 this.receiverParam = null;
3536 // Parsing formalParameters sets the receiverParam, if present
3537 List<JCVariableDecl> params = formalParameters();
3538 if (!isVoid) type = bracketsOpt(type);
3539 List<JCExpression> thrown = List.nil();
3540 if (token.kind == THROWS) {
3541 nextToken();
3542 thrown = qualidentList();
3543 }
3544 JCBlock body = null;
3545 JCExpression defaultValue;
3546 if (token.kind == LBRACE) {
3547 body = block();
3548 defaultValue = null;
3549 } else {
3550 if (token.kind == DEFAULT) {
3551 accept(DEFAULT);
3552 defaultValue = annotationValue();
3553 } else {
3554 defaultValue = null;
3555 }
3556 accept(SEMI);
3557 if (token.pos <= endPosTable.errorEndPos) {
3558 // error recovery
3559 skip(false, true, false, false);
3560 if (token.kind == LBRACE) {
3561 body = block();
3562 }
3563 }
3564 }
3566 JCMethodDecl result =
3567 toP(F.at(pos).MethodDef(mods, name, type, typarams,
3568 receiverParam, params, thrown,
3569 body, defaultValue));
3570 attach(result, dc);
3571 return result;
3572 } finally {
3573 this.receiverParam = prevReceiverParam;
3574 }
3575 }
3577 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
3578 */
3579 List<JCExpression> qualidentList() {
3580 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
3582 List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
3583 JCExpression qi = qualident(true);
3584 if (!typeAnnos.isEmpty()) {
3585 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
3586 ts.append(at);
3587 } else {
3588 ts.append(qi);
3589 }
3590 while (token.kind == COMMA) {
3591 nextToken();
3593 typeAnnos = typeAnnotationsOpt();
3594 qi = qualident(true);
3595 if (!typeAnnos.isEmpty()) {
3596 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
3597 ts.append(at);
3598 } else {
3599 ts.append(qi);
3600 }
3601 }
3602 return ts.toList();
3603 }
3605 /**
3606 * {@literal
3607 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
3608 * }
3609 */
3610 List<JCTypeParameter> typeParametersOpt() {
3611 if (token.kind == LT) {
3612 checkGenerics();
3613 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
3614 nextToken();
3615 typarams.append(typeParameter());
3616 while (token.kind == COMMA) {
3617 nextToken();
3618 typarams.append(typeParameter());
3619 }
3620 accept(GT);
3621 return typarams.toList();
3622 } else {
3623 return List.nil();
3624 }
3625 }
3627 /**
3628 * {@literal
3629 * TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
3630 * TypeParameterBound = EXTENDS Type {"&" Type}
3631 * TypeVariable = Ident
3632 * }
3633 */
3634 JCTypeParameter typeParameter() {
3635 int pos = token.pos;
3636 List<JCAnnotation> annos = typeAnnotationsOpt();
3637 Name name = ident();
3638 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
3639 if (token.kind == EXTENDS) {
3640 nextToken();
3641 bounds.append(parseType());
3642 while (token.kind == AMP) {
3643 nextToken();
3644 bounds.append(parseType());
3645 }
3646 }
3647 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
3648 }
3650 /** FormalParameters = "(" [ FormalParameterList ] ")"
3651 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
3652 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
3653 */
3654 List<JCVariableDecl> formalParameters() {
3655 return formalParameters(false);
3656 }
3657 List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
3658 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3659 JCVariableDecl lastParam;
3660 accept(LPAREN);
3661 if (token.kind != RPAREN) {
3662 this.allowThisIdent = true;
3663 lastParam = formalParameter(lambdaParameters);
3664 if (lastParam.nameexpr != null) {
3665 this.receiverParam = lastParam;
3666 } else {
3667 params.append(lastParam);
3668 }
3669 this.allowThisIdent = false;
3670 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
3671 nextToken();
3672 params.append(lastParam = formalParameter(lambdaParameters));
3673 }
3674 }
3675 accept(RPAREN);
3676 return params.toList();
3677 }
3679 List<JCVariableDecl> implicitParameters(boolean hasParens) {
3680 if (hasParens) {
3681 accept(LPAREN);
3682 }
3683 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3684 if (token.kind != RPAREN && token.kind != ARROW) {
3685 params.append(implicitParameter());
3686 while (token.kind == COMMA) {
3687 nextToken();
3688 params.append(implicitParameter());
3689 }
3690 }
3691 if (hasParens) {
3692 accept(RPAREN);
3693 }
3694 return params.toList();
3695 }
3697 JCModifiers optFinal(long flags) {
3698 JCModifiers mods = modifiersOpt();
3699 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
3700 mods.flags |= flags;
3701 return mods;
3702 }
3704 /**
3705 * Inserts the annotations (and possibly a new array level)
3706 * to the left-most type in an array or nested type.
3707 *
3708 * When parsing a type like {@code @B Outer.Inner @A []}, the
3709 * {@code @A} annotation should target the array itself, while
3710 * {@code @B} targets the nested type {@code Outer}.
3711 *
3712 * Currently the parser parses the annotation first, then
3713 * the array, and then inserts the annotation to the left-most
3714 * nested type.
3715 *
3716 * When {@code createNewLevel} is true, then a new array
3717 * level is inserted as the most inner type, and have the
3718 * annotations target it. This is useful in the case of
3719 * varargs, e.g. {@code String @A [] @B ...}, as the parser
3720 * first parses the type {@code String @A []} then inserts
3721 * a new array level with {@code @B} annotation.
3722 */
3723 private JCExpression insertAnnotationsToMostInner(
3724 JCExpression type, List<JCAnnotation> annos,
3725 boolean createNewLevel) {
3726 int origEndPos = getEndPos(type);
3727 JCExpression mostInnerType = type;
3728 JCArrayTypeTree mostInnerArrayType = null;
3729 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
3730 mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
3731 mostInnerType = mostInnerArrayType.elemtype;
3732 }
3734 if (createNewLevel) {
3735 mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
3736 }
3738 JCExpression mostInnerTypeToReturn = mostInnerType;
3739 if (annos.nonEmpty()) {
3740 JCExpression lastToModify = mostInnerType;
3742 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
3743 TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
3744 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
3745 lastToModify = mostInnerType;
3746 mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
3747 }
3748 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
3749 lastToModify = mostInnerType;
3750 mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
3751 }
3752 }
3754 mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
3756 if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
3757 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
3758 } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
3759 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
3760 } else {
3761 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
3762 mostInnerTypeToReturn = mostInnerType;
3763 }
3764 }
3766 if (mostInnerArrayType == null) {
3767 return mostInnerTypeToReturn;
3768 } else {
3769 mostInnerArrayType.elemtype = mostInnerTypeToReturn;
3770 storeEnd(type, origEndPos);
3771 return type;
3772 }
3773 }
3775 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
3776 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
3777 */
3778 protected JCVariableDecl formalParameter() {
3779 return formalParameter(false);
3780 }
3781 protected JCVariableDecl formalParameter(boolean lambdaParameter) {
3782 JCModifiers mods = optFinal(Flags.PARAMETER);
3783 // need to distinguish between vararg annos and array annos
3784 // look at typeAnnotationsPushedBack comment
3785 this.permitTypeAnnotationsPushBack = true;
3786 JCExpression type = parseType();
3787 this.permitTypeAnnotationsPushBack = false;
3789 if (token.kind == ELLIPSIS) {
3790 List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
3791 typeAnnotationsPushedBack = List.nil();
3792 checkVarargs();
3793 mods.flags |= Flags.VARARGS;
3794 // insert var arg type annotations
3795 type = insertAnnotationsToMostInner(type, varargsAnnos, true);
3796 nextToken();
3797 } else {
3798 // if not a var arg, then typeAnnotationsPushedBack should be null
3799 if (typeAnnotationsPushedBack.nonEmpty()) {
3800 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
3801 "illegal.start.of.type");
3802 }
3803 typeAnnotationsPushedBack = List.nil();
3804 }
3805 return variableDeclaratorId(mods, type, lambdaParameter);
3806 }
3808 protected JCVariableDecl implicitParameter() {
3809 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
3810 return variableDeclaratorId(mods, null, true);
3811 }
3813 /* ---------- auxiliary methods -------------- */
3815 void error(int pos, String key, Object ... args) {
3816 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3817 }
3819 void error(DiagnosticPosition pos, String key, Object ... args) {
3820 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3821 }
3823 void warning(int pos, String key, Object ... args) {
3824 log.warning(pos, key, args);
3825 }
3827 /** Check that given tree is a legal expression statement.
3828 */
3829 protected JCExpression checkExprStat(JCExpression t) {
3830 if (!TreeInfo.isExpressionStatement(t)) {
3831 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
3832 error(ret, "not.stmt");
3833 return ret;
3834 } else {
3835 return t;
3836 }
3837 }
3839 /** Return precedence of operator represented by token,
3840 * -1 if token is not a binary operator. @see TreeInfo.opPrec
3841 */
3842 static int prec(TokenKind token) {
3843 JCTree.Tag oc = optag(token);
3844 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
3845 }
3847 /**
3848 * Return the lesser of two positions, making allowance for either one
3849 * being unset.
3850 */
3851 static int earlier(int pos1, int pos2) {
3852 if (pos1 == Position.NOPOS)
3853 return pos2;
3854 if (pos2 == Position.NOPOS)
3855 return pos1;
3856 return (pos1 < pos2 ? pos1 : pos2);
3857 }
3859 /** Return operation tag of binary operator represented by token,
3860 * No_TAG if token is not a binary operator.
3861 */
3862 static JCTree.Tag optag(TokenKind token) {
3863 switch (token) {
3864 case BARBAR:
3865 return OR;
3866 case AMPAMP:
3867 return AND;
3868 case BAR:
3869 return BITOR;
3870 case BAREQ:
3871 return BITOR_ASG;
3872 case CARET:
3873 return BITXOR;
3874 case CARETEQ:
3875 return BITXOR_ASG;
3876 case AMP:
3877 return BITAND;
3878 case AMPEQ:
3879 return BITAND_ASG;
3880 case EQEQ:
3881 return JCTree.Tag.EQ;
3882 case BANGEQ:
3883 return NE;
3884 case LT:
3885 return JCTree.Tag.LT;
3886 case GT:
3887 return JCTree.Tag.GT;
3888 case LTEQ:
3889 return LE;
3890 case GTEQ:
3891 return GE;
3892 case LTLT:
3893 return SL;
3894 case LTLTEQ:
3895 return SL_ASG;
3896 case GTGT:
3897 return SR;
3898 case GTGTEQ:
3899 return SR_ASG;
3900 case GTGTGT:
3901 return USR;
3902 case GTGTGTEQ:
3903 return USR_ASG;
3904 case PLUS:
3905 return JCTree.Tag.PLUS;
3906 case PLUSEQ:
3907 return PLUS_ASG;
3908 case SUB:
3909 return MINUS;
3910 case SUBEQ:
3911 return MINUS_ASG;
3912 case STAR:
3913 return MUL;
3914 case STAREQ:
3915 return MUL_ASG;
3916 case SLASH:
3917 return DIV;
3918 case SLASHEQ:
3919 return DIV_ASG;
3920 case PERCENT:
3921 return MOD;
3922 case PERCENTEQ:
3923 return MOD_ASG;
3924 case INSTANCEOF:
3925 return TYPETEST;
3926 default:
3927 return NO_TAG;
3928 }
3929 }
3931 /** Return operation tag of unary operator represented by token,
3932 * No_TAG if token is not a binary operator.
3933 */
3934 static JCTree.Tag unoptag(TokenKind token) {
3935 switch (token) {
3936 case PLUS:
3937 return POS;
3938 case SUB:
3939 return NEG;
3940 case BANG:
3941 return NOT;
3942 case TILDE:
3943 return COMPL;
3944 case PLUSPLUS:
3945 return PREINC;
3946 case SUBSUB:
3947 return PREDEC;
3948 default:
3949 return NO_TAG;
3950 }
3951 }
3953 /** Return type tag of basic type represented by token,
3954 * NONE if token is not a basic type identifier.
3955 */
3956 static TypeTag typetag(TokenKind token) {
3957 switch (token) {
3958 case BYTE:
3959 return TypeTag.BYTE;
3960 case CHAR:
3961 return TypeTag.CHAR;
3962 case SHORT:
3963 return TypeTag.SHORT;
3964 case INT:
3965 return TypeTag.INT;
3966 case LONG:
3967 return TypeTag.LONG;
3968 case FLOAT:
3969 return TypeTag.FLOAT;
3970 case DOUBLE:
3971 return TypeTag.DOUBLE;
3972 case BOOLEAN:
3973 return TypeTag.BOOLEAN;
3974 default:
3975 return TypeTag.NONE;
3976 }
3977 }
3979 void checkGenerics() {
3980 if (!allowGenerics) {
3981 error(token.pos, "generics.not.supported.in.source", source.name);
3982 allowGenerics = true;
3983 }
3984 }
3985 void checkVarargs() {
3986 if (!allowVarargs) {
3987 error(token.pos, "varargs.not.supported.in.source", source.name);
3988 allowVarargs = true;
3989 }
3990 }
3991 void checkForeach() {
3992 if (!allowForeach) {
3993 error(token.pos, "foreach.not.supported.in.source", source.name);
3994 allowForeach = true;
3995 }
3996 }
3997 void checkStaticImports() {
3998 if (!allowStaticImport) {
3999 error(token.pos, "static.import.not.supported.in.source", source.name);
4000 allowStaticImport = true;
4001 }
4002 }
4003 void checkAnnotations() {
4004 if (!allowAnnotations) {
4005 error(token.pos, "annotations.not.supported.in.source", source.name);
4006 allowAnnotations = true;
4007 }
4008 }
4009 void checkDiamond() {
4010 if (!allowDiamond) {
4011 error(token.pos, "diamond.not.supported.in.source", source.name);
4012 allowDiamond = true;
4013 }
4014 }
4015 void checkMulticatch() {
4016 if (!allowMulticatch) {
4017 error(token.pos, "multicatch.not.supported.in.source", source.name);
4018 allowMulticatch = true;
4019 }
4020 }
4021 void checkTryWithResources() {
4022 if (!allowTWR) {
4023 error(token.pos, "try.with.resources.not.supported.in.source", source.name);
4024 allowTWR = true;
4025 }
4026 }
4027 void checkLambda() {
4028 if (!allowLambda) {
4029 log.error(token.pos, "lambda.not.supported.in.source", source.name);
4030 allowLambda = true;
4031 }
4032 }
4033 void checkMethodReferences() {
4034 if (!allowMethodReferences) {
4035 log.error(token.pos, "method.references.not.supported.in.source", source.name);
4036 allowMethodReferences = true;
4037 }
4038 }
4039 void checkDefaultMethods() {
4040 if (!allowDefaultMethods) {
4041 log.error(token.pos, "default.methods.not.supported.in.source", source.name);
4042 allowDefaultMethods = true;
4043 }
4044 }
4045 void checkIntersectionTypesInCast() {
4046 if (!allowIntersectionTypesInCast) {
4047 log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
4048 allowIntersectionTypesInCast = true;
4049 }
4050 }
4051 void checkStaticInterfaceMethods() {
4052 if (!allowStaticInterfaceMethods) {
4053 log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name);
4054 allowStaticInterfaceMethods = true;
4055 }
4056 }
4057 void checkTypeAnnotations() {
4058 if (!allowTypeAnnotations) {
4059 log.error(token.pos, "type.annotations.not.supported.in.source", source.name);
4060 allowTypeAnnotations = true;
4061 }
4062 }
4063 void checkAnnotationsAfterTypeParams(int pos) {
4064 if (!allowAnnotationsAfterTypeParams) {
4065 log.error(pos, "annotations.after.type.params.not.supported.in.source", source.name);
4066 allowAnnotationsAfterTypeParams = true;
4067 }
4068 }
4070 /*
4071 * a functional source tree and end position mappings
4072 */
4073 protected static class SimpleEndPosTable extends AbstractEndPosTable {
4075 private final IntHashTable endPosMap;
4077 SimpleEndPosTable(JavacParser parser) {
4078 super(parser);
4079 endPosMap = new IntHashTable();
4080 }
4082 public void storeEnd(JCTree tree, int endpos) {
4083 endPosMap.putAtIndex(tree, errorEndPos > endpos ? errorEndPos : endpos,
4084 endPosMap.lookup(tree));
4085 }
4087 protected <T extends JCTree> T to(T t) {
4088 storeEnd(t, parser.token.endPos);
4089 return t;
4090 }
4092 protected <T extends JCTree> T toP(T t) {
4093 storeEnd(t, parser.S.prevToken().endPos);
4094 return t;
4095 }
4097 public int getEndPos(JCTree tree) {
4098 int value = endPosMap.getFromIndex(endPosMap.lookup(tree));
4099 // As long as Position.NOPOS==-1, this just returns value.
4100 return (value == -1) ? Position.NOPOS : value;
4101 }
4103 public int replaceTree(JCTree oldTree, JCTree newTree) {
4104 int pos = endPosMap.remove(oldTree);
4105 if (pos != -1) {
4106 storeEnd(newTree, pos);
4107 return pos;
4108 }
4109 return Position.NOPOS;
4110 }
4111 }
4113 /*
4114 * a default skeletal implementation without any mapping overhead.
4115 */
4116 protected static class EmptyEndPosTable extends AbstractEndPosTable {
4118 EmptyEndPosTable(JavacParser parser) {
4119 super(parser);
4120 }
4122 public void storeEnd(JCTree tree, int endpos) { /* empty */ }
4124 protected <T extends JCTree> T to(T t) {
4125 return t;
4126 }
4128 protected <T extends JCTree> T toP(T t) {
4129 return t;
4130 }
4132 public int getEndPos(JCTree tree) {
4133 return Position.NOPOS;
4134 }
4136 public int replaceTree(JCTree oldTree, JCTree newTree) {
4137 return Position.NOPOS;
4138 }
4140 }
4142 protected static abstract class AbstractEndPosTable implements EndPosTable {
4143 /**
4144 * The current parser.
4145 */
4146 protected JavacParser parser;
4148 /**
4149 * Store the last error position.
4150 */
4151 protected int errorEndPos;
4153 public AbstractEndPosTable(JavacParser parser) {
4154 this.parser = parser;
4155 }
4157 /**
4158 * Store current token's ending position for a tree, the value of which
4159 * will be the greater of last error position and the ending position of
4160 * the current token.
4161 * @param t The tree.
4162 */
4163 protected abstract <T extends JCTree> T to(T t);
4165 /**
4166 * Store current token's ending position for a tree, the value of which
4167 * will be the greater of last error position and the ending position of
4168 * the previous token.
4169 * @param t The tree.
4170 */
4171 protected abstract <T extends JCTree> T toP(T t);
4173 /**
4174 * Set the error position during the parsing phases, the value of which
4175 * will be set only if it is greater than the last stored error position.
4176 * @param errPos The error position
4177 */
4178 protected void setErrorEndPos(int errPos) {
4179 if (errPos > errorEndPos) {
4180 errorEndPos = errPos;
4181 }
4182 }
4184 protected void setParser(JavacParser parser) {
4185 this.parser = parser;
4186 }
4187 }
4188 }