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