Mon, 26 Jul 2010 14:25:56 -0700
6957438: improve code for generating warning messages containing option names
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 1999, 2009, 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.tools.javac.tree.*;
31 import com.sun.tools.javac.code.*;
32 import com.sun.tools.javac.util.*;
33 import com.sun.tools.javac.util.List;
34 import static com.sun.tools.javac.util.ListBuffer.lb;
36 import com.sun.tools.javac.tree.JCTree.*;
38 import static com.sun.tools.javac.parser.Token.*;
40 /** The parser maps a token sequence into an abstract syntax
41 * tree. It operates by recursive descent, with code derived
42 * systematically from an LL(1) grammar. For efficiency reasons, an
43 * operator precedence scheme is used for parsing binary operation
44 * expressions.
45 *
46 * <p><b>This is NOT part of any supported API.
47 * If you write code that depends on this, you do so at your own risk.
48 * This code and its internal interfaces are subject to change or
49 * deletion without notice.</b>
50 */
51 public class JavacParser implements Parser {
53 /** The number of precedence levels of infix operators.
54 */
55 private static final int infixPrecedenceLevels = 10;
57 /** The scanner used for lexical analysis.
58 */
59 private Lexer S;
61 /** The factory to be used for abstract syntax tree construction.
62 */
63 protected TreeMaker F;
65 /** The log to be used for error diagnostics.
66 */
67 private Log log;
69 /** The keyword table. */
70 private Keywords keywords;
72 /** The Source language setting. */
73 private Source source;
75 /** The name table. */
76 private Names names;
78 // Because of javac's limited lookahead, some contexts are ambiguous in
79 // the presence of type annotations even though they are not ambiguous
80 // in the absence of type annotations. Consider this code:
81 // void m(String [] m) { }
82 // void m(String ... m) { }
83 // After parsing "String", javac calls bracketsOpt which immediately
84 // returns if the next character is not '['. Similarly, javac can see
85 // if the next token is ... and in that case parse an ellipsis. But in
86 // the presence of type annotations:
87 // void m(String @A [] m) { }
88 // void m(String @A ... m) { }
89 // no finite lookahead is enough to determine whether to read array
90 // levels or an ellipsis. Furthermore, if you call bracketsOpt, then
91 // bracketsOpt first reads all the leading annotations and only then
92 // discovers that it needs to fail. bracketsOpt needs a way to push
93 // back the extra annotations that it read. (But, bracketsOpt should
94 // not *always* be allowed to push back extra annotations that it finds
95 // -- in most contexts, any such extra annotation is an error.
96 // Another similar case occurs with arrays and receiver annotations:
97 // String b() @Array [] @Receiver { }
98 // String b() @Receiver { }
99 //
100 // The following two variables permit type annotations that have
101 // already been read to be stored for later use. Alternate
102 // implementations are possible but would cause much larger changes to
103 // the parser.
104 /** Type annotations that have already been read but have not yet been used. **/
105 private List<JCTypeAnnotation> typeAnnotationsPushedBack = null;
106 /**
107 * If the parser notices extra annotations, then it either immediately
108 * issues an error (if this variable is false) or places the extra
109 * annotations in variable typeAnnotationsPushedBack (if this variable
110 * is true).
111 */
112 private boolean permitTypeAnnotationsPushBack = false;
114 /** Construct a parser from a given scanner, tree factory and log.
115 */
116 protected JavacParser(ParserFactory fac,
117 Lexer S,
118 boolean keepDocComments,
119 boolean keepLineMap) {
120 this.S = S;
121 S.nextToken(); // prime the pump
122 this.F = fac.F;
123 this.log = fac.log;
124 this.names = fac.names;
125 this.keywords = fac.keywords;
126 this.source = fac.source;
127 this.allowGenerics = source.allowGenerics();
128 this.allowVarargs = source.allowVarargs();
129 this.allowAsserts = source.allowAsserts();
130 this.allowEnums = source.allowEnums();
131 this.allowForeach = source.allowForeach();
132 this.allowStaticImport = source.allowStaticImport();
133 this.allowAnnotations = source.allowAnnotations();
134 this.allowTWR = source.allowTryWithResources();
135 this.allowDiamond = source.allowDiamond();
136 this.allowMulticatch = source.allowMulticatch();
137 this.allowTypeAnnotations = source.allowTypeAnnotations();
138 this.keepDocComments = keepDocComments;
139 if (keepDocComments)
140 docComments = new HashMap<JCTree,String>();
141 this.keepLineMap = keepLineMap;
142 this.errorTree = F.Erroneous();
143 this.debugJSR308 = fac.options.get("TA:parser") != null;
144 }
146 /** Switch: debug output for type-annotations operations
147 */
148 boolean debugJSR308;
150 /** Switch: Should generics be recognized?
151 */
152 boolean allowGenerics;
154 /** Switch: Should diamond operator be recognized?
155 */
156 boolean allowDiamond;
158 /** Switch: Should multicatch clause be accepted?
159 */
160 boolean allowMulticatch;
162 /** Switch: Should varargs be recognized?
163 */
164 boolean allowVarargs;
166 /** Switch: should we recognize assert statements, or just give a warning?
167 */
168 boolean allowAsserts;
170 /** Switch: should we recognize enums, or just give a warning?
171 */
172 boolean allowEnums;
174 /** Switch: should we recognize foreach?
175 */
176 boolean allowForeach;
178 /** Switch: should we recognize foreach?
179 */
180 boolean allowStaticImport;
182 /** Switch: should we recognize annotations?
183 */
184 boolean allowAnnotations;
186 /** Switch: should we recognize type annotations?
187 */
188 boolean allowTypeAnnotations;
190 /** Switch: should we recognize automatic resource management?
191 */
192 boolean allowTWR;
194 /** Switch: should we keep docComments?
195 */
196 boolean keepDocComments;
198 /** Switch: should we keep line table?
199 */
200 boolean keepLineMap;
202 /** When terms are parsed, the mode determines which is expected:
203 * mode = EXPR : an expression
204 * mode = TYPE : a type
205 * mode = NOPARAMS : no parameters allowed for type
206 * mode = TYPEARG : type argument
207 */
208 static final int EXPR = 0x1;
209 static final int TYPE = 0x2;
210 static final int NOPARAMS = 0x4;
211 static final int TYPEARG = 0x8;
212 static final int DIAMOND = 0x10;
214 /** The current mode.
215 */
216 private int mode = 0;
218 /** The mode of the term that was parsed last.
219 */
220 private int lastmode = 0;
222 /* ---------- error recovery -------------- */
224 private JCErroneous errorTree;
226 /** Skip forward until a suitable stop token is found.
227 */
228 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
229 while (true) {
230 switch (S.token()) {
231 case SEMI:
232 S.nextToken();
233 return;
234 case PUBLIC:
235 case FINAL:
236 case ABSTRACT:
237 case MONKEYS_AT:
238 case EOF:
239 case CLASS:
240 case INTERFACE:
241 case ENUM:
242 return;
243 case IMPORT:
244 if (stopAtImport)
245 return;
246 break;
247 case LBRACE:
248 case RBRACE:
249 case PRIVATE:
250 case PROTECTED:
251 case STATIC:
252 case TRANSIENT:
253 case NATIVE:
254 case VOLATILE:
255 case SYNCHRONIZED:
256 case STRICTFP:
257 case LT:
258 case BYTE:
259 case SHORT:
260 case CHAR:
261 case INT:
262 case LONG:
263 case FLOAT:
264 case DOUBLE:
265 case BOOLEAN:
266 case VOID:
267 if (stopAtMemberDecl)
268 return;
269 break;
270 case IDENTIFIER:
271 if (stopAtIdentifier)
272 return;
273 break;
274 case CASE:
275 case DEFAULT:
276 case IF:
277 case FOR:
278 case WHILE:
279 case DO:
280 case TRY:
281 case SWITCH:
282 case RETURN:
283 case THROW:
284 case BREAK:
285 case CONTINUE:
286 case ELSE:
287 case FINALLY:
288 case CATCH:
289 if (stopAtStatement)
290 return;
291 break;
292 }
293 S.nextToken();
294 }
295 }
297 private JCErroneous syntaxError(int pos, String key, Token... args) {
298 return syntaxError(pos, null, key, args);
299 }
301 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
302 setErrorEndPos(pos);
303 reportSyntaxError(pos, key, (Object[])args);
304 return toP(F.at(pos).Erroneous(errs));
305 }
307 private int errorPos = Position.NOPOS;
308 /**
309 * Report a syntax error at given position using the given
310 * argument unless one was already reported at the same position.
311 */
312 private void reportSyntaxError(int pos, String key, Object... args) {
313 if (pos > S.errPos() || pos == Position.NOPOS) {
314 if (S.token() == EOF)
315 log.error(pos, "premature.eof");
316 else
317 log.error(pos, key, args);
318 }
319 S.errPos(pos);
320 if (S.pos() == errorPos)
321 S.nextToken(); // guarantee progress
322 errorPos = S.pos();
323 }
326 /** Generate a syntax error at current position unless one was already
327 * reported at the same position.
328 */
329 private JCErroneous syntaxError(String key) {
330 return syntaxError(S.pos(), key);
331 }
333 /** Generate a syntax error at current position unless one was
334 * already reported at the same position.
335 */
336 private JCErroneous syntaxError(String key, Token arg) {
337 return syntaxError(S.pos(), key, arg);
338 }
340 /** If next input token matches given token, skip it, otherwise report
341 * an error.
342 */
343 public void accept(Token token) {
344 if (S.token() == token) {
345 S.nextToken();
346 } else {
347 setErrorEndPos(S.pos());
348 reportSyntaxError(S.prevEndPos(), "expected", token);
349 }
350 }
352 /** Report an illegal start of expression/type error at given position.
353 */
354 JCExpression illegal(int pos) {
355 setErrorEndPos(S.pos());
356 if ((mode & EXPR) != 0)
357 return syntaxError(pos, "illegal.start.of.expr");
358 else
359 return syntaxError(pos, "illegal.start.of.type");
361 }
363 /** Report an illegal start of expression/type error at current position.
364 */
365 JCExpression illegal() {
366 return illegal(S.pos());
367 }
369 /** Diagnose a modifier flag from the set, if any. */
370 void checkNoMods(long mods) {
371 if (mods != 0) {
372 long lowestMod = mods & -mods;
373 log.error(S.pos(), "mod.not.allowed.here",
374 Flags.asFlagSet(lowestMod));
375 }
376 }
378 /* ---------- doc comments --------- */
380 /** A hashtable to store all documentation comments
381 * indexed by the tree nodes they refer to.
382 * defined only if option flag keepDocComment is set.
383 */
384 Map<JCTree, String> docComments;
386 /** Make an entry into docComments hashtable,
387 * provided flag keepDocComments is set and given doc comment is non-null.
388 * @param tree The tree to be used as index in the hashtable
389 * @param dc The doc comment to associate with the tree, or null.
390 */
391 void attach(JCTree tree, String dc) {
392 if (keepDocComments && dc != null) {
393 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
394 docComments.put(tree, dc);
395 }
396 }
398 /* -------- source positions ------- */
400 private int errorEndPos = -1;
402 private void setErrorEndPos(int errPos) {
403 if (errPos > errorEndPos)
404 errorEndPos = errPos;
405 }
407 protected int getErrorEndPos() {
408 return errorEndPos;
409 }
411 /**
412 * Store ending position for a tree.
413 * @param tree The tree.
414 * @param endpos The ending position to associate with the tree.
415 */
416 protected void storeEnd(JCTree tree, int endpos) {}
418 /**
419 * Store ending position for a tree. The ending position should
420 * be the ending position of the current token.
421 * @param t The tree.
422 */
423 protected <T extends JCTree> T to(T t) { return t; }
425 /**
426 * Store ending position for a tree. The ending position should
427 * be greater of the ending position of the previous token and errorEndPos.
428 * @param t The tree.
429 */
430 protected <T extends JCTree> T toP(T t) { return t; }
432 /** Get the start position for a tree node. The start position is
433 * defined to be the position of the first character of the first
434 * token of the node's source text.
435 * @param tree The tree node
436 */
437 public int getStartPos(JCTree tree) {
438 return TreeInfo.getStartPos(tree);
439 }
441 /**
442 * Get the end position for a tree node. The end position is
443 * defined to be the position of the last character of the last
444 * token of the node's source text. Returns Position.NOPOS if end
445 * positions are not generated or the position is otherwise not
446 * found.
447 * @param tree The tree node
448 */
449 public int getEndPos(JCTree tree) {
450 return Position.NOPOS;
451 }
455 /* ---------- parsing -------------- */
457 /**
458 * Ident = IDENTIFIER
459 */
460 Name ident() {
461 if (S.token() == IDENTIFIER) {
462 Name name = S.name();
463 S.nextToken();
464 return name;
465 } else if (S.token() == ASSERT) {
466 if (allowAsserts) {
467 log.error(S.pos(), "assert.as.identifier");
468 S.nextToken();
469 return names.error;
470 } else {
471 log.warning(S.pos(), "assert.as.identifier");
472 Name name = S.name();
473 S.nextToken();
474 return name;
475 }
476 } else if (S.token() == ENUM) {
477 if (allowEnums) {
478 log.error(S.pos(), "enum.as.identifier");
479 S.nextToken();
480 return names.error;
481 } else {
482 log.warning(S.pos(), "enum.as.identifier");
483 Name name = S.name();
484 S.nextToken();
485 return name;
486 }
487 } else {
488 accept(IDENTIFIER);
489 return names.error;
490 }
491 }
493 /**
494 * Qualident = Ident { DOT Ident }
495 */
496 public JCExpression qualident() {
497 JCExpression t = toP(F.at(S.pos()).Ident(ident()));
498 while (S.token() == DOT) {
499 int pos = S.pos();
500 S.nextToken();
501 t = toP(F.at(pos).Select(t, ident()));
502 }
503 return t;
504 }
506 /**
507 * Literal =
508 * INTLITERAL
509 * | LONGLITERAL
510 * | FLOATLITERAL
511 * | DOUBLELITERAL
512 * | CHARLITERAL
513 * | STRINGLITERAL
514 * | TRUE
515 * | FALSE
516 * | NULL
517 */
518 JCExpression literal(Name prefix) {
519 int pos = S.pos();
520 JCExpression t = errorTree;
521 switch (S.token()) {
522 case INTLITERAL:
523 try {
524 t = F.at(pos).Literal(
525 TypeTags.INT,
526 Convert.string2int(strval(prefix), S.radix()));
527 } catch (NumberFormatException ex) {
528 log.error(S.pos(), "int.number.too.large", strval(prefix));
529 }
530 break;
531 case LONGLITERAL:
532 try {
533 t = F.at(pos).Literal(
534 TypeTags.LONG,
535 new Long(Convert.string2long(strval(prefix), S.radix())));
536 } catch (NumberFormatException ex) {
537 log.error(S.pos(), "int.number.too.large", strval(prefix));
538 }
539 break;
540 case FLOATLITERAL: {
541 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
542 Float n;
543 try {
544 n = Float.valueOf(proper);
545 } catch (NumberFormatException ex) {
546 // error already repoted in scanner
547 n = Float.NaN;
548 }
549 if (n.floatValue() == 0.0f && !isZero(proper))
550 log.error(S.pos(), "fp.number.too.small");
551 else if (n.floatValue() == Float.POSITIVE_INFINITY)
552 log.error(S.pos(), "fp.number.too.large");
553 else
554 t = F.at(pos).Literal(TypeTags.FLOAT, n);
555 break;
556 }
557 case DOUBLELITERAL: {
558 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
559 Double n;
560 try {
561 n = Double.valueOf(proper);
562 } catch (NumberFormatException ex) {
563 // error already reported in scanner
564 n = Double.NaN;
565 }
566 if (n.doubleValue() == 0.0d && !isZero(proper))
567 log.error(S.pos(), "fp.number.too.small");
568 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
569 log.error(S.pos(), "fp.number.too.large");
570 else
571 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
572 break;
573 }
574 case CHARLITERAL:
575 t = F.at(pos).Literal(
576 TypeTags.CHAR,
577 S.stringVal().charAt(0) + 0);
578 break;
579 case STRINGLITERAL:
580 t = F.at(pos).Literal(
581 TypeTags.CLASS,
582 S.stringVal());
583 break;
584 case TRUE: case FALSE:
585 t = F.at(pos).Literal(
586 TypeTags.BOOLEAN,
587 (S.token() == TRUE ? 1 : 0));
588 break;
589 case NULL:
590 t = F.at(pos).Literal(
591 TypeTags.BOT,
592 null);
593 break;
594 default:
595 assert false;
596 }
597 if (t == errorTree)
598 t = F.at(pos).Erroneous();
599 storeEnd(t, S.endPos());
600 S.nextToken();
601 return t;
602 }
603 //where
604 boolean isZero(String s) {
605 char[] cs = s.toCharArray();
606 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
607 int i = ((base==16) ? 2 : 0);
608 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
609 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
610 }
612 String strval(Name prefix) {
613 String s = S.stringVal();
614 return prefix.isEmpty() ? s : prefix + s;
615 }
617 /** terms can be either expressions or types.
618 */
619 public JCExpression parseExpression() {
620 return term(EXPR);
621 }
623 /**
624 * parses (optional) type annotations followed by a type. If the
625 * annotations are present before the type and are not consumed during array
626 * parsing, this method returns a {@link JCAnnotatedType} consisting of
627 * these annotations and the underlying type. Otherwise, it returns the
628 * underlying type.
629 *
630 * <p>
631 *
632 * Note that this method sets {@code mode} to {@code TYPE} first, before
633 * parsing annotations.
634 */
635 public JCExpression parseType() {
636 List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
637 return parseType(annotations);
638 }
640 public JCExpression parseType(List<JCTypeAnnotation> annotations) {
641 JCExpression result = unannotatedType();
643 if (!annotations.isEmpty())
644 result = F.AnnotatedType(annotations, result);
646 return result;
647 }
649 public JCExpression unannotatedType() {
650 return term(TYPE);
651 }
653 JCExpression term(int newmode) {
654 int prevmode = mode;
655 mode = newmode;
656 JCExpression t = term();
657 lastmode = mode;
658 mode = prevmode;
659 return t;
660 }
662 /**
663 * Expression = Expression1 [ExpressionRest]
664 * ExpressionRest = [AssignmentOperator Expression1]
665 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
666 * "&=" | "|=" | "^=" |
667 * "%=" | "<<=" | ">>=" | ">>>="
668 * Type = Type1
669 * TypeNoParams = TypeNoParams1
670 * StatementExpression = Expression
671 * ConstantExpression = Expression
672 */
673 JCExpression term() {
674 JCExpression t = term1();
675 if ((mode & EXPR) != 0 &&
676 S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
677 return termRest(t);
678 else
679 return t;
680 }
682 JCExpression termRest(JCExpression t) {
683 switch (S.token()) {
684 case EQ: {
685 int pos = S.pos();
686 S.nextToken();
687 mode = EXPR;
688 JCExpression t1 = term();
689 return toP(F.at(pos).Assign(t, t1));
690 }
691 case PLUSEQ:
692 case SUBEQ:
693 case STAREQ:
694 case SLASHEQ:
695 case PERCENTEQ:
696 case AMPEQ:
697 case BAREQ:
698 case CARETEQ:
699 case LTLTEQ:
700 case GTGTEQ:
701 case GTGTGTEQ:
702 int pos = S.pos();
703 Token token = S.token();
704 S.nextToken();
705 mode = EXPR;
706 JCExpression t1 = term();
707 return F.at(pos).Assignop(optag(token), t, t1);
708 default:
709 return t;
710 }
711 }
713 /** Expression1 = Expression2 [Expression1Rest]
714 * Type1 = Type2
715 * TypeNoParams1 = TypeNoParams2
716 */
717 JCExpression term1() {
718 JCExpression t = term2();
719 if ((mode & EXPR) != 0 && S.token() == QUES) {
720 mode = EXPR;
721 return term1Rest(t);
722 } else {
723 return t;
724 }
725 }
727 /** Expression1Rest = ["?" Expression ":" Expression1]
728 */
729 JCExpression term1Rest(JCExpression t) {
730 if (S.token() == QUES) {
731 int pos = S.pos();
732 S.nextToken();
733 JCExpression t1 = term();
734 accept(COLON);
735 JCExpression t2 = term1();
736 return F.at(pos).Conditional(t, t1, t2);
737 } else {
738 return t;
739 }
740 }
742 /** Expression2 = Expression3 [Expression2Rest]
743 * Type2 = Type3
744 * TypeNoParams2 = TypeNoParams3
745 */
746 JCExpression term2() {
747 JCExpression t = term3();
748 if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
749 mode = EXPR;
750 return term2Rest(t, TreeInfo.orPrec);
751 } else {
752 return t;
753 }
754 }
756 /* Expression2Rest = {infixop Expression3}
757 * | Expression3 instanceof Type
758 * infixop = "||"
759 * | "&&"
760 * | "|"
761 * | "^"
762 * | "&"
763 * | "==" | "!="
764 * | "<" | ">" | "<=" | ">="
765 * | "<<" | ">>" | ">>>"
766 * | "+" | "-"
767 * | "*" | "/" | "%"
768 */
769 JCExpression term2Rest(JCExpression t, int minprec) {
770 List<JCExpression[]> savedOd = odStackSupply.elems;
771 JCExpression[] odStack = newOdStack();
772 List<Token[]> savedOp = opStackSupply.elems;
773 Token[] opStack = newOpStack();
774 List<int[]> savedPos = posStackSupply.elems;
775 int[] posStack = newPosStack();
776 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
777 int top = 0;
778 odStack[0] = t;
779 int startPos = S.pos();
780 Token topOp = ERROR;
781 int topOpPos = Position.NOPOS;
782 while (prec(S.token()) >= minprec) {
783 posStack[top] = topOpPos;
784 opStack[top] = topOp;
785 top++;
786 topOp = S.token();
787 topOpPos = S.pos();
788 S.nextToken();
789 odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
790 while (top > 0 && prec(topOp) >= prec(S.token())) {
791 odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
792 odStack[top]);
793 top--;
794 topOp = opStack[top];
795 topOpPos = posStack[top];
796 }
797 }
798 assert top == 0;
799 t = odStack[0];
801 if (t.getTag() == JCTree.PLUS) {
802 StringBuffer buf = foldStrings(t);
803 if (buf != null) {
804 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
805 }
806 }
808 odStackSupply.elems = savedOd; // optimization
809 opStackSupply.elems = savedOp; // optimization
810 posStackSupply.elems = savedPos; // optimization
811 return t;
812 }
813 //where
814 /** Construct a binary or type test node.
815 */
816 private JCExpression makeOp(int pos,
817 Token topOp,
818 JCExpression od1,
819 JCExpression od2)
820 {
821 if (topOp == INSTANCEOF) {
822 return F.at(pos).TypeTest(od1, od2);
823 } else {
824 return F.at(pos).Binary(optag(topOp), od1, od2);
825 }
826 }
827 /** If tree is a concatenation of string literals, replace it
828 * by a single literal representing the concatenated string.
829 */
830 protected StringBuffer foldStrings(JCTree tree) {
831 List<String> buf = List.nil();
832 while (true) {
833 if (tree.getTag() == JCTree.LITERAL) {
834 JCLiteral lit = (JCLiteral) tree;
835 if (lit.typetag == TypeTags.CLASS) {
836 StringBuffer sbuf =
837 new StringBuffer((String)lit.value);
838 while (buf.nonEmpty()) {
839 sbuf.append(buf.head);
840 buf = buf.tail;
841 }
842 return sbuf;
843 }
844 } else if (tree.getTag() == JCTree.PLUS) {
845 JCBinary op = (JCBinary)tree;
846 if (op.rhs.getTag() == JCTree.LITERAL) {
847 JCLiteral lit = (JCLiteral) op.rhs;
848 if (lit.typetag == TypeTags.CLASS) {
849 buf = buf.prepend((String) lit.value);
850 tree = op.lhs;
851 continue;
852 }
853 }
854 }
855 return null;
856 }
857 }
859 /** optimization: To save allocating a new operand/operator stack
860 * for every binary operation, we use supplys.
861 */
862 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
863 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
864 ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
866 private JCExpression[] newOdStack() {
867 if (odStackSupply.elems == odStackSupply.last)
868 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
869 JCExpression[] odStack = odStackSupply.elems.head;
870 odStackSupply.elems = odStackSupply.elems.tail;
871 return odStack;
872 }
874 private Token[] newOpStack() {
875 if (opStackSupply.elems == opStackSupply.last)
876 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
877 Token[] opStack = opStackSupply.elems.head;
878 opStackSupply.elems = opStackSupply.elems.tail;
879 return opStack;
880 }
882 private int[] newPosStack() {
883 if (posStackSupply.elems == posStackSupply.last)
884 posStackSupply.append(new int[infixPrecedenceLevels + 1]);
885 int[] posStack = posStackSupply.elems.head;
886 posStackSupply.elems = posStackSupply.elems.tail;
887 return posStack;
888 }
890 /** Expression3 = PrefixOp Expression3
891 * | "(" Expr | TypeNoParams ")" Expression3
892 * | Primary {Selector} {PostfixOp}
893 * Primary = "(" Expression ")"
894 * | Literal
895 * | [TypeArguments] THIS [Arguments]
896 * | [TypeArguments] SUPER SuperSuffix
897 * | NEW [TypeArguments] Creator
898 * | [Annotations] Ident { "." Ident }
899 * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
900 * | Arguments
901 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
902 * ]
903 * | BasicType BracketsOpt "." CLASS
904 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
905 * PostfixOp = "++" | "--"
906 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
907 * | BasicType
908 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
909 * Selector = "." [TypeArguments] Ident [Arguments]
910 * | "." THIS
911 * | "." [TypeArguments] SUPER SuperSuffix
912 * | "." NEW [TypeArguments] InnerCreator
913 * | "[" Expression "]"
914 * TypeSelector = "." Ident [TypeArguments]
915 * SuperSuffix = Arguments | "." Ident [Arguments]
916 */
917 protected JCExpression term3() {
918 int pos = S.pos();
919 JCExpression t;
920 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
921 switch (S.token()) {
922 case QUES:
923 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
924 mode = TYPE;
925 return typeArgument();
926 } else
927 return illegal();
928 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
929 if (typeArgs == null && (mode & EXPR) != 0) {
930 Token token = S.token();
931 S.nextToken();
932 mode = EXPR;
933 if (token == SUB &&
934 (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
935 S.radix() == 10) {
936 mode = EXPR;
937 t = literal(names.hyphen);
938 } else {
939 t = term3();
940 return F.at(pos).Unary(unoptag(token), t);
941 }
942 } else return illegal();
943 break;
944 case LPAREN:
945 if (typeArgs == null && (mode & EXPR) != 0) {
946 S.nextToken();
947 mode = EXPR | TYPE | NOPARAMS;
948 t = term3();
949 if ((mode & TYPE) != 0 && S.token() == LT) {
950 // Could be a cast to a parameterized type
951 int op = JCTree.LT;
952 int pos1 = S.pos();
953 S.nextToken();
954 mode &= (EXPR | TYPE);
955 mode |= TYPEARG;
956 JCExpression t1 = term3();
957 if ((mode & TYPE) != 0 &&
958 (S.token() == COMMA || S.token() == GT)) {
959 mode = TYPE;
960 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
961 args.append(t1);
962 while (S.token() == COMMA) {
963 S.nextToken();
964 args.append(typeArgument());
965 }
966 accept(GT);
967 t = toP(F.at(pos1).TypeApply(t, args.toList()));
968 checkGenerics();
969 while (S.token() == DOT) {
970 S.nextToken();
971 mode = TYPE;
972 t = toP(F.at(S.pos()).Select(t, ident()));
973 t = typeArgumentsOpt(t);
974 }
975 t = bracketsOpt(toP(t));
976 } else if ((mode & EXPR) != 0) {
977 mode = EXPR;
978 JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
979 t = F.at(pos1).Binary(op, t, e);
980 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
981 } else {
982 accept(GT);
983 }
984 }
985 else {
986 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
987 }
988 accept(RPAREN);
989 lastmode = mode;
990 mode = EXPR;
991 if ((lastmode & EXPR) == 0) {
992 JCExpression t1 = term3();
993 return F.at(pos).TypeCast(t, t1);
994 } else if ((lastmode & TYPE) != 0) {
995 switch (S.token()) {
996 /*case PLUSPLUS: case SUBSUB: */
997 case BANG: case TILDE:
998 case LPAREN: case THIS: case SUPER:
999 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
1000 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
1001 case TRUE: case FALSE: case NULL:
1002 case NEW: case IDENTIFIER: case ASSERT: case ENUM:
1003 case BYTE: case SHORT: case CHAR: case INT:
1004 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
1005 JCExpression t1 = term3();
1006 return F.at(pos).TypeCast(t, t1);
1007 }
1008 }
1009 } else return illegal();
1010 t = toP(F.at(pos).Parens(t));
1011 break;
1012 case THIS:
1013 if ((mode & EXPR) != 0) {
1014 mode = EXPR;
1015 t = to(F.at(pos).Ident(names._this));
1016 S.nextToken();
1017 if (typeArgs == null)
1018 t = argumentsOpt(null, t);
1019 else
1020 t = arguments(typeArgs, t);
1021 typeArgs = null;
1022 } else return illegal();
1023 break;
1024 case SUPER:
1025 if ((mode & EXPR) != 0) {
1026 mode = EXPR;
1027 t = to(F.at(pos).Ident(names._super));
1028 t = superSuffix(typeArgs, t);
1029 typeArgs = null;
1030 } else return illegal();
1031 break;
1032 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1033 case CHARLITERAL: case STRINGLITERAL:
1034 case TRUE: case FALSE: case NULL:
1035 if (typeArgs == null && (mode & EXPR) != 0) {
1036 mode = EXPR;
1037 t = literal(names.empty);
1038 } else return illegal();
1039 break;
1040 case NEW:
1041 if (typeArgs != null) return illegal();
1042 if ((mode & EXPR) != 0) {
1043 mode = EXPR;
1044 S.nextToken();
1045 if (S.token() == LT) typeArgs = typeArguments();
1046 t = creator(pos, typeArgs);
1047 typeArgs = null;
1048 } else return illegal();
1049 break;
1050 case MONKEYS_AT:
1052 // only annotated targetting class literals or cast types are valid
1053 List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
1054 if (typeAnnos.isEmpty()) {
1055 // else there would be no '@'
1056 throw new AssertionError("type annos is empty");
1057 }
1059 JCExpression expr = term3();
1061 // Type annotations: If term3 just parsed a non-type, expect a
1062 // class literal (and issue a syntax error if there is no class
1063 // literal). Otherwise, create a JCAnnotatedType.
1064 if ((mode & TYPE) == 0) {
1065 if (expr.getTag() != JCTree.SELECT)
1066 return illegal(typeAnnos.head.pos);
1067 JCFieldAccess sel = (JCFieldAccess)expr;
1068 if (sel.name != names._class)
1069 return illegal();
1070 else {
1071 sel.selected = F.AnnotatedType(typeAnnos, sel.selected);
1072 t = expr;
1073 }
1074 } else {
1075 // type annotation targeting a cast
1076 t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
1077 }
1078 break;
1079 case IDENTIFIER: case ASSERT: case ENUM:
1080 if (typeArgs != null) return illegal();
1081 t = toP(F.at(S.pos()).Ident(ident()));
1082 loop: while (true) {
1083 pos = S.pos();
1084 final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
1086 // need to report an error later if LBRACKET is for array
1087 // index access rather than array creation level
1088 if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS)
1089 return illegal(annos.head.pos);
1090 switch (S.token()) {
1091 case LBRACKET:
1092 S.nextToken();
1094 if (S.token() == RBRACKET) {
1096 S.nextToken();
1098 t = bracketsOpt(t, annos);
1099 t = toP(F.at(pos).TypeArray(t));
1100 t = bracketsSuffix(t);
1101 } else {
1102 if ((mode & EXPR) != 0) {
1103 mode = EXPR;
1104 JCExpression t1 = term();
1105 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1106 t = to(F.at(pos).Indexed(t, t1));
1107 }
1108 accept(RBRACKET);
1109 }
1110 break loop;
1111 case LPAREN:
1112 if ((mode & EXPR) != 0) {
1113 mode = EXPR;
1114 t = arguments(typeArgs, t);
1115 typeArgs = null;
1116 }
1117 break loop;
1118 case DOT:
1119 S.nextToken();
1120 int oldmode = mode;
1121 mode &= ~NOPARAMS;
1122 typeArgs = typeArgumentsOpt(EXPR);
1123 mode = oldmode;
1124 if ((mode & EXPR) != 0) {
1125 switch (S.token()) {
1126 case CLASS:
1127 if (typeArgs != null) return illegal();
1128 mode = EXPR;
1129 t = to(F.at(pos).Select(t, names._class));
1130 S.nextToken();
1131 break loop;
1132 case THIS:
1133 if (typeArgs != null) return illegal();
1134 mode = EXPR;
1135 t = to(F.at(pos).Select(t, names._this));
1136 S.nextToken();
1137 break loop;
1138 case SUPER:
1139 mode = EXPR;
1140 t = to(F.at(pos).Select(t, names._super));
1141 t = superSuffix(typeArgs, t);
1142 typeArgs = null;
1143 break loop;
1144 case NEW:
1145 if (typeArgs != null) return illegal();
1146 mode = EXPR;
1147 int pos1 = S.pos();
1148 S.nextToken();
1149 if (S.token() == LT) typeArgs = typeArguments();
1150 t = innerCreator(pos1, typeArgs, t);
1151 typeArgs = null;
1152 break loop;
1153 }
1154 }
1155 // typeArgs saved for next loop iteration.
1156 t = toP(F.at(pos).Select(t, ident()));
1157 break;
1158 case ELLIPSIS:
1159 if (this.permitTypeAnnotationsPushBack) {
1160 this.typeAnnotationsPushedBack = annos;
1161 } else if (annos.nonEmpty()) {
1162 // Don't return here -- error recovery attempt
1163 illegal(annos.head.pos);
1164 }
1165 break loop;
1166 default:
1167 break loop;
1168 }
1169 }
1170 if (typeArgs != null) illegal();
1171 t = typeArgumentsOpt(t);
1172 break;
1173 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1174 case DOUBLE: case BOOLEAN:
1175 if (typeArgs != null) illegal();
1176 t = bracketsSuffix(bracketsOpt(basicType()));
1177 break;
1178 case VOID:
1179 if (typeArgs != null) illegal();
1180 if ((mode & EXPR) != 0) {
1181 S.nextToken();
1182 if (S.token() == DOT) {
1183 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
1184 t = bracketsSuffix(ti);
1185 } else {
1186 return illegal(pos);
1187 }
1188 } else {
1189 // Support the corner case of myMethodHandle.<void>invoke() by passing
1190 // a void type (like other primitive types) to the next phase.
1191 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1192 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
1193 S.nextToken();
1194 return ti;
1195 //return illegal();
1196 }
1197 break;
1198 default:
1199 return illegal();
1200 }
1201 if (typeArgs != null) illegal();
1202 while (true) {
1203 int pos1 = S.pos();
1205 final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
1207 if (S.token() == LBRACKET) {
1208 S.nextToken();
1210 if ((mode & TYPE) != 0) {
1211 int oldmode = mode;
1212 mode = TYPE;
1213 if (S.token() == RBRACKET) {
1214 S.nextToken();
1215 t = bracketsOpt(t, annos);
1216 t = toP(F.at(pos1).TypeArray(t));
1217 return t;
1218 }
1219 mode = oldmode;
1220 }
1221 if ((mode & EXPR) != 0) {
1222 mode = EXPR;
1223 JCExpression t1 = term();
1224 t = to(F.at(pos1).Indexed(t, t1));
1225 }
1226 accept(RBRACKET);
1227 } else if (S.token() == DOT) {
1228 S.nextToken();
1229 typeArgs = typeArgumentsOpt(EXPR);
1230 if (S.token() == SUPER && (mode & EXPR) != 0) {
1231 mode = EXPR;
1232 t = to(F.at(pos1).Select(t, names._super));
1233 S.nextToken();
1234 t = arguments(typeArgs, t);
1235 typeArgs = null;
1236 } else if (S.token() == NEW && (mode & EXPR) != 0) {
1237 if (typeArgs != null) return illegal();
1238 mode = EXPR;
1239 int pos2 = S.pos();
1240 S.nextToken();
1241 if (S.token() == LT) typeArgs = typeArguments();
1242 t = innerCreator(pos2, typeArgs, t);
1243 typeArgs = null;
1244 } else {
1245 t = toP(F.at(pos1).Select(t, ident()));
1246 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1247 typeArgs = null;
1248 }
1249 } else {
1250 if (!annos.isEmpty()) {
1251 if (permitTypeAnnotationsPushBack)
1252 typeAnnotationsPushedBack = annos;
1253 else
1254 return illegal(annos.head.pos);
1255 }
1256 break;
1257 }
1258 }
1259 while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
1260 mode = EXPR;
1261 t = to(F.at(S.pos()).Unary(
1262 S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
1263 S.nextToken();
1264 }
1266 return toP(t);
1267 }
1269 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1270 */
1271 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1272 S.nextToken();
1273 if (S.token() == LPAREN || typeArgs != null) {
1274 t = arguments(typeArgs, t);
1275 } else {
1276 int pos = S.pos();
1277 accept(DOT);
1278 typeArgs = (S.token() == LT) ? typeArguments() : null;
1279 t = toP(F.at(pos).Select(t, ident()));
1280 t = argumentsOpt(typeArgs, t);
1281 }
1282 return t;
1283 }
1285 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1286 */
1287 JCPrimitiveTypeTree basicType() {
1288 JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
1289 S.nextToken();
1290 return t;
1291 }
1293 /** ArgumentsOpt = [ Arguments ]
1294 */
1295 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1296 if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
1297 mode = EXPR;
1298 return arguments(typeArgs, t);
1299 } else {
1300 return t;
1301 }
1302 }
1304 /** Arguments = "(" [Expression { COMMA Expression }] ")"
1305 */
1306 List<JCExpression> arguments() {
1307 ListBuffer<JCExpression> args = lb();
1308 if (S.token() == LPAREN) {
1309 S.nextToken();
1310 if (S.token() != RPAREN) {
1311 args.append(parseExpression());
1312 while (S.token() == COMMA) {
1313 S.nextToken();
1314 args.append(parseExpression());
1315 }
1316 }
1317 accept(RPAREN);
1318 } else {
1319 syntaxError(S.pos(), "expected", LPAREN);
1320 }
1321 return args.toList();
1322 }
1324 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1325 int pos = S.pos();
1326 List<JCExpression> args = arguments();
1327 return toP(F.at(pos).Apply(typeArgs, t, args));
1328 }
1330 /** TypeArgumentsOpt = [ TypeArguments ]
1331 */
1332 JCExpression typeArgumentsOpt(JCExpression t) {
1333 if (S.token() == LT &&
1334 (mode & TYPE) != 0 &&
1335 (mode & NOPARAMS) == 0) {
1336 mode = TYPE;
1337 checkGenerics();
1338 return typeArguments(t);
1339 } else {
1340 return t;
1341 }
1342 }
1343 List<JCExpression> typeArgumentsOpt() {
1344 return typeArgumentsOpt(TYPE);
1345 }
1347 List<JCExpression> typeArgumentsOpt(int useMode) {
1348 if (S.token() == LT) {
1349 checkGenerics();
1350 if ((mode & useMode) == 0 ||
1351 (mode & NOPARAMS) != 0) {
1352 illegal();
1353 }
1354 mode = useMode;
1355 return typeArguments();
1356 }
1357 return null;
1358 }
1360 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1361 */
1362 List<JCExpression> typeArguments() {
1363 ListBuffer<JCExpression> args = lb();
1364 if (S.token() == LT) {
1365 S.nextToken();
1366 if (S.token() == GT && (mode & DIAMOND) != 0) {
1367 checkDiamond();
1368 S.nextToken();
1369 return List.nil();
1370 }
1371 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1372 while (S.token() == COMMA) {
1373 S.nextToken();
1374 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1375 }
1376 switch (S.token()) {
1377 case GTGTGTEQ:
1378 S.token(GTGTEQ);
1379 break;
1380 case GTGTEQ:
1381 S.token(GTEQ);
1382 break;
1383 case GTEQ:
1384 S.token(EQ);
1385 break;
1386 case GTGTGT:
1387 S.token(GTGT);
1388 break;
1389 case GTGT:
1390 S.token(GT);
1391 break;
1392 default:
1393 accept(GT);
1394 break;
1395 }
1396 } else {
1397 syntaxError(S.pos(), "expected", LT);
1398 }
1399 return args.toList();
1400 }
1402 /** TypeArgument = Type
1403 * | [Annotations] "?"
1404 * | [Annotations] "?" EXTENDS Type {"&" Type}
1405 * | [Annotations] "?" SUPER Type
1406 */
1407 JCExpression typeArgument() {
1408 List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
1409 if (S.token() != QUES) return parseType(annotations);
1410 int pos = S.pos();
1411 S.nextToken();
1412 JCExpression result;
1413 if (S.token() == EXTENDS) {
1414 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
1415 S.nextToken();
1416 JCExpression bound = parseType();
1417 result = F.at(pos).Wildcard(t, bound);
1418 } else if (S.token() == SUPER) {
1419 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
1420 S.nextToken();
1421 JCExpression bound = parseType();
1422 result = F.at(pos).Wildcard(t, bound);
1423 } else if (S.token() == IDENTIFIER) {
1424 //error recovery
1425 reportSyntaxError(S.prevEndPos(), "expected3",
1426 GT, EXTENDS, SUPER);
1427 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1428 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1429 JCIdent id = toP(F.at(S.pos()).Ident(ident()));
1430 result = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1431 } else {
1432 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
1433 result = toP(F.at(pos).Wildcard(t, null));
1434 }
1435 if (!annotations.isEmpty())
1436 result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
1437 return result;
1438 }
1440 JCTypeApply typeArguments(JCExpression t) {
1441 int pos = S.pos();
1442 List<JCExpression> args = typeArguments();
1443 return toP(F.at(pos).TypeApply(t, args));
1444 }
1446 /**
1447 * BracketsOpt = { [Annotations] "[" "]" }
1448 *
1449 * <p>
1450 *
1451 * <code>annotations</code> is the list of annotations targeting
1452 * the expression <code>t</code>.
1453 */
1454 private JCExpression bracketsOpt(JCExpression t,
1455 List<JCTypeAnnotation> annotations) {
1456 List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
1458 if (S.token() == LBRACKET) {
1459 int pos = S.pos();
1460 S.nextToken();
1462 JCExpression orig = t;
1463 t = bracketsOptCont(t, pos, nextLevelAnnotations);
1464 } else if (!nextLevelAnnotations.isEmpty()) {
1465 if (permitTypeAnnotationsPushBack) {
1466 this.typeAnnotationsPushedBack = nextLevelAnnotations;
1467 } else
1468 return illegal(nextLevelAnnotations.head.pos);
1469 }
1471 int apos = S.pos();
1472 if (!annotations.isEmpty())
1473 t = F.at(apos).AnnotatedType(annotations, t);
1474 return t;
1475 }
1477 /** BracketsOpt = {"[" TypeAnnotations "]"}
1478 */
1479 private JCExpression bracketsOpt(JCExpression t) {
1480 return bracketsOpt(t, List.<JCTypeAnnotation>nil());
1481 }
1483 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos,
1484 List<JCTypeAnnotation> annotations) {
1485 accept(RBRACKET);
1486 t = bracketsOpt(t, annotations);
1487 return toP(F.at(pos).TypeArray(t));
1488 }
1490 /** BracketsSuffixExpr = "." CLASS
1491 * BracketsSuffixType =
1492 */
1493 JCExpression bracketsSuffix(JCExpression t) {
1494 if ((mode & EXPR) != 0 && S.token() == DOT) {
1495 mode = EXPR;
1496 int pos = S.pos();
1497 S.nextToken();
1498 accept(CLASS);
1499 if (S.pos() == errorEndPos) {
1500 // error recovery
1501 Name name = null;
1502 if (S.token() == IDENTIFIER) {
1503 name = S.name();
1504 S.nextToken();
1505 } else {
1506 name = names.error;
1507 }
1508 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1509 } else {
1510 t = toP(F.at(pos).Select(t, names._class));
1511 }
1512 } else if ((mode & TYPE) != 0) {
1513 mode = TYPE;
1514 } else {
1515 syntaxError(S.pos(), "dot.class.expected");
1516 }
1517 return t;
1518 }
1520 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1521 */
1522 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1524 List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt();
1526 switch (S.token()) {
1527 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1528 case DOUBLE: case BOOLEAN:
1529 if (typeArgs == null) {
1530 if (newAnnotations.isEmpty())
1531 return arrayCreatorRest(newpos, basicType());
1532 else
1533 return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType()));
1534 }
1535 break;
1536 default:
1537 }
1538 JCExpression t = qualident();
1539 // handle type annotations for non primitive arrays
1540 if (!newAnnotations.isEmpty())
1541 t = F.AnnotatedType(newAnnotations, t);
1543 int oldmode = mode;
1544 mode = TYPE | DIAMOND;
1545 if (S.token() == LT) {
1546 checkGenerics();
1547 t = typeArguments(t);
1548 }
1549 while (S.token() == DOT) {
1550 int pos = S.pos();
1551 S.nextToken();
1552 t = toP(F.at(pos).Select(t, ident()));
1553 if (S.token() == LT) {
1554 checkGenerics();
1555 t = typeArguments(t);
1556 }
1557 }
1558 mode = oldmode;
1559 if (S.token() == LBRACKET || S.token() == MONKEYS_AT) {
1560 JCExpression e = arrayCreatorRest(newpos, t);
1561 if (typeArgs != null) {
1562 int pos = newpos;
1563 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1564 // note: this should always happen but we should
1565 // not rely on this as the parser is continuously
1566 // modified to improve error recovery.
1567 pos = typeArgs.head.pos;
1568 }
1569 setErrorEndPos(S.prevEndPos());
1570 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
1571 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
1572 }
1573 return e;
1574 } else if (S.token() == LPAREN) {
1575 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
1576 if (newClass.def != null) {
1577 assert newClass.def.mods.annotations.isEmpty();
1578 if (newAnnotations.nonEmpty()) {
1579 newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
1580 newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
1581 }
1582 }
1583 return newClass;
1584 } else {
1585 reportSyntaxError(S.pos(), "expected2",
1586 LPAREN, LBRACKET);
1587 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1588 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1589 }
1590 }
1592 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1593 */
1594 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1595 JCExpression t = toP(F.at(S.pos()).Ident(ident()));
1596 if (S.token() == LT) {
1597 int oldmode = mode;
1598 mode |= DIAMOND;
1599 checkGenerics();
1600 t = typeArguments(t);
1601 mode = oldmode;
1602 }
1603 return classCreatorRest(newpos, encl, typeArgs, t);
1604 }
1606 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
1607 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
1608 */
1609 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1611 List<JCTypeAnnotation> topAnnos = List.nil();
1612 if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
1613 JCAnnotatedType atype = (JCAnnotatedType) elemtype;
1614 topAnnos = atype.annotations;
1615 elemtype = atype.underlyingType;
1616 }
1618 List<JCTypeAnnotation> annos = typeAnnotationsOpt();
1620 accept(LBRACKET);
1622 if (S.token() == RBRACKET) {
1623 accept(RBRACKET);
1625 elemtype = bracketsOpt(elemtype, annos);
1627 if (S.token() == LBRACE) {
1628 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
1630 na.annotations = topAnnos;
1632 return na;
1633 } else {
1634 return syntaxError(S.pos(), "array.dimension.missing");
1635 }
1636 } else {
1637 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1639 // maintain array dimension type annotations
1640 ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb();
1641 dimAnnotations.append(annos);
1643 dims.append(parseExpression());
1644 accept(RBRACKET);
1645 while (S.token() == LBRACKET
1646 || (S.token() == MONKEYS_AT)) {
1647 List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt();
1648 int pos = S.pos();
1649 S.nextToken();
1650 if (S.token() == RBRACKET) {
1651 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
1652 } else {
1653 if (S.token() == RBRACKET) { // no dimension
1654 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
1655 } else {
1656 dimAnnotations.append(maybeDimAnnos);
1657 dims.append(parseExpression());
1658 accept(RBRACKET);
1659 }
1660 }
1661 }
1663 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1664 na.annotations = topAnnos;
1665 na.dimAnnotations = dimAnnotations.toList();
1666 return na;
1667 }
1668 }
1670 /** ClassCreatorRest = Arguments [ClassBody]
1671 */
1672 JCNewClass classCreatorRest(int newpos,
1673 JCExpression encl,
1674 List<JCExpression> typeArgs,
1675 JCExpression t)
1676 {
1677 List<JCExpression> args = arguments();
1678 JCClassDecl body = null;
1679 if (S.token() == LBRACE) {
1680 int pos = S.pos();
1681 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1682 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1683 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1684 }
1685 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1686 }
1688 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1689 */
1690 JCExpression arrayInitializer(int newpos, JCExpression t) {
1691 accept(LBRACE);
1692 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1693 if (S.token() == COMMA) {
1694 S.nextToken();
1695 } else if (S.token() != RBRACE) {
1696 elems.append(variableInitializer());
1697 while (S.token() == COMMA) {
1698 S.nextToken();
1699 if (S.token() == RBRACE) break;
1700 elems.append(variableInitializer());
1701 }
1702 }
1703 accept(RBRACE);
1704 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1705 }
1707 /** VariableInitializer = ArrayInitializer | Expression
1708 */
1709 public JCExpression variableInitializer() {
1710 return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
1711 }
1713 /** ParExpression = "(" Expression ")"
1714 */
1715 JCExpression parExpression() {
1716 accept(LPAREN);
1717 JCExpression t = parseExpression();
1718 accept(RPAREN);
1719 return t;
1720 }
1722 /** Block = "{" BlockStatements "}"
1723 */
1724 JCBlock block(int pos, long flags) {
1725 accept(LBRACE);
1726 List<JCStatement> stats = blockStatements();
1727 JCBlock t = F.at(pos).Block(flags, stats);
1728 while (S.token() == CASE || S.token() == DEFAULT) {
1729 syntaxError("orphaned", S.token());
1730 switchBlockStatementGroups();
1731 }
1732 // the Block node has a field "endpos" for first char of last token, which is
1733 // usually but not necessarily the last char of the last token.
1734 t.endpos = S.pos();
1735 accept(RBRACE);
1736 return toP(t);
1737 }
1739 public JCBlock block() {
1740 return block(S.pos(), 0);
1741 }
1743 /** BlockStatements = { BlockStatement }
1744 * BlockStatement = LocalVariableDeclarationStatement
1745 * | ClassOrInterfaceOrEnumDeclaration
1746 * | [Ident ":"] Statement
1747 * LocalVariableDeclarationStatement
1748 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1749 */
1750 @SuppressWarnings("fallthrough")
1751 List<JCStatement> blockStatements() {
1752 //todo: skip to anchor on error(?)
1753 int lastErrPos = -1;
1754 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1755 while (true) {
1756 int pos = S.pos();
1757 switch (S.token()) {
1758 case RBRACE: case CASE: case DEFAULT: case EOF:
1759 return stats.toList();
1760 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1761 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1762 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1763 stats.append(parseStatement());
1764 break;
1765 case MONKEYS_AT:
1766 case FINAL: {
1767 String dc = S.docComment();
1768 JCModifiers mods = modifiersOpt();
1769 if (S.token() == INTERFACE ||
1770 S.token() == CLASS ||
1771 allowEnums && S.token() == ENUM) {
1772 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1773 } else {
1774 JCExpression t = parseType();
1775 stats.appendList(variableDeclarators(mods, t,
1776 new ListBuffer<JCStatement>()));
1777 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1778 storeEnd(stats.elems.last(), S.endPos());
1779 accept(SEMI);
1780 }
1781 break;
1782 }
1783 case ABSTRACT: case STRICTFP: {
1784 String dc = S.docComment();
1785 JCModifiers mods = modifiersOpt();
1786 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1787 break;
1788 }
1789 case INTERFACE:
1790 case CLASS:
1791 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1792 S.docComment()));
1793 break;
1794 case ENUM:
1795 case ASSERT:
1796 if (allowEnums && S.token() == ENUM) {
1797 log.error(S.pos(), "local.enum");
1798 stats.
1799 append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1800 S.docComment()));
1801 break;
1802 } else if (allowAsserts && S.token() == ASSERT) {
1803 stats.append(parseStatement());
1804 break;
1805 }
1806 /* fall through to default */
1807 default:
1808 Name name = S.name();
1809 JCExpression t = term(EXPR | TYPE);
1810 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
1811 S.nextToken();
1812 JCStatement stat = parseStatement();
1813 stats.append(F.at(pos).Labelled(name, stat));
1814 } else if ((lastmode & TYPE) != 0 &&
1815 (S.token() == IDENTIFIER ||
1816 S.token() == ASSERT ||
1817 S.token() == ENUM)) {
1818 pos = S.pos();
1819 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1820 F.at(pos);
1821 stats.appendList(variableDeclarators(mods, t,
1822 new ListBuffer<JCStatement>()));
1823 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1824 storeEnd(stats.elems.last(), S.endPos());
1825 accept(SEMI);
1826 } else {
1827 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1828 stats.append(to(F.at(pos).Exec(checkExprStat(t))));
1829 accept(SEMI);
1830 }
1831 }
1833 // error recovery
1834 if (S.pos() == lastErrPos)
1835 return stats.toList();
1836 if (S.pos() <= errorEndPos) {
1837 skip(false, true, true, true);
1838 lastErrPos = S.pos();
1839 }
1841 // ensure no dangling /** @deprecated */ active
1842 S.resetDeprecatedFlag();
1843 }
1844 }
1846 /** Statement =
1847 * Block
1848 * | IF ParExpression Statement [ELSE Statement]
1849 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1850 * | FOR "(" FormalParameter : Expression ")" Statement
1851 * | WHILE ParExpression Statement
1852 * | DO Statement WHILE ParExpression ";"
1853 * | TRY Block ( Catches | [Catches] FinallyPart )
1854 * | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart]
1855 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1856 * | SYNCHRONIZED ParExpression Block
1857 * | RETURN [Expression] ";"
1858 * | THROW Expression ";"
1859 * | BREAK [Ident] ";"
1860 * | CONTINUE [Ident] ";"
1861 * | ASSERT Expression [ ":" Expression ] ";"
1862 * | ";"
1863 * | ExpressionStatement
1864 * | Ident ":" Statement
1865 */
1866 @SuppressWarnings("fallthrough")
1867 public JCStatement parseStatement() {
1868 int pos = S.pos();
1869 switch (S.token()) {
1870 case LBRACE:
1871 return block();
1872 case IF: {
1873 S.nextToken();
1874 JCExpression cond = parExpression();
1875 JCStatement thenpart = parseStatement();
1876 JCStatement elsepart = null;
1877 if (S.token() == ELSE) {
1878 S.nextToken();
1879 elsepart = parseStatement();
1880 }
1881 return F.at(pos).If(cond, thenpart, elsepart);
1882 }
1883 case FOR: {
1884 S.nextToken();
1885 accept(LPAREN);
1886 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
1887 if (inits.length() == 1 &&
1888 inits.head.getTag() == JCTree.VARDEF &&
1889 ((JCVariableDecl) inits.head).init == null &&
1890 S.token() == COLON) {
1891 checkForeach();
1892 JCVariableDecl var = (JCVariableDecl)inits.head;
1893 accept(COLON);
1894 JCExpression expr = parseExpression();
1895 accept(RPAREN);
1896 JCStatement body = parseStatement();
1897 return F.at(pos).ForeachLoop(var, expr, body);
1898 } else {
1899 accept(SEMI);
1900 JCExpression cond = S.token() == SEMI ? null : parseExpression();
1901 accept(SEMI);
1902 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
1903 accept(RPAREN);
1904 JCStatement body = parseStatement();
1905 return F.at(pos).ForLoop(inits, cond, steps, body);
1906 }
1907 }
1908 case WHILE: {
1909 S.nextToken();
1910 JCExpression cond = parExpression();
1911 JCStatement body = parseStatement();
1912 return F.at(pos).WhileLoop(cond, body);
1913 }
1914 case DO: {
1915 S.nextToken();
1916 JCStatement body = parseStatement();
1917 accept(WHILE);
1918 JCExpression cond = parExpression();
1919 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
1920 accept(SEMI);
1921 return t;
1922 }
1923 case TRY: {
1924 S.nextToken();
1925 List<JCTree> resources = List.<JCTree>nil();
1926 if (S.token() == LPAREN) {
1927 checkAutomaticResourceManagement();
1928 S.nextToken();
1929 resources = resources();
1930 accept(RPAREN);
1931 }
1932 JCBlock body = block();
1933 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
1934 JCBlock finalizer = null;
1935 if (S.token() == CATCH || S.token() == FINALLY) {
1936 while (S.token() == CATCH) catchers.append(catchClause());
1937 if (S.token() == FINALLY) {
1938 S.nextToken();
1939 finalizer = block();
1940 }
1941 } else {
1942 if (allowTWR) {
1943 if (resources.isEmpty())
1944 log.error(pos, "try.without.catch.finally.or.resource.decls");
1945 } else
1946 log.error(pos, "try.without.catch.or.finally");
1947 }
1948 return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
1949 }
1950 case SWITCH: {
1951 S.nextToken();
1952 JCExpression selector = parExpression();
1953 accept(LBRACE);
1954 List<JCCase> cases = switchBlockStatementGroups();
1955 JCSwitch t = to(F.at(pos).Switch(selector, cases));
1956 accept(RBRACE);
1957 return t;
1958 }
1959 case SYNCHRONIZED: {
1960 S.nextToken();
1961 JCExpression lock = parExpression();
1962 JCBlock body = block();
1963 return F.at(pos).Synchronized(lock, body);
1964 }
1965 case RETURN: {
1966 S.nextToken();
1967 JCExpression result = S.token() == SEMI ? null : parseExpression();
1968 JCReturn t = to(F.at(pos).Return(result));
1969 accept(SEMI);
1970 return t;
1971 }
1972 case THROW: {
1973 S.nextToken();
1974 JCExpression exc = parseExpression();
1975 JCThrow t = to(F.at(pos).Throw(exc));
1976 accept(SEMI);
1977 return t;
1978 }
1979 case BREAK: {
1980 S.nextToken();
1981 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1982 JCBreak t = to(F.at(pos).Break(label));
1983 accept(SEMI);
1984 return t;
1985 }
1986 case CONTINUE: {
1987 S.nextToken();
1988 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1989 JCContinue t = to(F.at(pos).Continue(label));
1990 accept(SEMI);
1991 return t;
1992 }
1993 case SEMI:
1994 S.nextToken();
1995 return toP(F.at(pos).Skip());
1996 case ELSE:
1997 return toP(F.Exec(syntaxError("else.without.if")));
1998 case FINALLY:
1999 return toP(F.Exec(syntaxError("finally.without.try")));
2000 case CATCH:
2001 return toP(F.Exec(syntaxError("catch.without.try")));
2002 case ASSERT: {
2003 if (allowAsserts && S.token() == ASSERT) {
2004 S.nextToken();
2005 JCExpression assertion = parseExpression();
2006 JCExpression message = null;
2007 if (S.token() == COLON) {
2008 S.nextToken();
2009 message = parseExpression();
2010 }
2011 JCAssert t = to(F.at(pos).Assert(assertion, message));
2012 accept(SEMI);
2013 return t;
2014 }
2015 /* else fall through to default case */
2016 }
2017 case ENUM:
2018 default:
2019 Name name = S.name();
2020 JCExpression expr = parseExpression();
2021 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
2022 S.nextToken();
2023 JCStatement stat = parseStatement();
2024 return F.at(pos).Labelled(name, stat);
2025 } else {
2026 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2027 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
2028 accept(SEMI);
2029 return stat;
2030 }
2031 }
2032 }
2034 /** CatchClause = CATCH "(" FormalParameter ")" Block
2035 */
2036 JCCatch catchClause() {
2037 int pos = S.pos();
2038 accept(CATCH);
2039 accept(LPAREN);
2040 JCModifiers mods = optFinal(Flags.PARAMETER);
2041 List<JCExpression> catchTypes = catchTypes();
2042 JCExpression paramType = catchTypes.size() > 1 ?
2043 toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
2044 catchTypes.head;
2045 JCVariableDecl formal = variableDeclaratorId(mods, paramType);
2046 accept(RPAREN);
2047 JCBlock body = block();
2048 return F.at(pos).Catch(formal, body);
2049 }
2051 List<JCExpression> catchTypes() {
2052 ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
2053 catchTypes.add(parseType());
2054 while (S.token() == BAR) {
2055 checkMulticatch();
2056 S.nextToken();
2057 catchTypes.add(qualident());
2058 }
2059 return catchTypes.toList();
2060 }
2062 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2063 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
2064 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2065 */
2066 List<JCCase> switchBlockStatementGroups() {
2067 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2068 while (true) {
2069 int pos = S.pos();
2070 switch (S.token()) {
2071 case CASE: {
2072 S.nextToken();
2073 JCExpression pat = parseExpression();
2074 accept(COLON);
2075 List<JCStatement> stats = blockStatements();
2076 JCCase c = F.at(pos).Case(pat, stats);
2077 if (stats.isEmpty())
2078 storeEnd(c, S.prevEndPos());
2079 cases.append(c);
2080 break;
2081 }
2082 case DEFAULT: {
2083 S.nextToken();
2084 accept(COLON);
2085 List<JCStatement> stats = blockStatements();
2086 JCCase c = F.at(pos).Case(null, stats);
2087 if (stats.isEmpty())
2088 storeEnd(c, S.prevEndPos());
2089 cases.append(c);
2090 break;
2091 }
2092 case RBRACE: case EOF:
2093 return cases.toList();
2094 default:
2095 S.nextToken(); // to ensure progress
2096 syntaxError(pos, "expected3",
2097 CASE, DEFAULT, RBRACE);
2098 }
2099 }
2100 }
2102 /** MoreStatementExpressions = { COMMA StatementExpression }
2103 */
2104 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2105 JCExpression first,
2106 T stats) {
2107 // This Exec is a "StatementExpression"; it subsumes no terminating token
2108 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2109 while (S.token() == COMMA) {
2110 S.nextToken();
2111 pos = S.pos();
2112 JCExpression t = parseExpression();
2113 // This Exec is a "StatementExpression"; it subsumes no terminating token
2114 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2115 }
2116 return stats;
2117 }
2119 /** ForInit = StatementExpression MoreStatementExpressions
2120 * | { FINAL | '@' Annotation } Type VariableDeclarators
2121 */
2122 List<JCStatement> forInit() {
2123 ListBuffer<JCStatement> stats = lb();
2124 int pos = S.pos();
2125 if (S.token() == FINAL || S.token() == MONKEYS_AT) {
2126 return variableDeclarators(optFinal(0), parseType(), stats).toList();
2127 } else {
2128 JCExpression t = term(EXPR | TYPE);
2129 if ((lastmode & TYPE) != 0 &&
2130 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
2131 return variableDeclarators(modifiersOpt(), t, stats).toList();
2132 else
2133 return moreStatementExpressions(pos, t, stats).toList();
2134 }
2135 }
2137 /** ForUpdate = StatementExpression MoreStatementExpressions
2138 */
2139 List<JCExpressionStatement> forUpdate() {
2140 return moreStatementExpressions(S.pos(),
2141 parseExpression(),
2142 new ListBuffer<JCExpressionStatement>()).toList();
2143 }
2145 enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO };
2147 /** AnnotationsOpt = { '@' Annotation }
2148 */
2149 List<JCAnnotation> annotationsOpt(AnnotationKind kind) {
2150 if (S.token() != MONKEYS_AT) return List.nil(); // optimization
2151 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
2152 int prevmode = mode;
2153 while (S.token() == MONKEYS_AT) {
2154 int pos = S.pos();
2155 S.nextToken();
2156 buf.append(annotation(pos, kind));
2157 }
2158 lastmode = mode;
2159 mode = prevmode;
2160 List<JCAnnotation> annotations = buf.toList();
2162 if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO)
2163 System.out.println("TA: parsing " + annotations
2164 + " in " + log.currentSourceFile());
2165 return annotations;
2166 }
2168 List<JCTypeAnnotation> typeAnnotationsOpt() {
2169 List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO);
2170 return List.convert(JCTypeAnnotation.class, annotations);
2171 }
2173 /** ModifiersOpt = { Modifier }
2174 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
2175 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
2176 * | "@" Annotation
2177 */
2178 JCModifiers modifiersOpt() {
2179 return modifiersOpt(null);
2180 }
2181 JCModifiers modifiersOpt(JCModifiers partial) {
2182 long flags;
2183 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
2184 int pos;
2185 if (partial == null) {
2186 flags = 0;
2187 pos = S.pos();
2188 } else {
2189 flags = partial.flags;
2190 annotations.appendList(partial.annotations);
2191 pos = partial.pos;
2192 }
2193 if (S.deprecatedFlag()) {
2194 flags |= Flags.DEPRECATED;
2195 S.resetDeprecatedFlag();
2196 }
2197 int lastPos = Position.NOPOS;
2198 loop:
2199 while (true) {
2200 long flag;
2201 switch (S.token()) {
2202 case PRIVATE : flag = Flags.PRIVATE; break;
2203 case PROTECTED : flag = Flags.PROTECTED; break;
2204 case PUBLIC : flag = Flags.PUBLIC; break;
2205 case STATIC : flag = Flags.STATIC; break;
2206 case TRANSIENT : flag = Flags.TRANSIENT; break;
2207 case FINAL : flag = Flags.FINAL; break;
2208 case ABSTRACT : flag = Flags.ABSTRACT; break;
2209 case NATIVE : flag = Flags.NATIVE; break;
2210 case VOLATILE : flag = Flags.VOLATILE; break;
2211 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
2212 case STRICTFP : flag = Flags.STRICTFP; break;
2213 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
2214 default: break loop;
2215 }
2216 if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
2217 lastPos = S.pos();
2218 S.nextToken();
2219 if (flag == Flags.ANNOTATION) {
2220 checkAnnotations();
2221 if (S.token() != INTERFACE) {
2222 JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO);
2223 // if first modifier is an annotation, set pos to annotation's.
2224 if (flags == 0 && annotations.isEmpty())
2225 pos = ann.pos;
2226 annotations.append(ann);
2227 lastPos = ann.pos;
2228 flag = 0;
2229 }
2230 }
2231 flags |= flag;
2232 }
2233 switch (S.token()) {
2234 case ENUM: flags |= Flags.ENUM; break;
2235 case INTERFACE: flags |= Flags.INTERFACE; break;
2236 default: break;
2237 }
2239 /* A modifiers tree with no modifier tokens or annotations
2240 * has no text position. */
2241 if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty())
2242 pos = Position.NOPOS;
2244 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
2245 if (pos != Position.NOPOS)
2246 storeEnd(mods, S.prevEndPos());
2247 return mods;
2248 }
2250 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2251 * @param pos position of "@" token
2252 */
2253 JCAnnotation annotation(int pos, AnnotationKind kind) {
2254 // accept(AT); // AT consumed by caller
2255 checkAnnotations();
2256 if (kind == AnnotationKind.TYPE_ANNO)
2257 checkTypeAnnotations();
2258 JCTree ident = qualident();
2259 List<JCExpression> fieldValues = annotationFieldValuesOpt();
2260 JCAnnotation ann;
2261 if (kind == AnnotationKind.DEFAULT_ANNO)
2262 ann = F.at(pos).Annotation(ident, fieldValues);
2263 else
2264 ann = F.at(pos).TypeAnnotation(ident, fieldValues);
2265 storeEnd(ann, S.prevEndPos());
2266 return ann;
2267 }
2269 List<JCExpression> annotationFieldValuesOpt() {
2270 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2271 }
2273 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2274 List<JCExpression> annotationFieldValues() {
2275 accept(LPAREN);
2276 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2277 if (S.token() != RPAREN) {
2278 buf.append(annotationFieldValue());
2279 while (S.token() == COMMA) {
2280 S.nextToken();
2281 buf.append(annotationFieldValue());
2282 }
2283 }
2284 accept(RPAREN);
2285 return buf.toList();
2286 }
2288 /** AnnotationFieldValue = AnnotationValue
2289 * | Identifier "=" AnnotationValue
2290 */
2291 JCExpression annotationFieldValue() {
2292 if (S.token() == IDENTIFIER) {
2293 mode = EXPR;
2294 JCExpression t1 = term1();
2295 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
2296 int pos = S.pos();
2297 accept(EQ);
2298 JCExpression v = annotationValue();
2299 return toP(F.at(pos).Assign(t1, v));
2300 } else {
2301 return t1;
2302 }
2303 }
2304 return annotationValue();
2305 }
2307 /* AnnotationValue = ConditionalExpression
2308 * | Annotation
2309 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2310 */
2311 JCExpression annotationValue() {
2312 int pos;
2313 switch (S.token()) {
2314 case MONKEYS_AT:
2315 pos = S.pos();
2316 S.nextToken();
2317 return annotation(pos, AnnotationKind.DEFAULT_ANNO);
2318 case LBRACE:
2319 pos = S.pos();
2320 accept(LBRACE);
2321 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2322 if (S.token() != RBRACE) {
2323 buf.append(annotationValue());
2324 while (S.token() == COMMA) {
2325 S.nextToken();
2326 if (S.token() == RBRACE) break;
2327 buf.append(annotationValue());
2328 }
2329 }
2330 accept(RBRACE);
2331 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2332 default:
2333 mode = EXPR;
2334 return term1();
2335 }
2336 }
2338 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2339 */
2340 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2341 JCExpression type,
2342 T vdefs)
2343 {
2344 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
2345 }
2347 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2348 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2349 *
2350 * @param reqInit Is an initializer always required?
2351 * @param dc The documentation comment for the variable declarations, or null.
2352 */
2353 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2354 JCModifiers mods,
2355 JCExpression type,
2356 Name name,
2357 boolean reqInit,
2358 String dc,
2359 T vdefs)
2360 {
2361 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2362 while (S.token() == COMMA) {
2363 // All but last of multiple declarators subsume a comma
2364 storeEnd((JCTree)vdefs.elems.last(), S.endPos());
2365 S.nextToken();
2366 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2367 }
2368 return vdefs;
2369 }
2371 /** VariableDeclarator = Ident VariableDeclaratorRest
2372 * ConstantDeclarator = Ident ConstantDeclaratorRest
2373 */
2374 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
2375 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
2376 }
2378 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2379 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2380 *
2381 * @param reqInit Is an initializer always required?
2382 * @param dc The documentation comment for the variable declarations, or null.
2383 */
2384 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2385 boolean reqInit, String dc) {
2386 type = bracketsOpt(type);
2387 JCExpression init = null;
2388 if (S.token() == EQ) {
2389 S.nextToken();
2390 init = variableInitializer();
2391 }
2392 else if (reqInit) syntaxError(S.pos(), "expected", EQ);
2393 JCVariableDecl result =
2394 toP(F.at(pos).VarDef(mods, name, type, init));
2395 attach(result, dc);
2396 return result;
2397 }
2399 /** VariableDeclaratorId = Ident BracketsOpt
2400 */
2401 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2402 int pos = S.pos();
2403 Name name = ident();
2404 if ((mods.flags & Flags.VARARGS) == 0)
2405 type = bracketsOpt(type);
2406 return toP(F.at(pos).VarDef(mods, name, type, null));
2407 }
2409 /** Resources = Resource { ";" Resources }
2410 */
2411 List<JCTree> resources() {
2412 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2413 defs.append(resource());
2414 while (S.token() == SEMI) {
2415 // All but last of multiple declarators subsume a semicolon
2416 storeEnd(defs.elems.last(), S.endPos());
2417 S.nextToken();
2418 defs.append(resource());
2419 }
2420 return defs.toList();
2421 }
2423 /** Resource =
2424 * VariableModifiers Type VariableDeclaratorId = Expression
2425 * | Expression
2426 */
2427 JCTree resource() {
2428 int pos = S.pos();
2429 if (S.token() == FINAL || S.token() == MONKEYS_AT) {
2430 return variableDeclaratorRest(pos, optFinal(0), parseType(),
2431 ident(), true, null);
2432 } else {
2433 JCExpression t = term(EXPR | TYPE);
2434 if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER)
2435 return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t,
2436 ident(), true, null);
2437 else
2438 return t;
2439 }
2440 }
2442 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2443 */
2444 public JCTree.JCCompilationUnit parseCompilationUnit() {
2445 int pos = S.pos();
2446 JCExpression pid = null;
2447 String dc = S.docComment();
2448 JCModifiers mods = null;
2449 List<JCAnnotation> packageAnnotations = List.nil();
2450 if (S.token() == MONKEYS_AT)
2451 mods = modifiersOpt();
2453 if (S.token() == PACKAGE) {
2454 if (mods != null) {
2455 checkNoMods(mods.flags);
2456 packageAnnotations = mods.annotations;
2457 mods = null;
2458 }
2459 S.nextToken();
2460 pid = qualident();
2461 accept(SEMI);
2462 }
2463 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2464 boolean checkForImports = true;
2465 while (S.token() != EOF) {
2466 if (S.pos() <= errorEndPos) {
2467 // error recovery
2468 skip(checkForImports, false, false, false);
2469 if (S.token() == EOF)
2470 break;
2471 }
2472 if (checkForImports && mods == null && S.token() == IMPORT) {
2473 defs.append(importDeclaration());
2474 } else {
2475 JCTree def = typeDeclaration(mods);
2476 if (def instanceof JCExpressionStatement)
2477 def = ((JCExpressionStatement)def).expr;
2478 defs.append(def);
2479 if (def instanceof JCClassDecl)
2480 checkForImports = false;
2481 mods = null;
2482 }
2483 }
2484 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
2485 attach(toplevel, dc);
2486 if (defs.elems.isEmpty())
2487 storeEnd(toplevel, S.prevEndPos());
2488 if (keepDocComments)
2489 toplevel.docComments = docComments;
2490 if (keepLineMap)
2491 toplevel.lineMap = S.getLineMap();
2492 return toplevel;
2493 }
2495 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2496 */
2497 JCTree importDeclaration() {
2498 int pos = S.pos();
2499 S.nextToken();
2500 boolean importStatic = false;
2501 if (S.token() == STATIC) {
2502 checkStaticImports();
2503 importStatic = true;
2504 S.nextToken();
2505 }
2506 JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
2507 do {
2508 int pos1 = S.pos();
2509 accept(DOT);
2510 if (S.token() == STAR) {
2511 pid = to(F.at(pos1).Select(pid, names.asterisk));
2512 S.nextToken();
2513 break;
2514 } else {
2515 pid = toP(F.at(pos1).Select(pid, ident()));
2516 }
2517 } while (S.token() == DOT);
2518 accept(SEMI);
2519 return toP(F.at(pos).Import(pid, importStatic));
2520 }
2522 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2523 * | ";"
2524 */
2525 JCTree typeDeclaration(JCModifiers mods) {
2526 int pos = S.pos();
2527 if (mods == null && S.token() == SEMI) {
2528 S.nextToken();
2529 return toP(F.at(pos).Skip());
2530 } else {
2531 String dc = S.docComment();
2532 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
2533 }
2534 }
2536 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2537 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2538 * @param mods Any modifiers starting the class or interface declaration
2539 * @param dc The documentation comment for the class, or null.
2540 */
2541 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
2542 if (S.token() == CLASS) {
2543 return classDeclaration(mods, dc);
2544 } else if (S.token() == INTERFACE) {
2545 return interfaceDeclaration(mods, dc);
2546 } else if (allowEnums) {
2547 if (S.token() == ENUM) {
2548 return enumDeclaration(mods, dc);
2549 } else {
2550 int pos = S.pos();
2551 List<JCTree> errs;
2552 if (S.token() == IDENTIFIER) {
2553 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2554 setErrorEndPos(S.pos());
2555 } else {
2556 errs = List.<JCTree>of(mods);
2557 }
2558 return toP(F.Exec(syntaxError(pos, errs, "expected3",
2559 CLASS, INTERFACE, ENUM)));
2560 }
2561 } else {
2562 if (S.token() == ENUM) {
2563 log.error(S.pos(), "enums.not.supported.in.source", source.name);
2564 allowEnums = true;
2565 return enumDeclaration(mods, dc);
2566 }
2567 int pos = S.pos();
2568 List<JCTree> errs;
2569 if (S.token() == IDENTIFIER) {
2570 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2571 setErrorEndPos(S.pos());
2572 } else {
2573 errs = List.<JCTree>of(mods);
2574 }
2575 return toP(F.Exec(syntaxError(pos, errs, "expected2",
2576 CLASS, INTERFACE)));
2577 }
2578 }
2580 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2581 * [IMPLEMENTS TypeList] ClassBody
2582 * @param mods The modifiers starting the class declaration
2583 * @param dc The documentation comment for the class, or null.
2584 */
2585 JCClassDecl classDeclaration(JCModifiers mods, String dc) {
2586 int pos = S.pos();
2587 accept(CLASS);
2588 Name name = ident();
2590 List<JCTypeParameter> typarams = typeParametersOpt();
2592 JCTree extending = null;
2593 if (S.token() == EXTENDS) {
2594 S.nextToken();
2595 extending = parseType();
2596 }
2597 List<JCExpression> implementing = List.nil();
2598 if (S.token() == IMPLEMENTS) {
2599 S.nextToken();
2600 implementing = typeList();
2601 }
2602 List<JCTree> defs = classOrInterfaceBody(name, false);
2603 JCClassDecl result = toP(F.at(pos).ClassDef(
2604 mods, name, typarams, extending, implementing, defs));
2605 attach(result, dc);
2606 return result;
2607 }
2609 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2610 * [EXTENDS TypeList] InterfaceBody
2611 * @param mods The modifiers starting the interface declaration
2612 * @param dc The documentation comment for the interface, or null.
2613 */
2614 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
2615 int pos = S.pos();
2616 accept(INTERFACE);
2617 Name name = ident();
2619 List<JCTypeParameter> typarams = typeParametersOpt();
2621 List<JCExpression> extending = List.nil();
2622 if (S.token() == EXTENDS) {
2623 S.nextToken();
2624 extending = typeList();
2625 }
2626 List<JCTree> defs = classOrInterfaceBody(name, true);
2627 JCClassDecl result = toP(F.at(pos).ClassDef(
2628 mods, name, typarams, null, extending, defs));
2629 attach(result, dc);
2630 return result;
2631 }
2633 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2634 * @param mods The modifiers starting the enum declaration
2635 * @param dc The documentation comment for the enum, or null.
2636 */
2637 JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
2638 int pos = S.pos();
2639 accept(ENUM);
2640 Name name = ident();
2642 List<JCExpression> implementing = List.nil();
2643 if (S.token() == IMPLEMENTS) {
2644 S.nextToken();
2645 implementing = typeList();
2646 }
2648 List<JCTree> defs = enumBody(name);
2649 mods.flags |= Flags.ENUM;
2650 JCClassDecl result = toP(F.at(pos).
2651 ClassDef(mods, name, List.<JCTypeParameter>nil(),
2652 null, implementing, defs));
2653 attach(result, dc);
2654 return result;
2655 }
2657 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2658 * [ ";" {ClassBodyDeclaration} ] "}"
2659 */
2660 List<JCTree> enumBody(Name enumName) {
2661 accept(LBRACE);
2662 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2663 if (S.token() == COMMA) {
2664 S.nextToken();
2665 } else if (S.token() != RBRACE && S.token() != SEMI) {
2666 defs.append(enumeratorDeclaration(enumName));
2667 while (S.token() == COMMA) {
2668 S.nextToken();
2669 if (S.token() == RBRACE || S.token() == SEMI) break;
2670 defs.append(enumeratorDeclaration(enumName));
2671 }
2672 if (S.token() != SEMI && S.token() != RBRACE) {
2673 defs.append(syntaxError(S.pos(), "expected3",
2674 COMMA, RBRACE, SEMI));
2675 S.nextToken();
2676 }
2677 }
2678 if (S.token() == SEMI) {
2679 S.nextToken();
2680 while (S.token() != RBRACE && S.token() != EOF) {
2681 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2682 false));
2683 if (S.pos() <= errorEndPos) {
2684 // error recovery
2685 skip(false, true, true, false);
2686 }
2687 }
2688 }
2689 accept(RBRACE);
2690 return defs.toList();
2691 }
2693 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2694 */
2695 JCTree enumeratorDeclaration(Name enumName) {
2696 String dc = S.docComment();
2697 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2698 if (S.deprecatedFlag()) {
2699 flags |= Flags.DEPRECATED;
2700 S.resetDeprecatedFlag();
2701 }
2702 int pos = S.pos();
2703 List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
2704 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2705 List<JCExpression> typeArgs = typeArgumentsOpt();
2706 int identPos = S.pos();
2707 Name name = ident();
2708 int createPos = S.pos();
2709 List<JCExpression> args = (S.token() == LPAREN)
2710 ? arguments() : List.<JCExpression>nil();
2711 JCClassDecl body = null;
2712 if (S.token() == LBRACE) {
2713 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2714 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2715 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2716 }
2717 if (args.isEmpty() && body == null)
2718 createPos = identPos;
2719 JCIdent ident = F.at(identPos).Ident(enumName);
2720 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2721 if (createPos != identPos)
2722 storeEnd(create, S.prevEndPos());
2723 ident = F.at(identPos).Ident(enumName);
2724 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2725 attach(result, dc);
2726 return result;
2727 }
2729 /** TypeList = Type {"," Type}
2730 */
2731 List<JCExpression> typeList() {
2732 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2733 ts.append(parseType());
2734 while (S.token() == COMMA) {
2735 S.nextToken();
2736 ts.append(parseType());
2737 }
2738 return ts.toList();
2739 }
2741 /** ClassBody = "{" {ClassBodyDeclaration} "}"
2742 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2743 */
2744 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2745 accept(LBRACE);
2746 if (S.pos() <= errorEndPos) {
2747 // error recovery
2748 skip(false, true, false, false);
2749 if (S.token() == LBRACE)
2750 S.nextToken();
2751 }
2752 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2753 while (S.token() != RBRACE && S.token() != EOF) {
2754 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2755 if (S.pos() <= errorEndPos) {
2756 // error recovery
2757 skip(false, true, true, false);
2758 }
2759 }
2760 accept(RBRACE);
2761 return defs.toList();
2762 }
2764 /** ClassBodyDeclaration =
2765 * ";"
2766 * | [STATIC] Block
2767 * | ModifiersOpt
2768 * ( Type Ident
2769 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2770 * | VOID Ident MethodDeclaratorRest
2771 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2772 * | Ident ConstructorDeclaratorRest
2773 * | TypeParameters Ident ConstructorDeclaratorRest
2774 * | ClassOrInterfaceOrEnumDeclaration
2775 * )
2776 * InterfaceBodyDeclaration =
2777 * ";"
2778 * | ModifiersOpt Type Ident
2779 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2780 */
2781 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2782 if (S.token() == SEMI) {
2783 S.nextToken();
2784 return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
2785 } else {
2786 String dc = S.docComment();
2787 int pos = S.pos();
2788 JCModifiers mods = modifiersOpt();
2789 if (S.token() == CLASS ||
2790 S.token() == INTERFACE ||
2791 allowEnums && S.token() == ENUM) {
2792 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2793 } else if (S.token() == LBRACE && !isInterface &&
2794 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2795 mods.annotations.isEmpty()) {
2796 return List.<JCTree>of(block(pos, mods.flags));
2797 } else {
2798 pos = S.pos();
2799 List<JCTypeParameter> typarams = typeParametersOpt();
2800 List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
2802 Name name = S.name();
2803 pos = S.pos();
2804 JCExpression type;
2805 boolean isVoid = S.token() == VOID;
2806 if (isVoid) {
2807 if (annosAfterParams.nonEmpty())
2808 illegal(annosAfterParams.head.pos);
2809 type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2810 S.nextToken();
2811 } else {
2812 if (annosAfterParams.nonEmpty()) {
2813 mods.annotations = mods.annotations.appendList(annosAfterParams);
2814 if (mods.pos == Position.NOPOS)
2815 mods.pos = mods.annotations.head.pos;
2816 }
2817 // method returns types are un-annotated types
2818 type = unannotatedType();
2819 }
2820 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
2821 if (isInterface || name != className)
2822 log.error(pos, "invalid.meth.decl.ret.type.req");
2823 return List.of(methodDeclaratorRest(
2824 pos, mods, null, names.init, typarams,
2825 isInterface, true, dc));
2826 } else {
2827 pos = S.pos();
2828 name = ident();
2829 if (S.token() == LPAREN) {
2830 return List.of(methodDeclaratorRest(
2831 pos, mods, type, name, typarams,
2832 isInterface, isVoid, dc));
2833 } else if (!isVoid && typarams.isEmpty()) {
2834 List<JCTree> defs =
2835 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2836 new ListBuffer<JCTree>()).toList();
2837 storeEnd(defs.last(), S.endPos());
2838 accept(SEMI);
2839 return defs;
2840 } else {
2841 pos = S.pos();
2842 List<JCTree> err = isVoid
2843 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2844 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2845 : null;
2846 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
2847 }
2848 }
2849 }
2850 }
2851 }
2853 /** MethodDeclaratorRest =
2854 * FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2855 * VoidMethodDeclaratorRest =
2856 * FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";")
2857 * InterfaceMethodDeclaratorRest =
2858 * FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";"
2859 * VoidInterfaceMethodDeclaratorRest =
2860 * FormalParameters [Annotations] [THROWS TypeList] ";"
2861 * ConstructorDeclaratorRest =
2862 * "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody
2863 */
2864 JCTree methodDeclaratorRest(int pos,
2865 JCModifiers mods,
2866 JCExpression type,
2867 Name name,
2868 List<JCTypeParameter> typarams,
2869 boolean isInterface, boolean isVoid,
2870 String dc) {
2871 List<JCVariableDecl> params = formalParameters();
2873 List<JCTypeAnnotation> receiverAnnotations;
2874 if (!isVoid) {
2875 // need to distinguish between receiver anno and array anno
2876 // look at typeAnnotationsPushedBack comment
2877 this.permitTypeAnnotationsPushBack = true;
2878 type = methodReturnArrayRest(type);
2879 this.permitTypeAnnotationsPushBack = false;
2880 if (typeAnnotationsPushedBack == null)
2881 receiverAnnotations = List.nil();
2882 else
2883 receiverAnnotations = typeAnnotationsPushedBack;
2884 typeAnnotationsPushedBack = null;
2885 } else
2886 receiverAnnotations = typeAnnotationsOpt();
2888 List<JCExpression> thrown = List.nil();
2889 if (S.token() == THROWS) {
2890 S.nextToken();
2891 thrown = qualidentList();
2892 }
2893 JCBlock body = null;
2894 JCExpression defaultValue;
2895 if (S.token() == LBRACE) {
2896 body = block();
2897 defaultValue = null;
2898 } else {
2899 if (S.token() == DEFAULT) {
2900 accept(DEFAULT);
2901 defaultValue = annotationValue();
2902 } else {
2903 defaultValue = null;
2904 }
2905 accept(SEMI);
2906 if (S.pos() <= errorEndPos) {
2907 // error recovery
2908 skip(false, true, false, false);
2909 if (S.token() == LBRACE) {
2910 body = block();
2911 }
2912 }
2913 }
2915 JCMethodDecl result =
2916 toP(F.at(pos).MethodDef(mods, name, type, typarams,
2917 params, receiverAnnotations, thrown,
2918 body, defaultValue));
2919 attach(result, dc);
2920 return result;
2921 }
2923 /** Parses the array levels after the format parameters list, and append
2924 * them to the return type, while preseving the order of type annotations
2925 */
2926 private JCExpression methodReturnArrayRest(JCExpression type) {
2927 if (type.getTag() != JCTree.TYPEARRAY)
2928 return bracketsOpt(type);
2930 JCArrayTypeTree baseArray = (JCArrayTypeTree)type;
2931 while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree)
2932 baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype);
2934 if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
2935 JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype;
2936 at.underlyingType = bracketsOpt(at.underlyingType);
2937 } else {
2938 baseArray.elemtype = bracketsOpt(baseArray.elemtype);
2939 }
2941 return type;
2942 }
2944 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
2945 */
2946 List<JCExpression> qualidentList() {
2947 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2949 List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
2950 if (!typeAnnos.isEmpty())
2951 ts.append(F.AnnotatedType(typeAnnos, qualident()));
2952 else
2953 ts.append(qualident());
2954 while (S.token() == COMMA) {
2955 S.nextToken();
2957 typeAnnos = typeAnnotationsOpt();
2958 if (!typeAnnos.isEmpty())
2959 ts.append(F.AnnotatedType(typeAnnos, qualident()));
2960 else
2961 ts.append(qualident());
2962 }
2963 return ts.toList();
2964 }
2966 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2967 */
2968 List<JCTypeParameter> typeParametersOpt() {
2969 if (S.token() == LT) {
2970 checkGenerics();
2971 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
2972 S.nextToken();
2973 typarams.append(typeParameter());
2974 while (S.token() == COMMA) {
2975 S.nextToken();
2976 typarams.append(typeParameter());
2977 }
2978 accept(GT);
2979 return typarams.toList();
2980 } else {
2981 return List.nil();
2982 }
2983 }
2985 /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
2986 * TypeParameterBound = EXTENDS Type {"&" Type}
2987 * TypeVariable = Ident
2988 */
2989 JCTypeParameter typeParameter() {
2990 int pos = S.pos();
2991 List<JCTypeAnnotation> annos = typeAnnotationsOpt();
2992 Name name = ident();
2993 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
2994 if (S.token() == EXTENDS) {
2995 S.nextToken();
2996 bounds.append(parseType());
2997 while (S.token() == AMP) {
2998 S.nextToken();
2999 bounds.append(parseType());
3000 }
3001 }
3002 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
3003 }
3005 /** FormalParameters = "(" [ FormalParameterList ] ")"
3006 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
3007 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
3008 */
3009 List<JCVariableDecl> formalParameters() {
3010 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3011 JCVariableDecl lastParam = null;
3012 accept(LPAREN);
3013 if (S.token() != RPAREN) {
3014 params.append(lastParam = formalParameter());
3015 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
3016 S.nextToken();
3017 params.append(lastParam = formalParameter());
3018 }
3019 }
3020 accept(RPAREN);
3021 return params.toList();
3022 }
3024 JCModifiers optFinal(long flags) {
3025 JCModifiers mods = modifiersOpt();
3026 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
3027 mods.flags |= flags;
3028 return mods;
3029 }
3031 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
3032 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
3033 */
3034 JCVariableDecl formalParameter() {
3035 JCModifiers mods = optFinal(Flags.PARAMETER);
3036 // need to distinguish between vararg annos and array annos
3037 // look at typeAnnotaitonsPushedBack comment
3038 this.permitTypeAnnotationsPushBack = true;
3039 JCExpression type = parseType();
3040 this.permitTypeAnnotationsPushBack = false;
3042 if (S.token() == ELLIPSIS) {
3043 List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack;
3044 typeAnnotationsPushedBack = null;
3045 checkVarargs();
3046 mods.flags |= Flags.VARARGS;
3047 // insert var arg type annotations
3048 if (varargsAnnos != null && varargsAnnos.nonEmpty())
3049 type = F.at(S.pos()).AnnotatedType(varargsAnnos, type);
3050 type = to(F.at(S.pos()).TypeArray(type));
3052 S.nextToken();
3053 } else {
3054 // if not a var arg, then typeAnnotationsPushedBack should be null
3055 if (typeAnnotationsPushedBack != null
3056 && !typeAnnotationsPushedBack.isEmpty()) {
3057 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
3058 "illegal.start.of.type");
3059 }
3060 typeAnnotationsPushedBack = null;
3061 }
3062 return variableDeclaratorId(mods, type);
3063 }
3065 /* ---------- auxiliary methods -------------- */
3067 /** Check that given tree is a legal expression statement.
3068 */
3069 protected JCExpression checkExprStat(JCExpression t) {
3070 switch(t.getTag()) {
3071 case JCTree.PREINC: case JCTree.PREDEC:
3072 case JCTree.POSTINC: case JCTree.POSTDEC:
3073 case JCTree.ASSIGN:
3074 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
3075 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
3076 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
3077 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
3078 case JCTree.APPLY: case JCTree.NEWCLASS:
3079 case JCTree.ERRONEOUS:
3080 return t;
3081 default:
3082 log.error(t.pos, "not.stmt");
3083 return F.at(t.pos).Erroneous(List.<JCTree>of(t));
3084 }
3085 }
3087 /** Return precedence of operator represented by token,
3088 * -1 if token is not a binary operator. @see TreeInfo.opPrec
3089 */
3090 static int prec(Token token) {
3091 int oc = optag(token);
3092 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
3093 }
3095 /**
3096 * Return the lesser of two positions, making allowance for either one
3097 * being unset.
3098 */
3099 static int earlier(int pos1, int pos2) {
3100 if (pos1 == Position.NOPOS)
3101 return pos2;
3102 if (pos2 == Position.NOPOS)
3103 return pos1;
3104 return (pos1 < pos2 ? pos1 : pos2);
3105 }
3107 /** Return operation tag of binary operator represented by token,
3108 * -1 if token is not a binary operator.
3109 */
3110 static int optag(Token token) {
3111 switch (token) {
3112 case BARBAR:
3113 return JCTree.OR;
3114 case AMPAMP:
3115 return JCTree.AND;
3116 case BAR:
3117 return JCTree.BITOR;
3118 case BAREQ:
3119 return JCTree.BITOR_ASG;
3120 case CARET:
3121 return JCTree.BITXOR;
3122 case CARETEQ:
3123 return JCTree.BITXOR_ASG;
3124 case AMP:
3125 return JCTree.BITAND;
3126 case AMPEQ:
3127 return JCTree.BITAND_ASG;
3128 case EQEQ:
3129 return JCTree.EQ;
3130 case BANGEQ:
3131 return JCTree.NE;
3132 case LT:
3133 return JCTree.LT;
3134 case GT:
3135 return JCTree.GT;
3136 case LTEQ:
3137 return JCTree.LE;
3138 case GTEQ:
3139 return JCTree.GE;
3140 case LTLT:
3141 return JCTree.SL;
3142 case LTLTEQ:
3143 return JCTree.SL_ASG;
3144 case GTGT:
3145 return JCTree.SR;
3146 case GTGTEQ:
3147 return JCTree.SR_ASG;
3148 case GTGTGT:
3149 return JCTree.USR;
3150 case GTGTGTEQ:
3151 return JCTree.USR_ASG;
3152 case PLUS:
3153 return JCTree.PLUS;
3154 case PLUSEQ:
3155 return JCTree.PLUS_ASG;
3156 case SUB:
3157 return JCTree.MINUS;
3158 case SUBEQ:
3159 return JCTree.MINUS_ASG;
3160 case STAR:
3161 return JCTree.MUL;
3162 case STAREQ:
3163 return JCTree.MUL_ASG;
3164 case SLASH:
3165 return JCTree.DIV;
3166 case SLASHEQ:
3167 return JCTree.DIV_ASG;
3168 case PERCENT:
3169 return JCTree.MOD;
3170 case PERCENTEQ:
3171 return JCTree.MOD_ASG;
3172 case INSTANCEOF:
3173 return JCTree.TYPETEST;
3174 default:
3175 return -1;
3176 }
3177 }
3179 /** Return operation tag of unary operator represented by token,
3180 * -1 if token is not a binary operator.
3181 */
3182 static int unoptag(Token token) {
3183 switch (token) {
3184 case PLUS:
3185 return JCTree.POS;
3186 case SUB:
3187 return JCTree.NEG;
3188 case BANG:
3189 return JCTree.NOT;
3190 case TILDE:
3191 return JCTree.COMPL;
3192 case PLUSPLUS:
3193 return JCTree.PREINC;
3194 case SUBSUB:
3195 return JCTree.PREDEC;
3196 default:
3197 return -1;
3198 }
3199 }
3201 /** Return type tag of basic type represented by token,
3202 * -1 if token is not a basic type identifier.
3203 */
3204 static int typetag(Token token) {
3205 switch (token) {
3206 case BYTE:
3207 return TypeTags.BYTE;
3208 case CHAR:
3209 return TypeTags.CHAR;
3210 case SHORT:
3211 return TypeTags.SHORT;
3212 case INT:
3213 return TypeTags.INT;
3214 case LONG:
3215 return TypeTags.LONG;
3216 case FLOAT:
3217 return TypeTags.FLOAT;
3218 case DOUBLE:
3219 return TypeTags.DOUBLE;
3220 case BOOLEAN:
3221 return TypeTags.BOOLEAN;
3222 default:
3223 return -1;
3224 }
3225 }
3227 void checkGenerics() {
3228 if (!allowGenerics) {
3229 log.error(S.pos(), "generics.not.supported.in.source", source.name);
3230 allowGenerics = true;
3231 }
3232 }
3233 void checkVarargs() {
3234 if (!allowVarargs) {
3235 log.error(S.pos(), "varargs.not.supported.in.source", source.name);
3236 allowVarargs = true;
3237 }
3238 }
3239 void checkForeach() {
3240 if (!allowForeach) {
3241 log.error(S.pos(), "foreach.not.supported.in.source", source.name);
3242 allowForeach = true;
3243 }
3244 }
3245 void checkStaticImports() {
3246 if (!allowStaticImport) {
3247 log.error(S.pos(), "static.import.not.supported.in.source", source.name);
3248 allowStaticImport = true;
3249 }
3250 }
3251 void checkAnnotations() {
3252 if (!allowAnnotations) {
3253 log.error(S.pos(), "annotations.not.supported.in.source", source.name);
3254 allowAnnotations = true;
3255 }
3256 }
3257 void checkTypeAnnotations() {
3258 if (!allowTypeAnnotations) {
3259 log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
3260 allowTypeAnnotations = true;
3261 }
3262 }
3263 void checkDiamond() {
3264 if (!allowDiamond) {
3265 log.error(S.pos(), "diamond.not.supported.in.source", source.name);
3266 allowDiamond = true;
3267 }
3268 }
3269 void checkMulticatch() {
3270 if (!allowMulticatch) {
3271 log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
3272 allowMulticatch = true;
3273 }
3274 }
3275 void checkAutomaticResourceManagement() {
3276 if (!allowTWR) {
3277 log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
3278 allowTWR = true;
3279 }
3280 }
3281 }