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