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