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