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