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