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