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