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