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