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