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