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