Wed, 27 Apr 2016 01:34:52 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17
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(modifiersOpt(), 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 /* A modifiers tree with no modifier tokens or annotations
2833 * has no text position. */
2834 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
2835 pos = Position.NOPOS;
2837 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
2838 if (pos != Position.NOPOS)
2839 storeEnd(mods, S.prevToken().endPos);
2840 return mods;
2841 }
2843 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2844 *
2845 * @param pos position of "@" token
2846 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
2847 */
2848 JCAnnotation annotation(int pos, Tag kind) {
2849 // accept(AT); // AT consumed by caller
2850 checkAnnotations();
2851 if (kind == Tag.TYPE_ANNOTATION) {
2852 checkTypeAnnotations();
2853 }
2854 JCTree ident = qualident(false);
2855 List<JCExpression> fieldValues = annotationFieldValuesOpt();
2856 JCAnnotation ann;
2857 if (kind == Tag.ANNOTATION) {
2858 ann = F.at(pos).Annotation(ident, fieldValues);
2859 } else if (kind == Tag.TYPE_ANNOTATION) {
2860 ann = F.at(pos).TypeAnnotation(ident, fieldValues);
2861 } else {
2862 throw new AssertionError("Unhandled annotation kind: " + kind);
2863 }
2865 storeEnd(ann, S.prevToken().endPos);
2866 return ann;
2867 }
2869 List<JCExpression> annotationFieldValuesOpt() {
2870 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2871 }
2873 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2874 List<JCExpression> annotationFieldValues() {
2875 accept(LPAREN);
2876 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2877 if (token.kind != RPAREN) {
2878 buf.append(annotationFieldValue());
2879 while (token.kind == COMMA) {
2880 nextToken();
2881 buf.append(annotationFieldValue());
2882 }
2883 }
2884 accept(RPAREN);
2885 return buf.toList();
2886 }
2888 /** AnnotationFieldValue = AnnotationValue
2889 * | Identifier "=" AnnotationValue
2890 */
2891 JCExpression annotationFieldValue() {
2892 if (LAX_IDENTIFIER.accepts(token.kind)) {
2893 mode = EXPR;
2894 JCExpression t1 = term1();
2895 if (t1.hasTag(IDENT) && token.kind == EQ) {
2896 int pos = token.pos;
2897 accept(EQ);
2898 JCExpression v = annotationValue();
2899 return toP(F.at(pos).Assign(t1, v));
2900 } else {
2901 return t1;
2902 }
2903 }
2904 return annotationValue();
2905 }
2907 /* AnnotationValue = ConditionalExpression
2908 * | Annotation
2909 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2910 */
2911 JCExpression annotationValue() {
2912 int pos;
2913 switch (token.kind) {
2914 case MONKEYS_AT:
2915 pos = token.pos;
2916 nextToken();
2917 return annotation(pos, Tag.ANNOTATION);
2918 case LBRACE:
2919 pos = token.pos;
2920 accept(LBRACE);
2921 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2922 if (token.kind == COMMA) {
2923 nextToken();
2924 } else if (token.kind != RBRACE) {
2925 buf.append(annotationValue());
2926 while (token.kind == COMMA) {
2927 nextToken();
2928 if (token.kind == RBRACE) break;
2929 buf.append(annotationValue());
2930 }
2931 }
2932 accept(RBRACE);
2933 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2934 default:
2935 mode = EXPR;
2936 return term1();
2937 }
2938 }
2940 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2941 */
2942 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2943 JCExpression type,
2944 T vdefs)
2945 {
2946 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
2947 }
2949 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2950 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2951 *
2952 * @param reqInit Is an initializer always required?
2953 * @param dc The documentation comment for the variable declarations, or null.
2954 */
2955 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2956 JCModifiers mods,
2957 JCExpression type,
2958 Name name,
2959 boolean reqInit,
2960 Comment dc,
2961 T vdefs)
2962 {
2963 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2964 while (token.kind == COMMA) {
2965 // All but last of multiple declarators subsume a comma
2966 storeEnd((JCTree)vdefs.last(), token.endPos);
2967 nextToken();
2968 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2969 }
2970 return vdefs;
2971 }
2973 /** VariableDeclarator = Ident VariableDeclaratorRest
2974 * ConstantDeclarator = Ident ConstantDeclaratorRest
2975 */
2976 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
2977 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
2978 }
2980 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2981 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2982 *
2983 * @param reqInit Is an initializer always required?
2984 * @param dc The documentation comment for the variable declarations, or null.
2985 */
2986 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2987 boolean reqInit, Comment dc) {
2988 type = bracketsOpt(type);
2989 JCExpression init = null;
2990 if (token.kind == EQ) {
2991 nextToken();
2992 init = variableInitializer();
2993 }
2994 else if (reqInit) syntaxError(token.pos, "expected", EQ);
2995 JCVariableDecl result =
2996 toP(F.at(pos).VarDef(mods, name, type, init));
2997 attach(result, dc);
2998 return result;
2999 }
3001 /** VariableDeclaratorId = Ident BracketsOpt
3002 */
3003 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
3004 return variableDeclaratorId(mods, type, false);
3005 }
3006 //where
3007 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
3008 int pos = token.pos;
3009 Name name;
3010 if (lambdaParameter && token.kind == UNDERSCORE) {
3011 log.error(pos, "underscore.as.identifier.in.lambda");
3012 name = token.name();
3013 nextToken();
3014 } else {
3015 if (allowThisIdent) {
3016 JCExpression pn = qualident(false);
3017 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3018 name = ((JCIdent)pn).name;
3019 } else {
3020 if ((mods.flags & Flags.VARARGS) != 0) {
3021 log.error(token.pos, "varargs.and.receiver");
3022 }
3023 if (token.kind == LBRACKET) {
3024 log.error(token.pos, "array.and.receiver");
3025 }
3026 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3027 }
3028 } else {
3029 name = ident();
3030 }
3031 }
3032 if ((mods.flags & Flags.VARARGS) != 0 &&
3033 token.kind == LBRACKET) {
3034 log.error(token.pos, "varargs.and.old.array.syntax");
3035 }
3036 type = bracketsOpt(type);
3037 return toP(F.at(pos).VarDef(mods, name, type, null));
3038 }
3040 /** Resources = Resource { ";" Resources }
3041 */
3042 List<JCTree> resources() {
3043 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3044 defs.append(resource());
3045 while (token.kind == SEMI) {
3046 // All but last of multiple declarators must subsume a semicolon
3047 storeEnd(defs.last(), token.endPos);
3048 int semiColonPos = token.pos;
3049 nextToken();
3050 if (token.kind == RPAREN) { // Optional trailing semicolon
3051 // after last resource
3052 break;
3053 }
3054 defs.append(resource());
3055 }
3056 return defs.toList();
3057 }
3059 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
3060 */
3061 protected JCTree resource() {
3062 JCModifiers optFinal = optFinal(Flags.FINAL);
3063 JCExpression type = parseType();
3064 int pos = token.pos;
3065 Name ident = ident();
3066 return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
3067 }
3069 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
3070 */
3071 public JCTree.JCCompilationUnit parseCompilationUnit() {
3072 Token firstToken = token;
3073 JCExpression pid = null;
3074 JCModifiers mods = null;
3075 boolean consumedToplevelDoc = false;
3076 boolean seenImport = false;
3077 boolean seenPackage = false;
3078 List<JCAnnotation> packageAnnotations = List.nil();
3079 if (token.kind == MONKEYS_AT)
3080 mods = modifiersOpt();
3082 if (token.kind == PACKAGE) {
3083 seenPackage = true;
3084 if (mods != null) {
3085 checkNoMods(mods.flags);
3086 packageAnnotations = mods.annotations;
3087 mods = null;
3088 }
3089 nextToken();
3090 pid = qualident(false);
3091 accept(SEMI);
3092 }
3093 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3094 boolean checkForImports = true;
3095 boolean firstTypeDecl = true;
3096 while (token.kind != EOF) {
3097 if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
3098 // error recovery
3099 skip(checkForImports, false, false, false);
3100 if (token.kind == EOF)
3101 break;
3102 }
3103 if (checkForImports && mods == null && token.kind == IMPORT) {
3104 seenImport = true;
3105 defs.append(importDeclaration());
3106 } else {
3107 Comment docComment = token.comment(CommentStyle.JAVADOC);
3108 if (firstTypeDecl && !seenImport && !seenPackage) {
3109 docComment = firstToken.comment(CommentStyle.JAVADOC);
3110 consumedToplevelDoc = true;
3111 }
3112 JCTree def = typeDeclaration(mods, docComment);
3113 if (def instanceof JCExpressionStatement)
3114 def = ((JCExpressionStatement)def).expr;
3115 defs.append(def);
3116 if (def instanceof JCClassDecl)
3117 checkForImports = false;
3118 mods = null;
3119 firstTypeDecl = false;
3120 }
3121 }
3122 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
3123 if (!consumedToplevelDoc)
3124 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
3125 if (defs.isEmpty())
3126 storeEnd(toplevel, S.prevToken().endPos);
3127 if (keepDocComments)
3128 toplevel.docComments = docComments;
3129 if (keepLineMap)
3130 toplevel.lineMap = S.getLineMap();
3131 this.endPosTable.setParser(null); // remove reference to parser
3132 toplevel.endPositions = this.endPosTable;
3133 return toplevel;
3134 }
3136 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
3137 */
3138 JCTree importDeclaration() {
3139 int pos = token.pos;
3140 nextToken();
3141 boolean importStatic = false;
3142 if (token.kind == STATIC) {
3143 checkStaticImports();
3144 importStatic = true;
3145 nextToken();
3146 }
3147 JCExpression pid = toP(F.at(token.pos).Ident(ident()));
3148 do {
3149 int pos1 = token.pos;
3150 accept(DOT);
3151 if (token.kind == STAR) {
3152 pid = to(F.at(pos1).Select(pid, names.asterisk));
3153 nextToken();
3154 break;
3155 } else {
3156 pid = toP(F.at(pos1).Select(pid, ident()));
3157 }
3158 } while (token.kind == DOT);
3159 accept(SEMI);
3160 return toP(F.at(pos).Import(pid, importStatic));
3161 }
3163 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
3164 * | ";"
3165 */
3166 JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
3167 int pos = token.pos;
3168 if (mods == null && token.kind == SEMI) {
3169 nextToken();
3170 return toP(F.at(pos).Skip());
3171 } else {
3172 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
3173 }
3174 }
3176 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
3177 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
3178 * @param mods Any modifiers starting the class or interface declaration
3179 * @param dc The documentation comment for the class, or null.
3180 */
3181 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
3182 if (token.kind == CLASS) {
3183 return classDeclaration(mods, dc);
3184 } else if (token.kind == INTERFACE) {
3185 return interfaceDeclaration(mods, dc);
3186 } else if (allowEnums) {
3187 if (token.kind == ENUM) {
3188 return enumDeclaration(mods, dc);
3189 } else {
3190 int pos = token.pos;
3191 List<JCTree> errs;
3192 if (LAX_IDENTIFIER.accepts(token.kind)) {
3193 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
3194 setErrorEndPos(token.pos);
3195 } else {
3196 errs = List.<JCTree>of(mods);
3197 }
3198 return toP(F.Exec(syntaxError(pos, errs, "expected3",
3199 CLASS, INTERFACE, ENUM)));
3200 }
3201 } else {
3202 if (token.kind == ENUM) {
3203 error(token.pos, "enums.not.supported.in.source", source.name);
3204 allowEnums = true;
3205 return enumDeclaration(mods, dc);
3206 }
3207 int pos = token.pos;
3208 List<JCTree> errs;
3209 if (LAX_IDENTIFIER.accepts(token.kind)) {
3210 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
3211 setErrorEndPos(token.pos);
3212 } else {
3213 errs = List.<JCTree>of(mods);
3214 }
3215 return toP(F.Exec(syntaxError(pos, errs, "expected2",
3216 CLASS, INTERFACE)));
3217 }
3218 }
3220 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
3221 * [IMPLEMENTS TypeList] ClassBody
3222 * @param mods The modifiers starting the class declaration
3223 * @param dc The documentation comment for the class, or null.
3224 */
3225 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
3226 int pos = token.pos;
3227 accept(CLASS);
3228 Name name = ident();
3230 List<JCTypeParameter> typarams = typeParametersOpt();
3232 JCExpression extending = null;
3233 if (token.kind == EXTENDS) {
3234 nextToken();
3235 extending = parseType();
3236 }
3237 List<JCExpression> implementing = List.nil();
3238 if (token.kind == IMPLEMENTS) {
3239 nextToken();
3240 implementing = typeList();
3241 }
3242 List<JCTree> defs = classOrInterfaceBody(name, false);
3243 JCClassDecl result = toP(F.at(pos).ClassDef(
3244 mods, name, typarams, extending, implementing, defs));
3245 attach(result, dc);
3246 return result;
3247 }
3249 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
3250 * [EXTENDS TypeList] InterfaceBody
3251 * @param mods The modifiers starting the interface declaration
3252 * @param dc The documentation comment for the interface, or null.
3253 */
3254 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
3255 int pos = token.pos;
3256 accept(INTERFACE);
3257 Name name = ident();
3259 List<JCTypeParameter> typarams = typeParametersOpt();
3261 List<JCExpression> extending = List.nil();
3262 if (token.kind == EXTENDS) {
3263 nextToken();
3264 extending = typeList();
3265 }
3266 List<JCTree> defs = classOrInterfaceBody(name, true);
3267 JCClassDecl result = toP(F.at(pos).ClassDef(
3268 mods, name, typarams, null, extending, defs));
3269 attach(result, dc);
3270 return result;
3271 }
3273 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
3274 * @param mods The modifiers starting the enum declaration
3275 * @param dc The documentation comment for the enum, or null.
3276 */
3277 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
3278 int pos = token.pos;
3279 accept(ENUM);
3280 Name name = ident();
3282 List<JCExpression> implementing = List.nil();
3283 if (token.kind == IMPLEMENTS) {
3284 nextToken();
3285 implementing = typeList();
3286 }
3288 List<JCTree> defs = enumBody(name);
3289 mods.flags |= Flags.ENUM;
3290 JCClassDecl result = toP(F.at(pos).
3291 ClassDef(mods, name, List.<JCTypeParameter>nil(),
3292 null, implementing, defs));
3293 attach(result, dc);
3294 return result;
3295 }
3297 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
3298 * [ ";" {ClassBodyDeclaration} ] "}"
3299 */
3300 List<JCTree> enumBody(Name enumName) {
3301 accept(LBRACE);
3302 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3303 if (token.kind == COMMA) {
3304 nextToken();
3305 } else if (token.kind != RBRACE && token.kind != SEMI) {
3306 defs.append(enumeratorDeclaration(enumName));
3307 while (token.kind == COMMA) {
3308 nextToken();
3309 if (token.kind == RBRACE || token.kind == SEMI) break;
3310 defs.append(enumeratorDeclaration(enumName));
3311 }
3312 if (token.kind != SEMI && token.kind != RBRACE) {
3313 defs.append(syntaxError(token.pos, "expected3",
3314 COMMA, RBRACE, SEMI));
3315 nextToken();
3316 }
3317 }
3318 if (token.kind == SEMI) {
3319 nextToken();
3320 while (token.kind != RBRACE && token.kind != EOF) {
3321 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
3322 false));
3323 if (token.pos <= endPosTable.errorEndPos) {
3324 // error recovery
3325 skip(false, true, true, false);
3326 }
3327 }
3328 }
3329 accept(RBRACE);
3330 return defs.toList();
3331 }
3333 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
3334 */
3335 JCTree enumeratorDeclaration(Name enumName) {
3336 Comment dc = token.comment(CommentStyle.JAVADOC);
3337 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
3338 if (token.deprecatedFlag()) {
3339 flags |= Flags.DEPRECATED;
3340 }
3341 int pos = token.pos;
3342 List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
3343 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
3344 List<JCExpression> typeArgs = typeArgumentsOpt();
3345 int identPos = token.pos;
3346 Name name = ident();
3347 int createPos = token.pos;
3348 List<JCExpression> args = (token.kind == LPAREN)
3349 ? arguments() : List.<JCExpression>nil();
3350 JCClassDecl body = null;
3351 if (token.kind == LBRACE) {
3352 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
3353 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
3354 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
3355 }
3356 if (args.isEmpty() && body == null)
3357 createPos = identPos;
3358 JCIdent ident = F.at(identPos).Ident(enumName);
3359 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
3360 if (createPos != identPos)
3361 storeEnd(create, S.prevToken().endPos);
3362 ident = F.at(identPos).Ident(enumName);
3363 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
3364 attach(result, dc);
3365 return result;
3366 }
3368 /** TypeList = Type {"," Type}
3369 */
3370 List<JCExpression> typeList() {
3371 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
3372 ts.append(parseType());
3373 while (token.kind == COMMA) {
3374 nextToken();
3375 ts.append(parseType());
3376 }
3377 return ts.toList();
3378 }
3380 /** ClassBody = "{" {ClassBodyDeclaration} "}"
3381 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
3382 */
3383 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
3384 accept(LBRACE);
3385 if (token.pos <= endPosTable.errorEndPos) {
3386 // error recovery
3387 skip(false, true, false, false);
3388 if (token.kind == LBRACE)
3389 nextToken();
3390 }
3391 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
3392 while (token.kind != RBRACE && token.kind != EOF) {
3393 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
3394 if (token.pos <= endPosTable.errorEndPos) {
3395 // error recovery
3396 skip(false, true, true, false);
3397 }
3398 }
3399 accept(RBRACE);
3400 return defs.toList();
3401 }
3403 /** ClassBodyDeclaration =
3404 * ";"
3405 * | [STATIC] Block
3406 * | ModifiersOpt
3407 * ( Type Ident
3408 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
3409 * | VOID Ident VoidMethodDeclaratorRest
3410 * | TypeParameters [Annotations]
3411 * ( Type Ident MethodDeclaratorRest
3412 * | VOID Ident VoidMethodDeclaratorRest
3413 * )
3414 * | Ident ConstructorDeclaratorRest
3415 * | TypeParameters Ident ConstructorDeclaratorRest
3416 * | ClassOrInterfaceOrEnumDeclaration
3417 * )
3418 * InterfaceBodyDeclaration =
3419 * ";"
3420 * | ModifiersOpt
3421 * ( Type Ident
3422 * ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
3423 * | VOID Ident MethodDeclaratorRest
3424 * | TypeParameters [Annotations]
3425 * ( Type Ident MethodDeclaratorRest
3426 * | VOID Ident VoidMethodDeclaratorRest
3427 * )
3428 * | ClassOrInterfaceOrEnumDeclaration
3429 * )
3430 *
3431 */
3432 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
3433 if (token.kind == SEMI) {
3434 nextToken();
3435 return List.<JCTree>nil();
3436 } else {
3437 Comment dc = token.comment(CommentStyle.JAVADOC);
3438 int pos = token.pos;
3439 JCModifiers mods = modifiersOpt();
3440 if (token.kind == CLASS ||
3441 token.kind == INTERFACE ||
3442 allowEnums && token.kind == ENUM) {
3443 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
3444 } else if (token.kind == LBRACE && !isInterface &&
3445 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
3446 mods.annotations.isEmpty()) {
3447 return List.<JCTree>of(block(pos, mods.flags));
3448 } else {
3449 pos = token.pos;
3450 List<JCTypeParameter> typarams = typeParametersOpt();
3451 // if there are type parameters but no modifiers, save the start
3452 // position of the method in the modifiers.
3453 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
3454 mods.pos = pos;
3455 storeEnd(mods, pos);
3456 }
3457 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
3459 if (annosAfterParams.nonEmpty()) {
3460 checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
3461 mods.annotations = mods.annotations.appendList(annosAfterParams);
3462 if (mods.pos == Position.NOPOS)
3463 mods.pos = mods.annotations.head.pos;
3464 }
3466 Token tk = token;
3467 pos = token.pos;
3468 JCExpression type;
3469 boolean isVoid = token.kind == VOID;
3470 if (isVoid) {
3471 type = to(F.at(pos).TypeIdent(TypeTag.VOID));
3472 nextToken();
3473 } else {
3474 // method returns types are un-annotated types
3475 type = unannotatedType();
3476 }
3477 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
3478 if (isInterface || tk.name() != className)
3479 error(pos, "invalid.meth.decl.ret.type.req");
3480 else if (annosAfterParams.nonEmpty())
3481 illegal(annosAfterParams.head.pos);
3482 return List.of(methodDeclaratorRest(
3483 pos, mods, null, names.init, typarams,
3484 isInterface, true, dc));
3485 } else {
3486 pos = token.pos;
3487 Name name = ident();
3488 if (token.kind == LPAREN) {
3489 return List.of(methodDeclaratorRest(
3490 pos, mods, type, name, typarams,
3491 isInterface, isVoid, dc));
3492 } else if (!isVoid && typarams.isEmpty()) {
3493 List<JCTree> defs =
3494 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
3495 new ListBuffer<JCTree>()).toList();
3496 storeEnd(defs.last(), token.endPos);
3497 accept(SEMI);
3498 return defs;
3499 } else {
3500 pos = token.pos;
3501 List<JCTree> err = isVoid
3502 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
3503 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
3504 : null;
3505 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
3506 }
3507 }
3508 }
3509 }
3510 }
3512 /** MethodDeclaratorRest =
3513 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
3514 * VoidMethodDeclaratorRest =
3515 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
3516 * ConstructorDeclaratorRest =
3517 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
3518 */
3519 protected JCTree methodDeclaratorRest(int pos,
3520 JCModifiers mods,
3521 JCExpression type,
3522 Name name,
3523 List<JCTypeParameter> typarams,
3524 boolean isInterface, boolean isVoid,
3525 Comment dc) {
3526 if (isInterface && (mods.flags & Flags.STATIC) != 0) {
3527 checkStaticInterfaceMethods();
3528 }
3529 JCVariableDecl prevReceiverParam = this.receiverParam;
3530 try {
3531 this.receiverParam = null;
3532 // Parsing formalParameters sets the receiverParam, if present
3533 List<JCVariableDecl> params = formalParameters();
3534 if (!isVoid) type = bracketsOpt(type);
3535 List<JCExpression> thrown = List.nil();
3536 if (token.kind == THROWS) {
3537 nextToken();
3538 thrown = qualidentList();
3539 }
3540 JCBlock body = null;
3541 JCExpression defaultValue;
3542 if (token.kind == LBRACE) {
3543 body = block();
3544 defaultValue = null;
3545 } else {
3546 if (token.kind == DEFAULT) {
3547 accept(DEFAULT);
3548 defaultValue = annotationValue();
3549 } else {
3550 defaultValue = null;
3551 }
3552 accept(SEMI);
3553 if (token.pos <= endPosTable.errorEndPos) {
3554 // error recovery
3555 skip(false, true, false, false);
3556 if (token.kind == LBRACE) {
3557 body = block();
3558 }
3559 }
3560 }
3562 JCMethodDecl result =
3563 toP(F.at(pos).MethodDef(mods, name, type, typarams,
3564 receiverParam, params, thrown,
3565 body, defaultValue));
3566 attach(result, dc);
3567 return result;
3568 } finally {
3569 this.receiverParam = prevReceiverParam;
3570 }
3571 }
3573 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
3574 */
3575 List<JCExpression> qualidentList() {
3576 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
3578 List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
3579 JCExpression qi = qualident(true);
3580 if (!typeAnnos.isEmpty()) {
3581 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
3582 ts.append(at);
3583 } else {
3584 ts.append(qi);
3585 }
3586 while (token.kind == COMMA) {
3587 nextToken();
3589 typeAnnos = typeAnnotationsOpt();
3590 qi = qualident(true);
3591 if (!typeAnnos.isEmpty()) {
3592 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
3593 ts.append(at);
3594 } else {
3595 ts.append(qi);
3596 }
3597 }
3598 return ts.toList();
3599 }
3601 /**
3602 * {@literal
3603 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
3604 * }
3605 */
3606 List<JCTypeParameter> typeParametersOpt() {
3607 if (token.kind == LT) {
3608 checkGenerics();
3609 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
3610 nextToken();
3611 typarams.append(typeParameter());
3612 while (token.kind == COMMA) {
3613 nextToken();
3614 typarams.append(typeParameter());
3615 }
3616 accept(GT);
3617 return typarams.toList();
3618 } else {
3619 return List.nil();
3620 }
3621 }
3623 /**
3624 * {@literal
3625 * TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
3626 * TypeParameterBound = EXTENDS Type {"&" Type}
3627 * TypeVariable = Ident
3628 * }
3629 */
3630 JCTypeParameter typeParameter() {
3631 int pos = token.pos;
3632 List<JCAnnotation> annos = typeAnnotationsOpt();
3633 Name name = ident();
3634 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
3635 if (token.kind == EXTENDS) {
3636 nextToken();
3637 bounds.append(parseType());
3638 while (token.kind == AMP) {
3639 nextToken();
3640 bounds.append(parseType());
3641 }
3642 }
3643 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
3644 }
3646 /** FormalParameters = "(" [ FormalParameterList ] ")"
3647 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
3648 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
3649 */
3650 List<JCVariableDecl> formalParameters() {
3651 return formalParameters(false);
3652 }
3653 List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
3654 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3655 JCVariableDecl lastParam;
3656 accept(LPAREN);
3657 if (token.kind != RPAREN) {
3658 this.allowThisIdent = true;
3659 lastParam = formalParameter(lambdaParameters);
3660 if (lastParam.nameexpr != null) {
3661 this.receiverParam = lastParam;
3662 } else {
3663 params.append(lastParam);
3664 }
3665 this.allowThisIdent = false;
3666 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
3667 nextToken();
3668 params.append(lastParam = formalParameter(lambdaParameters));
3669 }
3670 }
3671 accept(RPAREN);
3672 return params.toList();
3673 }
3675 List<JCVariableDecl> implicitParameters(boolean hasParens) {
3676 if (hasParens) {
3677 accept(LPAREN);
3678 }
3679 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3680 if (token.kind != RPAREN && token.kind != ARROW) {
3681 params.append(implicitParameter());
3682 while (token.kind == COMMA) {
3683 nextToken();
3684 params.append(implicitParameter());
3685 }
3686 }
3687 if (hasParens) {
3688 accept(RPAREN);
3689 }
3690 return params.toList();
3691 }
3693 JCModifiers optFinal(long flags) {
3694 JCModifiers mods = modifiersOpt();
3695 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
3696 mods.flags |= flags;
3697 return mods;
3698 }
3700 /**
3701 * Inserts the annotations (and possibly a new array level)
3702 * to the left-most type in an array or nested type.
3703 *
3704 * When parsing a type like {@code @B Outer.Inner @A []}, the
3705 * {@code @A} annotation should target the array itself, while
3706 * {@code @B} targets the nested type {@code Outer}.
3707 *
3708 * Currently the parser parses the annotation first, then
3709 * the array, and then inserts the annotation to the left-most
3710 * nested type.
3711 *
3712 * When {@code createNewLevel} is true, then a new array
3713 * level is inserted as the most inner type, and have the
3714 * annotations target it. This is useful in the case of
3715 * varargs, e.g. {@code String @A [] @B ...}, as the parser
3716 * first parses the type {@code String @A []} then inserts
3717 * a new array level with {@code @B} annotation.
3718 */
3719 private JCExpression insertAnnotationsToMostInner(
3720 JCExpression type, List<JCAnnotation> annos,
3721 boolean createNewLevel) {
3722 int origEndPos = getEndPos(type);
3723 JCExpression mostInnerType = type;
3724 JCArrayTypeTree mostInnerArrayType = null;
3725 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
3726 mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
3727 mostInnerType = mostInnerArrayType.elemtype;
3728 }
3730 if (createNewLevel) {
3731 mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
3732 }
3734 JCExpression mostInnerTypeToReturn = mostInnerType;
3735 if (annos.nonEmpty()) {
3736 JCExpression lastToModify = mostInnerType;
3738 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
3739 TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
3740 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
3741 lastToModify = mostInnerType;
3742 mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
3743 }
3744 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
3745 lastToModify = mostInnerType;
3746 mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
3747 }
3748 }
3750 mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
3752 if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
3753 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
3754 } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
3755 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
3756 } else {
3757 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
3758 mostInnerTypeToReturn = mostInnerType;
3759 }
3760 }
3762 if (mostInnerArrayType == null) {
3763 return mostInnerTypeToReturn;
3764 } else {
3765 mostInnerArrayType.elemtype = mostInnerTypeToReturn;
3766 storeEnd(type, origEndPos);
3767 return type;
3768 }
3769 }
3771 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
3772 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
3773 */
3774 protected JCVariableDecl formalParameter() {
3775 return formalParameter(false);
3776 }
3777 protected JCVariableDecl formalParameter(boolean lambdaParameter) {
3778 JCModifiers mods = optFinal(Flags.PARAMETER);
3779 // need to distinguish between vararg annos and array annos
3780 // look at typeAnnotationsPushedBack comment
3781 this.permitTypeAnnotationsPushBack = true;
3782 JCExpression type = parseType();
3783 this.permitTypeAnnotationsPushBack = false;
3785 if (token.kind == ELLIPSIS) {
3786 List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
3787 typeAnnotationsPushedBack = List.nil();
3788 checkVarargs();
3789 mods.flags |= Flags.VARARGS;
3790 // insert var arg type annotations
3791 type = insertAnnotationsToMostInner(type, varargsAnnos, true);
3792 nextToken();
3793 } else {
3794 // if not a var arg, then typeAnnotationsPushedBack should be null
3795 if (typeAnnotationsPushedBack.nonEmpty()) {
3796 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
3797 "illegal.start.of.type");
3798 }
3799 typeAnnotationsPushedBack = List.nil();
3800 }
3801 return variableDeclaratorId(mods, type, lambdaParameter);
3802 }
3804 protected JCVariableDecl implicitParameter() {
3805 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
3806 return variableDeclaratorId(mods, null, true);
3807 }
3809 /* ---------- auxiliary methods -------------- */
3811 void error(int pos, String key, Object ... args) {
3812 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3813 }
3815 void error(DiagnosticPosition pos, String key, Object ... args) {
3816 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3817 }
3819 void warning(int pos, String key, Object ... args) {
3820 log.warning(pos, key, args);
3821 }
3823 /** Check that given tree is a legal expression statement.
3824 */
3825 protected JCExpression checkExprStat(JCExpression t) {
3826 if (!TreeInfo.isExpressionStatement(t)) {
3827 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
3828 error(ret, "not.stmt");
3829 return ret;
3830 } else {
3831 return t;
3832 }
3833 }
3835 /** Return precedence of operator represented by token,
3836 * -1 if token is not a binary operator. @see TreeInfo.opPrec
3837 */
3838 static int prec(TokenKind token) {
3839 JCTree.Tag oc = optag(token);
3840 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
3841 }
3843 /**
3844 * Return the lesser of two positions, making allowance for either one
3845 * being unset.
3846 */
3847 static int earlier(int pos1, int pos2) {
3848 if (pos1 == Position.NOPOS)
3849 return pos2;
3850 if (pos2 == Position.NOPOS)
3851 return pos1;
3852 return (pos1 < pos2 ? pos1 : pos2);
3853 }
3855 /** Return operation tag of binary operator represented by token,
3856 * No_TAG if token is not a binary operator.
3857 */
3858 static JCTree.Tag optag(TokenKind token) {
3859 switch (token) {
3860 case BARBAR:
3861 return OR;
3862 case AMPAMP:
3863 return AND;
3864 case BAR:
3865 return BITOR;
3866 case BAREQ:
3867 return BITOR_ASG;
3868 case CARET:
3869 return BITXOR;
3870 case CARETEQ:
3871 return BITXOR_ASG;
3872 case AMP:
3873 return BITAND;
3874 case AMPEQ:
3875 return BITAND_ASG;
3876 case EQEQ:
3877 return JCTree.Tag.EQ;
3878 case BANGEQ:
3879 return NE;
3880 case LT:
3881 return JCTree.Tag.LT;
3882 case GT:
3883 return JCTree.Tag.GT;
3884 case LTEQ:
3885 return LE;
3886 case GTEQ:
3887 return GE;
3888 case LTLT:
3889 return SL;
3890 case LTLTEQ:
3891 return SL_ASG;
3892 case GTGT:
3893 return SR;
3894 case GTGTEQ:
3895 return SR_ASG;
3896 case GTGTGT:
3897 return USR;
3898 case GTGTGTEQ:
3899 return USR_ASG;
3900 case PLUS:
3901 return JCTree.Tag.PLUS;
3902 case PLUSEQ:
3903 return PLUS_ASG;
3904 case SUB:
3905 return MINUS;
3906 case SUBEQ:
3907 return MINUS_ASG;
3908 case STAR:
3909 return MUL;
3910 case STAREQ:
3911 return MUL_ASG;
3912 case SLASH:
3913 return DIV;
3914 case SLASHEQ:
3915 return DIV_ASG;
3916 case PERCENT:
3917 return MOD;
3918 case PERCENTEQ:
3919 return MOD_ASG;
3920 case INSTANCEOF:
3921 return TYPETEST;
3922 default:
3923 return NO_TAG;
3924 }
3925 }
3927 /** Return operation tag of unary operator represented by token,
3928 * No_TAG if token is not a binary operator.
3929 */
3930 static JCTree.Tag unoptag(TokenKind token) {
3931 switch (token) {
3932 case PLUS:
3933 return POS;
3934 case SUB:
3935 return NEG;
3936 case BANG:
3937 return NOT;
3938 case TILDE:
3939 return COMPL;
3940 case PLUSPLUS:
3941 return PREINC;
3942 case SUBSUB:
3943 return PREDEC;
3944 default:
3945 return NO_TAG;
3946 }
3947 }
3949 /** Return type tag of basic type represented by token,
3950 * NONE if token is not a basic type identifier.
3951 */
3952 static TypeTag typetag(TokenKind token) {
3953 switch (token) {
3954 case BYTE:
3955 return TypeTag.BYTE;
3956 case CHAR:
3957 return TypeTag.CHAR;
3958 case SHORT:
3959 return TypeTag.SHORT;
3960 case INT:
3961 return TypeTag.INT;
3962 case LONG:
3963 return TypeTag.LONG;
3964 case FLOAT:
3965 return TypeTag.FLOAT;
3966 case DOUBLE:
3967 return TypeTag.DOUBLE;
3968 case BOOLEAN:
3969 return TypeTag.BOOLEAN;
3970 default:
3971 return TypeTag.NONE;
3972 }
3973 }
3975 void checkGenerics() {
3976 if (!allowGenerics) {
3977 error(token.pos, "generics.not.supported.in.source", source.name);
3978 allowGenerics = true;
3979 }
3980 }
3981 void checkVarargs() {
3982 if (!allowVarargs) {
3983 error(token.pos, "varargs.not.supported.in.source", source.name);
3984 allowVarargs = true;
3985 }
3986 }
3987 void checkForeach() {
3988 if (!allowForeach) {
3989 error(token.pos, "foreach.not.supported.in.source", source.name);
3990 allowForeach = true;
3991 }
3992 }
3993 void checkStaticImports() {
3994 if (!allowStaticImport) {
3995 error(token.pos, "static.import.not.supported.in.source", source.name);
3996 allowStaticImport = true;
3997 }
3998 }
3999 void checkAnnotations() {
4000 if (!allowAnnotations) {
4001 error(token.pos, "annotations.not.supported.in.source", source.name);
4002 allowAnnotations = true;
4003 }
4004 }
4005 void checkDiamond() {
4006 if (!allowDiamond) {
4007 error(token.pos, "diamond.not.supported.in.source", source.name);
4008 allowDiamond = true;
4009 }
4010 }
4011 void checkMulticatch() {
4012 if (!allowMulticatch) {
4013 error(token.pos, "multicatch.not.supported.in.source", source.name);
4014 allowMulticatch = true;
4015 }
4016 }
4017 void checkTryWithResources() {
4018 if (!allowTWR) {
4019 error(token.pos, "try.with.resources.not.supported.in.source", source.name);
4020 allowTWR = true;
4021 }
4022 }
4023 void checkLambda() {
4024 if (!allowLambda) {
4025 log.error(token.pos, "lambda.not.supported.in.source", source.name);
4026 allowLambda = true;
4027 }
4028 }
4029 void checkMethodReferences() {
4030 if (!allowMethodReferences) {
4031 log.error(token.pos, "method.references.not.supported.in.source", source.name);
4032 allowMethodReferences = true;
4033 }
4034 }
4035 void checkDefaultMethods() {
4036 if (!allowDefaultMethods) {
4037 log.error(token.pos, "default.methods.not.supported.in.source", source.name);
4038 allowDefaultMethods = true;
4039 }
4040 }
4041 void checkIntersectionTypesInCast() {
4042 if (!allowIntersectionTypesInCast) {
4043 log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
4044 allowIntersectionTypesInCast = true;
4045 }
4046 }
4047 void checkStaticInterfaceMethods() {
4048 if (!allowStaticInterfaceMethods) {
4049 log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name);
4050 allowStaticInterfaceMethods = true;
4051 }
4052 }
4053 void checkTypeAnnotations() {
4054 if (!allowTypeAnnotations) {
4055 log.error(token.pos, "type.annotations.not.supported.in.source", source.name);
4056 allowTypeAnnotations = true;
4057 }
4058 }
4059 void checkAnnotationsAfterTypeParams(int pos) {
4060 if (!allowAnnotationsAfterTypeParams) {
4061 log.error(pos, "annotations.after.type.params.not.supported.in.source", source.name);
4062 allowAnnotationsAfterTypeParams = true;
4063 }
4064 }
4066 /*
4067 * a functional source tree and end position mappings
4068 */
4069 protected static class SimpleEndPosTable extends AbstractEndPosTable {
4071 private final IntHashTable endPosMap;
4073 SimpleEndPosTable(JavacParser parser) {
4074 super(parser);
4075 endPosMap = new IntHashTable();
4076 }
4078 public void storeEnd(JCTree tree, int endpos) {
4079 endPosMap.putAtIndex(tree, errorEndPos > endpos ? errorEndPos : endpos,
4080 endPosMap.lookup(tree));
4081 }
4083 protected <T extends JCTree> T to(T t) {
4084 storeEnd(t, parser.token.endPos);
4085 return t;
4086 }
4088 protected <T extends JCTree> T toP(T t) {
4089 storeEnd(t, parser.S.prevToken().endPos);
4090 return t;
4091 }
4093 public int getEndPos(JCTree tree) {
4094 int value = endPosMap.getFromIndex(endPosMap.lookup(tree));
4095 // As long as Position.NOPOS==-1, this just returns value.
4096 return (value == -1) ? Position.NOPOS : value;
4097 }
4099 public int replaceTree(JCTree oldTree, JCTree newTree) {
4100 int pos = endPosMap.remove(oldTree);
4101 if (pos != -1) {
4102 storeEnd(newTree, pos);
4103 return pos;
4104 }
4105 return Position.NOPOS;
4106 }
4107 }
4109 /*
4110 * a default skeletal implementation without any mapping overhead.
4111 */
4112 protected static class EmptyEndPosTable extends AbstractEndPosTable {
4114 EmptyEndPosTable(JavacParser parser) {
4115 super(parser);
4116 }
4118 public void storeEnd(JCTree tree, int endpos) { /* empty */ }
4120 protected <T extends JCTree> T to(T t) {
4121 return t;
4122 }
4124 protected <T extends JCTree> T toP(T t) {
4125 return t;
4126 }
4128 public int getEndPos(JCTree tree) {
4129 return Position.NOPOS;
4130 }
4132 public int replaceTree(JCTree oldTree, JCTree newTree) {
4133 return Position.NOPOS;
4134 }
4136 }
4138 protected static abstract class AbstractEndPosTable implements EndPosTable {
4139 /**
4140 * The current parser.
4141 */
4142 protected JavacParser parser;
4144 /**
4145 * Store the last error position.
4146 */
4147 protected int errorEndPos;
4149 public AbstractEndPosTable(JavacParser parser) {
4150 this.parser = parser;
4151 }
4153 /**
4154 * Store current token's ending position for a tree, the value of which
4155 * will be the greater of last error position and the ending position of
4156 * the current token.
4157 * @param t The tree.
4158 */
4159 protected abstract <T extends JCTree> T to(T t);
4161 /**
4162 * Store current token's ending position for a tree, the value of which
4163 * will be the greater of last error position and the ending position of
4164 * the previous token.
4165 * @param t The tree.
4166 */
4167 protected abstract <T extends JCTree> T toP(T t);
4169 /**
4170 * Set the error position during the parsing phases, the value of which
4171 * will be set only if it is greater than the last stored error position.
4172 * @param errPos The error position
4173 */
4174 protected void setErrorEndPos(int errPos) {
4175 if (errPos > errorEndPos) {
4176 errorEndPos = errPos;
4177 }
4178 }
4180 protected void setParser(JavacParser parser) {
4181 this.parser = parser;
4182 }
4183 }
4184 }