Wed, 20 May 2009 13:36:23 -0700
6827026: Change javac source and target default to 7
Reviewed-by: darcy, ohair
1 /*
2 * Copyright 1999-2009 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 while (S.token() == DOT) {
867 S.nextToken();
868 mode = TYPE;
869 t = toP(F.at(S.pos()).Select(t, ident()));
870 t = typeArgumentsOpt(t);
871 }
872 t = bracketsOpt(toP(t));
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 // Support the corner case of myMethodHandle.<void>invoke() by passing
1038 // a void type (like other primitive types) to the next phase.
1039 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1040 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
1041 S.nextToken();
1042 return ti;
1043 //return illegal();
1044 }
1045 break;
1046 default:
1047 return illegal();
1048 }
1049 if (typeArgs != null) illegal();
1050 while (true) {
1051 int pos1 = S.pos();
1052 if (S.token() == LBRACKET) {
1053 S.nextToken();
1054 if ((mode & TYPE) != 0) {
1055 int oldmode = mode;
1056 mode = TYPE;
1057 if (S.token() == RBRACKET) {
1058 S.nextToken();
1059 t = bracketsOpt(t);
1060 t = toP(F.at(pos1).TypeArray(t));
1061 return t;
1062 }
1063 mode = oldmode;
1064 }
1065 if ((mode & EXPR) != 0) {
1066 mode = EXPR;
1067 JCExpression t1 = term();
1068 t = to(F.at(pos1).Indexed(t, t1));
1069 }
1070 accept(RBRACKET);
1071 } else if (S.token() == DOT) {
1072 S.nextToken();
1073 typeArgs = typeArgumentsOpt(EXPR);
1074 if (S.token() == SUPER && (mode & EXPR) != 0) {
1075 mode = EXPR;
1076 t = to(F.at(pos1).Select(t, names._super));
1077 S.nextToken();
1078 t = arguments(typeArgs, t);
1079 typeArgs = null;
1080 } else if (S.token() == NEW && (mode & EXPR) != 0) {
1081 if (typeArgs != null) return illegal();
1082 mode = EXPR;
1083 int pos2 = S.pos();
1084 S.nextToken();
1085 if (S.token() == LT) typeArgs = typeArguments();
1086 t = innerCreator(pos2, typeArgs, t);
1087 typeArgs = null;
1088 } else {
1089 t = toP(F.at(pos1).Select(t, ident()));
1090 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1091 typeArgs = null;
1092 }
1093 } else {
1094 break;
1095 }
1096 }
1097 while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
1098 mode = EXPR;
1099 t = to(F.at(S.pos()).Unary(
1100 S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
1101 S.nextToken();
1102 }
1103 return toP(t);
1104 }
1106 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1107 */
1108 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1109 S.nextToken();
1110 if (S.token() == LPAREN || typeArgs != null) {
1111 t = arguments(typeArgs, t);
1112 } else {
1113 int pos = S.pos();
1114 accept(DOT);
1115 typeArgs = (S.token() == LT) ? typeArguments() : null;
1116 t = toP(F.at(pos).Select(t, ident()));
1117 t = argumentsOpt(typeArgs, t);
1118 }
1119 return t;
1120 }
1122 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1123 */
1124 JCPrimitiveTypeTree basicType() {
1125 JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
1126 S.nextToken();
1127 return t;
1128 }
1130 /** ArgumentsOpt = [ Arguments ]
1131 */
1132 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1133 if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
1134 mode = EXPR;
1135 return arguments(typeArgs, t);
1136 } else {
1137 return t;
1138 }
1139 }
1141 /** Arguments = "(" [Expression { COMMA Expression }] ")"
1142 */
1143 List<JCExpression> arguments() {
1144 ListBuffer<JCExpression> args = lb();
1145 if (S.token() == LPAREN) {
1146 S.nextToken();
1147 if (S.token() != RPAREN) {
1148 args.append(parseExpression());
1149 while (S.token() == COMMA) {
1150 S.nextToken();
1151 args.append(parseExpression());
1152 }
1153 }
1154 accept(RPAREN);
1155 } else {
1156 syntaxError(S.pos(), "expected", LPAREN);
1157 }
1158 return args.toList();
1159 }
1161 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1162 int pos = S.pos();
1163 List<JCExpression> args = arguments();
1164 return toP(F.at(pos).Apply(typeArgs, t, args));
1165 }
1167 /** TypeArgumentsOpt = [ TypeArguments ]
1168 */
1169 JCExpression typeArgumentsOpt(JCExpression t) {
1170 if (S.token() == LT &&
1171 (mode & TYPE) != 0 &&
1172 (mode & NOPARAMS) == 0) {
1173 mode = TYPE;
1174 checkGenerics();
1175 return typeArguments(t);
1176 } else {
1177 return t;
1178 }
1179 }
1180 List<JCExpression> typeArgumentsOpt() {
1181 return typeArgumentsOpt(TYPE);
1182 }
1184 List<JCExpression> typeArgumentsOpt(int useMode) {
1185 if (S.token() == LT) {
1186 checkGenerics();
1187 if ((mode & useMode) == 0 ||
1188 (mode & NOPARAMS) != 0) {
1189 illegal();
1190 }
1191 mode = useMode;
1192 return typeArguments();
1193 }
1194 return null;
1195 }
1197 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1198 */
1199 List<JCExpression> typeArguments() {
1200 ListBuffer<JCExpression> args = lb();
1201 if (S.token() == LT) {
1202 S.nextToken();
1203 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1204 while (S.token() == COMMA) {
1205 S.nextToken();
1206 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1207 }
1208 switch (S.token()) {
1209 case GTGTGTEQ:
1210 S.token(GTGTEQ);
1211 break;
1212 case GTGTEQ:
1213 S.token(GTEQ);
1214 break;
1215 case GTEQ:
1216 S.token(EQ);
1217 break;
1218 case GTGTGT:
1219 S.token(GTGT);
1220 break;
1221 case GTGT:
1222 S.token(GT);
1223 break;
1224 default:
1225 accept(GT);
1226 break;
1227 }
1228 } else {
1229 syntaxError(S.pos(), "expected", LT);
1230 }
1231 return args.toList();
1232 }
1234 /** TypeArgument = Type
1235 * | "?"
1236 * | "?" EXTENDS Type {"&" Type}
1237 * | "?" SUPER Type
1238 */
1239 JCExpression typeArgument() {
1240 if (S.token() != QUES) return parseType();
1241 int pos = S.pos();
1242 S.nextToken();
1243 if (S.token() == EXTENDS) {
1244 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
1245 S.nextToken();
1246 return F.at(pos).Wildcard(t, parseType());
1247 } else if (S.token() == SUPER) {
1248 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
1249 S.nextToken();
1250 return F.at(pos).Wildcard(t, parseType());
1251 } else if (S.token() == IDENTIFIER) {
1252 //error recovery
1253 reportSyntaxError(S.prevEndPos(), "expected3",
1254 GT, EXTENDS, SUPER);
1255 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1256 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1257 JCIdent id = toP(F.at(S.pos()).Ident(ident()));
1258 return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1259 } else {
1260 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1261 return toP(F.at(pos).Wildcard(t, null));
1262 }
1263 }
1265 JCTypeApply typeArguments(JCExpression t) {
1266 int pos = S.pos();
1267 List<JCExpression> args = typeArguments();
1268 return toP(F.at(pos).TypeApply(t, args));
1269 }
1271 /** BracketsOpt = {"[" "]"}
1272 */
1273 private JCExpression bracketsOpt(JCExpression t) {
1274 if (S.token() == LBRACKET) {
1275 int pos = S.pos();
1276 S.nextToken();
1277 t = bracketsOptCont(t, pos);
1278 F.at(pos);
1279 }
1280 return t;
1281 }
1283 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1284 accept(RBRACKET);
1285 t = bracketsOpt(t);
1286 return toP(F.at(pos).TypeArray(t));
1287 }
1289 /** BracketsSuffixExpr = "." CLASS
1290 * BracketsSuffixType =
1291 */
1292 JCExpression bracketsSuffix(JCExpression t) {
1293 if ((mode & EXPR) != 0 && S.token() == DOT) {
1294 mode = EXPR;
1295 int pos = S.pos();
1296 S.nextToken();
1297 accept(CLASS);
1298 if (S.pos() == errorEndPos) {
1299 // error recovery
1300 Name name = null;
1301 if (S.token() == IDENTIFIER) {
1302 name = S.name();
1303 S.nextToken();
1304 } else {
1305 name = names.error;
1306 }
1307 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1308 } else {
1309 t = toP(F.at(pos).Select(t, names._class));
1310 }
1311 } else if ((mode & TYPE) != 0) {
1312 mode = TYPE;
1313 } else {
1314 syntaxError(S.pos(), "dot.class.expected");
1315 }
1316 return t;
1317 }
1319 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1320 */
1321 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1322 switch (S.token()) {
1323 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1324 case DOUBLE: case BOOLEAN:
1325 if (typeArgs == null)
1326 return arrayCreatorRest(newpos, basicType());
1327 break;
1328 default:
1329 }
1330 JCExpression t = qualident();
1331 int oldmode = mode;
1332 mode = TYPE;
1333 if (S.token() == LT) {
1334 checkGenerics();
1335 t = typeArguments(t);
1336 }
1337 while (S.token() == DOT) {
1338 int pos = S.pos();
1339 S.nextToken();
1340 t = toP(F.at(pos).Select(t, ident()));
1341 if (S.token() == LT) {
1342 checkGenerics();
1343 t = typeArguments(t);
1344 }
1345 }
1346 mode = oldmode;
1347 if (S.token() == LBRACKET) {
1348 JCExpression e = arrayCreatorRest(newpos, t);
1349 if (typeArgs != null) {
1350 int pos = newpos;
1351 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1352 // note: this should always happen but we should
1353 // not rely on this as the parser is continuously
1354 // modified to improve error recovery.
1355 pos = typeArgs.head.pos;
1356 }
1357 setErrorEndPos(S.prevEndPos());
1358 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
1359 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
1360 }
1361 return e;
1362 } else if (S.token() == LPAREN) {
1363 return classCreatorRest(newpos, null, typeArgs, t);
1364 } else {
1365 reportSyntaxError(S.pos(), "expected2",
1366 LPAREN, LBRACKET);
1367 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1368 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1369 }
1370 }
1372 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1373 */
1374 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1375 JCExpression t = toP(F.at(S.pos()).Ident(ident()));
1376 if (S.token() == LT) {
1377 checkGenerics();
1378 t = typeArguments(t);
1379 }
1380 return classCreatorRest(newpos, encl, typeArgs, t);
1381 }
1383 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1384 * | Expression "]" {"[" Expression "]"} BracketsOpt )
1385 */
1386 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1387 accept(LBRACKET);
1388 if (S.token() == RBRACKET) {
1389 accept(RBRACKET);
1390 elemtype = bracketsOpt(elemtype);
1391 if (S.token() == LBRACE) {
1392 return arrayInitializer(newpos, elemtype);
1393 } else {
1394 return syntaxError(S.pos(), "array.dimension.missing");
1395 }
1396 } else {
1397 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1398 dims.append(parseExpression());
1399 accept(RBRACKET);
1400 while (S.token() == LBRACKET) {
1401 int pos = S.pos();
1402 S.nextToken();
1403 if (S.token() == RBRACKET) {
1404 elemtype = bracketsOptCont(elemtype, pos);
1405 } else {
1406 dims.append(parseExpression());
1407 accept(RBRACKET);
1408 }
1409 }
1410 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1411 }
1412 }
1414 /** ClassCreatorRest = Arguments [ClassBody]
1415 */
1416 JCExpression classCreatorRest(int newpos,
1417 JCExpression encl,
1418 List<JCExpression> typeArgs,
1419 JCExpression t)
1420 {
1421 List<JCExpression> args = arguments();
1422 JCClassDecl body = null;
1423 if (S.token() == LBRACE) {
1424 int pos = S.pos();
1425 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1426 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1427 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1428 }
1429 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1430 }
1432 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1433 */
1434 JCExpression arrayInitializer(int newpos, JCExpression t) {
1435 accept(LBRACE);
1436 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1437 if (S.token() == COMMA) {
1438 S.nextToken();
1439 } else if (S.token() != RBRACE) {
1440 elems.append(variableInitializer());
1441 while (S.token() == COMMA) {
1442 S.nextToken();
1443 if (S.token() == RBRACE) break;
1444 elems.append(variableInitializer());
1445 }
1446 }
1447 accept(RBRACE);
1448 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1449 }
1451 /** VariableInitializer = ArrayInitializer | Expression
1452 */
1453 public JCExpression variableInitializer() {
1454 return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
1455 }
1457 /** ParExpression = "(" Expression ")"
1458 */
1459 JCExpression parExpression() {
1460 accept(LPAREN);
1461 JCExpression t = parseExpression();
1462 accept(RPAREN);
1463 return t;
1464 }
1466 /** Block = "{" BlockStatements "}"
1467 */
1468 JCBlock block(int pos, long flags) {
1469 accept(LBRACE);
1470 List<JCStatement> stats = blockStatements();
1471 JCBlock t = F.at(pos).Block(flags, stats);
1472 while (S.token() == CASE || S.token() == DEFAULT) {
1473 syntaxError("orphaned", S.token());
1474 switchBlockStatementGroups();
1475 }
1476 // the Block node has a field "endpos" for first char of last token, which is
1477 // usually but not necessarily the last char of the last token.
1478 t.endpos = S.pos();
1479 accept(RBRACE);
1480 return toP(t);
1481 }
1483 public JCBlock block() {
1484 return block(S.pos(), 0);
1485 }
1487 /** BlockStatements = { BlockStatement }
1488 * BlockStatement = LocalVariableDeclarationStatement
1489 * | ClassOrInterfaceOrEnumDeclaration
1490 * | [Ident ":"] Statement
1491 * LocalVariableDeclarationStatement
1492 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1493 */
1494 @SuppressWarnings("fallthrough")
1495 List<JCStatement> blockStatements() {
1496 //todo: skip to anchor on error(?)
1497 int lastErrPos = -1;
1498 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1499 while (true) {
1500 int pos = S.pos();
1501 switch (S.token()) {
1502 case RBRACE: case CASE: case DEFAULT: case EOF:
1503 return stats.toList();
1504 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1505 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1506 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1507 stats.append(parseStatement());
1508 break;
1509 case MONKEYS_AT:
1510 case FINAL: {
1511 String dc = S.docComment();
1512 JCModifiers mods = modifiersOpt();
1513 if (S.token() == INTERFACE ||
1514 S.token() == CLASS ||
1515 allowEnums && S.token() == ENUM) {
1516 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1517 } else {
1518 JCExpression t = parseType();
1519 stats.appendList(variableDeclarators(mods, t,
1520 new ListBuffer<JCStatement>()));
1521 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1522 storeEnd(stats.elems.last(), S.endPos());
1523 accept(SEMI);
1524 }
1525 break;
1526 }
1527 case ABSTRACT: case STRICTFP: {
1528 String dc = S.docComment();
1529 JCModifiers mods = modifiersOpt();
1530 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1531 break;
1532 }
1533 case INTERFACE:
1534 case CLASS:
1535 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1536 S.docComment()));
1537 break;
1538 case ENUM:
1539 case ASSERT:
1540 if (allowEnums && S.token() == ENUM) {
1541 log.error(S.pos(), "local.enum");
1542 stats.
1543 append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1544 S.docComment()));
1545 break;
1546 } else if (allowAsserts && S.token() == ASSERT) {
1547 stats.append(parseStatement());
1548 break;
1549 }
1550 /* fall through to default */
1551 default:
1552 Name name = S.name();
1553 JCExpression t = term(EXPR | TYPE);
1554 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
1555 S.nextToken();
1556 JCStatement stat = parseStatement();
1557 stats.append(F.at(pos).Labelled(name, stat));
1558 } else if ((lastmode & TYPE) != 0 &&
1559 (S.token() == IDENTIFIER ||
1560 S.token() == ASSERT ||
1561 S.token() == ENUM)) {
1562 pos = S.pos();
1563 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1564 F.at(pos);
1565 stats.appendList(variableDeclarators(mods, t,
1566 new ListBuffer<JCStatement>()));
1567 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1568 storeEnd(stats.elems.last(), S.endPos());
1569 accept(SEMI);
1570 } else {
1571 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1572 stats.append(to(F.at(pos).Exec(checkExprStat(t))));
1573 accept(SEMI);
1574 }
1575 }
1577 // error recovery
1578 if (S.pos() == lastErrPos)
1579 return stats.toList();
1580 if (S.pos() <= errorEndPos) {
1581 skip(false, true, true, true);
1582 lastErrPos = S.pos();
1583 }
1585 // ensure no dangling /** @deprecated */ active
1586 S.resetDeprecatedFlag();
1587 }
1588 }
1590 /** Statement =
1591 * Block
1592 * | IF ParExpression Statement [ELSE Statement]
1593 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1594 * | FOR "(" FormalParameter : Expression ")" Statement
1595 * | WHILE ParExpression Statement
1596 * | DO Statement WHILE ParExpression ";"
1597 * | TRY Block ( Catches | [Catches] FinallyPart )
1598 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1599 * | SYNCHRONIZED ParExpression Block
1600 * | RETURN [Expression] ";"
1601 * | THROW Expression ";"
1602 * | BREAK [Ident] ";"
1603 * | CONTINUE [Ident] ";"
1604 * | ASSERT Expression [ ":" Expression ] ";"
1605 * | ";"
1606 * | ExpressionStatement
1607 * | Ident ":" Statement
1608 */
1609 @SuppressWarnings("fallthrough")
1610 public JCStatement parseStatement() {
1611 int pos = S.pos();
1612 switch (S.token()) {
1613 case LBRACE:
1614 return block();
1615 case IF: {
1616 S.nextToken();
1617 JCExpression cond = parExpression();
1618 JCStatement thenpart = parseStatement();
1619 JCStatement elsepart = null;
1620 if (S.token() == ELSE) {
1621 S.nextToken();
1622 elsepart = parseStatement();
1623 }
1624 return F.at(pos).If(cond, thenpart, elsepart);
1625 }
1626 case FOR: {
1627 S.nextToken();
1628 accept(LPAREN);
1629 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
1630 if (inits.length() == 1 &&
1631 inits.head.getTag() == JCTree.VARDEF &&
1632 ((JCVariableDecl) inits.head).init == null &&
1633 S.token() == COLON) {
1634 checkForeach();
1635 JCVariableDecl var = (JCVariableDecl)inits.head;
1636 accept(COLON);
1637 JCExpression expr = parseExpression();
1638 accept(RPAREN);
1639 JCStatement body = parseStatement();
1640 return F.at(pos).ForeachLoop(var, expr, body);
1641 } else {
1642 accept(SEMI);
1643 JCExpression cond = S.token() == SEMI ? null : parseExpression();
1644 accept(SEMI);
1645 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
1646 accept(RPAREN);
1647 JCStatement body = parseStatement();
1648 return F.at(pos).ForLoop(inits, cond, steps, body);
1649 }
1650 }
1651 case WHILE: {
1652 S.nextToken();
1653 JCExpression cond = parExpression();
1654 JCStatement body = parseStatement();
1655 return F.at(pos).WhileLoop(cond, body);
1656 }
1657 case DO: {
1658 S.nextToken();
1659 JCStatement body = parseStatement();
1660 accept(WHILE);
1661 JCExpression cond = parExpression();
1662 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
1663 accept(SEMI);
1664 return t;
1665 }
1666 case TRY: {
1667 S.nextToken();
1668 JCBlock body = block();
1669 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
1670 JCBlock finalizer = null;
1671 if (S.token() == CATCH || S.token() == FINALLY) {
1672 while (S.token() == CATCH) catchers.append(catchClause());
1673 if (S.token() == FINALLY) {
1674 S.nextToken();
1675 finalizer = block();
1676 }
1677 } else {
1678 log.error(pos, "try.without.catch.or.finally");
1679 }
1680 return F.at(pos).Try(body, catchers.toList(), finalizer);
1681 }
1682 case SWITCH: {
1683 S.nextToken();
1684 JCExpression selector = parExpression();
1685 accept(LBRACE);
1686 List<JCCase> cases = switchBlockStatementGroups();
1687 JCSwitch t = to(F.at(pos).Switch(selector, cases));
1688 accept(RBRACE);
1689 return t;
1690 }
1691 case SYNCHRONIZED: {
1692 S.nextToken();
1693 JCExpression lock = parExpression();
1694 JCBlock body = block();
1695 return F.at(pos).Synchronized(lock, body);
1696 }
1697 case RETURN: {
1698 S.nextToken();
1699 JCExpression result = S.token() == SEMI ? null : parseExpression();
1700 JCReturn t = to(F.at(pos).Return(result));
1701 accept(SEMI);
1702 return t;
1703 }
1704 case THROW: {
1705 S.nextToken();
1706 JCExpression exc = parseExpression();
1707 JCThrow t = to(F.at(pos).Throw(exc));
1708 accept(SEMI);
1709 return t;
1710 }
1711 case BREAK: {
1712 S.nextToken();
1713 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1714 JCBreak t = to(F.at(pos).Break(label));
1715 accept(SEMI);
1716 return t;
1717 }
1718 case CONTINUE: {
1719 S.nextToken();
1720 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1721 JCContinue t = to(F.at(pos).Continue(label));
1722 accept(SEMI);
1723 return t;
1724 }
1725 case SEMI:
1726 S.nextToken();
1727 return toP(F.at(pos).Skip());
1728 case ELSE:
1729 return toP(F.Exec(syntaxError("else.without.if")));
1730 case FINALLY:
1731 return toP(F.Exec(syntaxError("finally.without.try")));
1732 case CATCH:
1733 return toP(F.Exec(syntaxError("catch.without.try")));
1734 case ASSERT: {
1735 if (allowAsserts && S.token() == ASSERT) {
1736 S.nextToken();
1737 JCExpression assertion = parseExpression();
1738 JCExpression message = null;
1739 if (S.token() == COLON) {
1740 S.nextToken();
1741 message = parseExpression();
1742 }
1743 JCAssert t = to(F.at(pos).Assert(assertion, message));
1744 accept(SEMI);
1745 return t;
1746 }
1747 /* else fall through to default case */
1748 }
1749 case ENUM:
1750 default:
1751 Name name = S.name();
1752 JCExpression expr = parseExpression();
1753 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
1754 S.nextToken();
1755 JCStatement stat = parseStatement();
1756 return F.at(pos).Labelled(name, stat);
1757 } else {
1758 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1759 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
1760 accept(SEMI);
1761 return stat;
1762 }
1763 }
1764 }
1766 /** CatchClause = CATCH "(" FormalParameter ")" Block
1767 */
1768 JCCatch catchClause() {
1769 int pos = S.pos();
1770 accept(CATCH);
1771 accept(LPAREN);
1772 JCVariableDecl formal =
1773 variableDeclaratorId(optFinal(Flags.PARAMETER),
1774 qualident());
1775 accept(RPAREN);
1776 JCBlock body = block();
1777 return F.at(pos).Catch(formal, body);
1778 }
1780 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
1781 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
1782 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
1783 */
1784 List<JCCase> switchBlockStatementGroups() {
1785 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
1786 while (true) {
1787 int pos = S.pos();
1788 switch (S.token()) {
1789 case CASE: {
1790 S.nextToken();
1791 JCExpression pat = parseExpression();
1792 accept(COLON);
1793 List<JCStatement> stats = blockStatements();
1794 JCCase c = F.at(pos).Case(pat, stats);
1795 if (stats.isEmpty())
1796 storeEnd(c, S.prevEndPos());
1797 cases.append(c);
1798 break;
1799 }
1800 case DEFAULT: {
1801 S.nextToken();
1802 accept(COLON);
1803 List<JCStatement> stats = blockStatements();
1804 JCCase c = F.at(pos).Case(null, stats);
1805 if (stats.isEmpty())
1806 storeEnd(c, S.prevEndPos());
1807 cases.append(c);
1808 break;
1809 }
1810 case RBRACE: case EOF:
1811 return cases.toList();
1812 default:
1813 S.nextToken(); // to ensure progress
1814 syntaxError(pos, "expected3",
1815 CASE, DEFAULT, RBRACE);
1816 }
1817 }
1818 }
1820 /** MoreStatementExpressions = { COMMA StatementExpression }
1821 */
1822 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
1823 JCExpression first,
1824 T stats) {
1825 // This Exec is a "StatementExpression"; it subsumes no terminating token
1826 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
1827 while (S.token() == COMMA) {
1828 S.nextToken();
1829 pos = S.pos();
1830 JCExpression t = parseExpression();
1831 // This Exec is a "StatementExpression"; it subsumes no terminating token
1832 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
1833 }
1834 return stats;
1835 }
1837 /** ForInit = StatementExpression MoreStatementExpressions
1838 * | { FINAL | '@' Annotation } Type VariableDeclarators
1839 */
1840 List<JCStatement> forInit() {
1841 ListBuffer<JCStatement> stats = lb();
1842 int pos = S.pos();
1843 if (S.token() == FINAL || S.token() == MONKEYS_AT) {
1844 return variableDeclarators(optFinal(0), parseType(), stats).toList();
1845 } else {
1846 JCExpression t = term(EXPR | TYPE);
1847 if ((lastmode & TYPE) != 0 &&
1848 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
1849 return variableDeclarators(modifiersOpt(), t, stats).toList();
1850 else
1851 return moreStatementExpressions(pos, t, stats).toList();
1852 }
1853 }
1855 /** ForUpdate = StatementExpression MoreStatementExpressions
1856 */
1857 List<JCExpressionStatement> forUpdate() {
1858 return moreStatementExpressions(S.pos(),
1859 parseExpression(),
1860 new ListBuffer<JCExpressionStatement>()).toList();
1861 }
1863 /** AnnotationsOpt = { '@' Annotation }
1864 */
1865 List<JCAnnotation> annotationsOpt() {
1866 if (S.token() != MONKEYS_AT) return List.nil(); // optimization
1867 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
1868 while (S.token() == MONKEYS_AT) {
1869 int pos = S.pos();
1870 S.nextToken();
1871 buf.append(annotation(pos));
1872 }
1873 return buf.toList();
1874 }
1876 /** ModifiersOpt = { Modifier }
1877 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
1878 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
1879 * | "@" Annotation
1880 */
1881 JCModifiers modifiersOpt() {
1882 return modifiersOpt(null);
1883 }
1884 JCModifiers modifiersOpt(JCModifiers partial) {
1885 long flags = (partial == null) ? 0 : partial.flags;
1886 if (S.deprecatedFlag()) {
1887 flags |= Flags.DEPRECATED;
1888 S.resetDeprecatedFlag();
1889 }
1890 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
1891 if (partial != null) annotations.appendList(partial.annotations);
1892 int pos = S.pos();
1893 int lastPos = Position.NOPOS;
1894 loop:
1895 while (true) {
1896 long flag;
1897 switch (S.token()) {
1898 case PRIVATE : flag = Flags.PRIVATE; break;
1899 case PROTECTED : flag = Flags.PROTECTED; break;
1900 case PUBLIC : flag = Flags.PUBLIC; break;
1901 case STATIC : flag = Flags.STATIC; break;
1902 case TRANSIENT : flag = Flags.TRANSIENT; break;
1903 case FINAL : flag = Flags.FINAL; break;
1904 case ABSTRACT : flag = Flags.ABSTRACT; break;
1905 case NATIVE : flag = Flags.NATIVE; break;
1906 case VOLATILE : flag = Flags.VOLATILE; break;
1907 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
1908 case STRICTFP : flag = Flags.STRICTFP; break;
1909 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
1910 default: break loop;
1911 }
1912 if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
1913 lastPos = S.pos();
1914 S.nextToken();
1915 if (flag == Flags.ANNOTATION) {
1916 checkAnnotations();
1917 if (S.token() != INTERFACE) {
1918 JCAnnotation ann = annotation(lastPos);
1919 // if first modifier is an annotation, set pos to annotation's.
1920 if (flags == 0 && annotations.isEmpty())
1921 pos = ann.pos;
1922 annotations.append(ann);
1923 lastPos = ann.pos;
1924 flag = 0;
1925 }
1926 }
1927 flags |= flag;
1928 }
1929 switch (S.token()) {
1930 case ENUM: flags |= Flags.ENUM; break;
1931 case INTERFACE: flags |= Flags.INTERFACE; break;
1932 default: break;
1933 }
1935 /* A modifiers tree with no modifier tokens or annotations
1936 * has no text position. */
1937 if (flags == 0 && annotations.isEmpty())
1938 pos = Position.NOPOS;
1940 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
1941 if (pos != Position.NOPOS)
1942 storeEnd(mods, S.prevEndPos());
1943 return mods;
1944 }
1946 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
1947 * @param pos position of "@" token
1948 */
1949 JCAnnotation annotation(int pos) {
1950 // accept(AT); // AT consumed by caller
1951 checkAnnotations();
1952 JCTree ident = qualident();
1953 List<JCExpression> fieldValues = annotationFieldValuesOpt();
1954 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
1955 storeEnd(ann, S.prevEndPos());
1956 return ann;
1957 }
1959 List<JCExpression> annotationFieldValuesOpt() {
1960 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
1961 }
1963 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
1964 List<JCExpression> annotationFieldValues() {
1965 accept(LPAREN);
1966 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
1967 if (S.token() != RPAREN) {
1968 buf.append(annotationFieldValue());
1969 while (S.token() == COMMA) {
1970 S.nextToken();
1971 buf.append(annotationFieldValue());
1972 }
1973 }
1974 accept(RPAREN);
1975 return buf.toList();
1976 }
1978 /** AnnotationFieldValue = AnnotationValue
1979 * | Identifier "=" AnnotationValue
1980 */
1981 JCExpression annotationFieldValue() {
1982 if (S.token() == IDENTIFIER) {
1983 mode = EXPR;
1984 JCExpression t1 = term1();
1985 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
1986 int pos = S.pos();
1987 accept(EQ);
1988 return toP(F.at(pos).Assign(t1, annotationValue()));
1989 } else {
1990 return t1;
1991 }
1992 }
1993 return annotationValue();
1994 }
1996 /* AnnotationValue = ConditionalExpression
1997 * | Annotation
1998 * | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
1999 */
2000 JCExpression annotationValue() {
2001 int pos;
2002 switch (S.token()) {
2003 case MONKEYS_AT:
2004 pos = S.pos();
2005 S.nextToken();
2006 return annotation(pos);
2007 case LBRACE:
2008 pos = S.pos();
2009 accept(LBRACE);
2010 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2011 if (S.token() != RBRACE) {
2012 buf.append(annotationValue());
2013 while (S.token() == COMMA) {
2014 S.nextToken();
2015 if (S.token() == RPAREN) break;
2016 buf.append(annotationValue());
2017 }
2018 }
2019 accept(RBRACE);
2020 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2021 default:
2022 mode = EXPR;
2023 return term1();
2024 }
2025 }
2027 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2028 */
2029 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2030 JCExpression type,
2031 T vdefs)
2032 {
2033 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
2034 }
2036 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2037 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2038 *
2039 * @param reqInit Is an initializer always required?
2040 * @param dc The documentation comment for the variable declarations, or null.
2041 */
2042 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2043 JCModifiers mods,
2044 JCExpression type,
2045 Name name,
2046 boolean reqInit,
2047 String dc,
2048 T vdefs)
2049 {
2050 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2051 while (S.token() == COMMA) {
2052 // All but last of multiple declarators subsume a comma
2053 storeEnd((JCTree)vdefs.elems.last(), S.endPos());
2054 S.nextToken();
2055 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2056 }
2057 return vdefs;
2058 }
2060 /** VariableDeclarator = Ident VariableDeclaratorRest
2061 * ConstantDeclarator = Ident ConstantDeclaratorRest
2062 */
2063 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
2064 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
2065 }
2067 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2068 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2069 *
2070 * @param reqInit Is an initializer always required?
2071 * @param dc The documentation comment for the variable declarations, or null.
2072 */
2073 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2074 boolean reqInit, String dc) {
2075 type = bracketsOpt(type);
2076 JCExpression init = null;
2077 if (S.token() == EQ) {
2078 S.nextToken();
2079 init = variableInitializer();
2080 }
2081 else if (reqInit) syntaxError(S.pos(), "expected", EQ);
2082 JCVariableDecl result =
2083 toP(F.at(pos).VarDef(mods, name, type, init));
2084 attach(result, dc);
2085 return result;
2086 }
2088 /** VariableDeclaratorId = Ident BracketsOpt
2089 */
2090 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2091 int pos = S.pos();
2092 Name name = ident();
2093 if ((mods.flags & Flags.VARARGS) == 0)
2094 type = bracketsOpt(type);
2095 return toP(F.at(pos).VarDef(mods, name, type, null));
2096 }
2098 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2099 */
2100 public JCTree.JCCompilationUnit parseCompilationUnit() {
2101 int pos = S.pos();
2102 JCExpression pid = null;
2103 String dc = S.docComment();
2104 JCModifiers mods = null;
2105 List<JCAnnotation> packageAnnotations = List.nil();
2106 if (S.token() == MONKEYS_AT)
2107 mods = modifiersOpt();
2109 if (S.token() == PACKAGE) {
2110 if (mods != null) {
2111 checkNoMods(mods.flags);
2112 packageAnnotations = mods.annotations;
2113 mods = null;
2114 }
2115 S.nextToken();
2116 pid = qualident();
2117 accept(SEMI);
2118 }
2119 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2120 boolean checkForImports = true;
2121 while (S.token() != EOF) {
2122 if (S.pos() <= errorEndPos) {
2123 // error recovery
2124 skip(checkForImports, false, false, false);
2125 if (S.token() == EOF)
2126 break;
2127 }
2128 if (checkForImports && mods == null && S.token() == IMPORT) {
2129 defs.append(importDeclaration());
2130 } else {
2131 JCTree def = typeDeclaration(mods);
2132 if (def instanceof JCExpressionStatement)
2133 def = ((JCExpressionStatement)def).expr;
2134 defs.append(def);
2135 if (def instanceof JCClassDecl)
2136 checkForImports = false;
2137 mods = null;
2138 }
2139 }
2140 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
2141 attach(toplevel, dc);
2142 if (defs.elems.isEmpty())
2143 storeEnd(toplevel, S.prevEndPos());
2144 if (keepDocComments)
2145 toplevel.docComments = docComments;
2146 if (keepLineMap)
2147 toplevel.lineMap = S.getLineMap();
2148 return toplevel;
2149 }
2151 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2152 */
2153 JCTree importDeclaration() {
2154 int pos = S.pos();
2155 S.nextToken();
2156 boolean importStatic = false;
2157 if (S.token() == STATIC) {
2158 checkStaticImports();
2159 importStatic = true;
2160 S.nextToken();
2161 }
2162 JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
2163 do {
2164 int pos1 = S.pos();
2165 accept(DOT);
2166 if (S.token() == STAR) {
2167 pid = to(F.at(pos1).Select(pid, names.asterisk));
2168 S.nextToken();
2169 break;
2170 } else {
2171 pid = toP(F.at(pos1).Select(pid, ident()));
2172 }
2173 } while (S.token() == DOT);
2174 accept(SEMI);
2175 return toP(F.at(pos).Import(pid, importStatic));
2176 }
2178 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2179 * | ";"
2180 */
2181 JCTree typeDeclaration(JCModifiers mods) {
2182 int pos = S.pos();
2183 if (mods == null && S.token() == SEMI) {
2184 S.nextToken();
2185 return toP(F.at(pos).Skip());
2186 } else {
2187 String dc = S.docComment();
2188 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
2189 }
2190 }
2192 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2193 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2194 * @param mods Any modifiers starting the class or interface declaration
2195 * @param dc The documentation comment for the class, or null.
2196 */
2197 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
2198 if (S.token() == CLASS) {
2199 return classDeclaration(mods, dc);
2200 } else if (S.token() == INTERFACE) {
2201 return interfaceDeclaration(mods, dc);
2202 } else if (allowEnums) {
2203 if (S.token() == ENUM) {
2204 return enumDeclaration(mods, dc);
2205 } else {
2206 int pos = S.pos();
2207 List<JCTree> errs;
2208 if (S.token() == IDENTIFIER) {
2209 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2210 setErrorEndPos(S.pos());
2211 } else {
2212 errs = List.<JCTree>of(mods);
2213 }
2214 return toP(F.Exec(syntaxError(pos, errs, "expected3",
2215 CLASS, INTERFACE, ENUM)));
2216 }
2217 } else {
2218 if (S.token() == ENUM) {
2219 log.error(S.pos(), "enums.not.supported.in.source", source.name);
2220 allowEnums = true;
2221 return enumDeclaration(mods, dc);
2222 }
2223 int pos = S.pos();
2224 List<JCTree> errs;
2225 if (S.token() == IDENTIFIER) {
2226 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2227 setErrorEndPos(S.pos());
2228 } else {
2229 errs = List.<JCTree>of(mods);
2230 }
2231 return toP(F.Exec(syntaxError(pos, errs, "expected2",
2232 CLASS, INTERFACE)));
2233 }
2234 }
2236 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2237 * [IMPLEMENTS TypeList] ClassBody
2238 * @param mods The modifiers starting the class declaration
2239 * @param dc The documentation comment for the class, or null.
2240 */
2241 JCClassDecl classDeclaration(JCModifiers mods, String dc) {
2242 int pos = S.pos();
2243 accept(CLASS);
2244 Name name = ident();
2246 List<JCTypeParameter> typarams = typeParametersOpt();
2248 JCTree extending = null;
2249 if (S.token() == EXTENDS) {
2250 S.nextToken();
2251 extending = parseType();
2252 }
2253 List<JCExpression> implementing = List.nil();
2254 if (S.token() == IMPLEMENTS) {
2255 S.nextToken();
2256 implementing = typeList();
2257 }
2258 List<JCTree> defs = classOrInterfaceBody(name, false);
2259 JCClassDecl result = toP(F.at(pos).ClassDef(
2260 mods, name, typarams, extending, implementing, defs));
2261 attach(result, dc);
2262 return result;
2263 }
2265 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2266 * [EXTENDS TypeList] InterfaceBody
2267 * @param mods The modifiers starting the interface declaration
2268 * @param dc The documentation comment for the interface, or null.
2269 */
2270 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
2271 int pos = S.pos();
2272 accept(INTERFACE);
2273 Name name = ident();
2275 List<JCTypeParameter> typarams = typeParametersOpt();
2277 List<JCExpression> extending = List.nil();
2278 if (S.token() == EXTENDS) {
2279 S.nextToken();
2280 extending = typeList();
2281 }
2282 List<JCTree> defs = classOrInterfaceBody(name, true);
2283 JCClassDecl result = toP(F.at(pos).ClassDef(
2284 mods, name, typarams, null, extending, defs));
2285 attach(result, dc);
2286 return result;
2287 }
2289 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2290 * @param mods The modifiers starting the enum declaration
2291 * @param dc The documentation comment for the enum, or null.
2292 */
2293 JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
2294 int pos = S.pos();
2295 accept(ENUM);
2296 Name name = ident();
2298 List<JCExpression> implementing = List.nil();
2299 if (S.token() == IMPLEMENTS) {
2300 S.nextToken();
2301 implementing = typeList();
2302 }
2304 List<JCTree> defs = enumBody(name);
2305 JCModifiers newMods =
2306 F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
2307 JCClassDecl result = toP(F.at(pos).
2308 ClassDef(newMods, name, List.<JCTypeParameter>nil(),
2309 null, implementing, defs));
2310 attach(result, dc);
2311 return result;
2312 }
2314 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2315 * [ ";" {ClassBodyDeclaration} ] "}"
2316 */
2317 List<JCTree> enumBody(Name enumName) {
2318 accept(LBRACE);
2319 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2320 if (S.token() == COMMA) {
2321 S.nextToken();
2322 } else if (S.token() != RBRACE && S.token() != SEMI) {
2323 defs.append(enumeratorDeclaration(enumName));
2324 while (S.token() == COMMA) {
2325 S.nextToken();
2326 if (S.token() == RBRACE || S.token() == SEMI) break;
2327 defs.append(enumeratorDeclaration(enumName));
2328 }
2329 if (S.token() != SEMI && S.token() != RBRACE) {
2330 defs.append(syntaxError(S.pos(), "expected3",
2331 COMMA, RBRACE, SEMI));
2332 S.nextToken();
2333 }
2334 }
2335 if (S.token() == SEMI) {
2336 S.nextToken();
2337 while (S.token() != RBRACE && S.token() != EOF) {
2338 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2339 false));
2340 if (S.pos() <= errorEndPos) {
2341 // error recovery
2342 skip(false, true, true, false);
2343 }
2344 }
2345 }
2346 accept(RBRACE);
2347 return defs.toList();
2348 }
2350 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2351 */
2352 JCTree enumeratorDeclaration(Name enumName) {
2353 String dc = S.docComment();
2354 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2355 if (S.deprecatedFlag()) {
2356 flags |= Flags.DEPRECATED;
2357 S.resetDeprecatedFlag();
2358 }
2359 int pos = S.pos();
2360 List<JCAnnotation> annotations = annotationsOpt();
2361 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2362 List<JCExpression> typeArgs = typeArgumentsOpt();
2363 int identPos = S.pos();
2364 Name name = ident();
2365 int createPos = S.pos();
2366 List<JCExpression> args = (S.token() == LPAREN)
2367 ? arguments() : List.<JCExpression>nil();
2368 JCClassDecl body = null;
2369 if (S.token() == LBRACE) {
2370 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2371 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2372 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2373 }
2374 if (args.isEmpty() && body == null)
2375 createPos = Position.NOPOS;
2376 JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
2377 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2378 if (createPos != Position.NOPOS)
2379 storeEnd(create, S.prevEndPos());
2380 ident = F.at(Position.NOPOS).Ident(enumName);
2381 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2382 attach(result, dc);
2383 return result;
2384 }
2386 /** TypeList = Type {"," Type}
2387 */
2388 List<JCExpression> typeList() {
2389 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2390 ts.append(parseType());
2391 while (S.token() == COMMA) {
2392 S.nextToken();
2393 ts.append(parseType());
2394 }
2395 return ts.toList();
2396 }
2398 /** ClassBody = "{" {ClassBodyDeclaration} "}"
2399 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2400 */
2401 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2402 accept(LBRACE);
2403 if (S.pos() <= errorEndPos) {
2404 // error recovery
2405 skip(false, true, false, false);
2406 if (S.token() == LBRACE)
2407 S.nextToken();
2408 }
2409 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2410 while (S.token() != RBRACE && S.token() != EOF) {
2411 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2412 if (S.pos() <= errorEndPos) {
2413 // error recovery
2414 skip(false, true, true, false);
2415 }
2416 }
2417 accept(RBRACE);
2418 return defs.toList();
2419 }
2421 /** ClassBodyDeclaration =
2422 * ";"
2423 * | [STATIC] Block
2424 * | ModifiersOpt
2425 * ( Type Ident
2426 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2427 * | VOID Ident MethodDeclaratorRest
2428 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2429 * | Ident ConstructorDeclaratorRest
2430 * | TypeParameters Ident ConstructorDeclaratorRest
2431 * | ClassOrInterfaceOrEnumDeclaration
2432 * )
2433 * InterfaceBodyDeclaration =
2434 * ";"
2435 * | ModifiersOpt Type Ident
2436 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2437 */
2438 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2439 if (S.token() == SEMI) {
2440 S.nextToken();
2441 return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
2442 } else {
2443 String dc = S.docComment();
2444 int pos = S.pos();
2445 JCModifiers mods = modifiersOpt();
2446 if (S.token() == CLASS ||
2447 S.token() == INTERFACE ||
2448 allowEnums && S.token() == ENUM) {
2449 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2450 } else if (S.token() == LBRACE && !isInterface &&
2451 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2452 mods.annotations.isEmpty()) {
2453 return List.<JCTree>of(block(pos, mods.flags));
2454 } else {
2455 pos = S.pos();
2456 List<JCTypeParameter> typarams = typeParametersOpt();
2457 // Hack alert: if there are type arguments but no Modifiers, the start
2458 // position will be lost unless we set the Modifiers position. There
2459 // should be an AST node for type parameters (BugId 5005090).
2460 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
2461 mods.pos = pos;
2462 }
2463 Token token = S.token();
2464 Name name = S.name();
2465 pos = S.pos();
2466 JCExpression type;
2467 boolean isVoid = S.token() == VOID;
2468 if (isVoid) {
2469 type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2470 S.nextToken();
2471 } else {
2472 type = parseType();
2473 }
2474 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
2475 if (isInterface || name != className)
2476 log.error(pos, "invalid.meth.decl.ret.type.req");
2477 return List.of(methodDeclaratorRest(
2478 pos, mods, null, names.init, typarams,
2479 isInterface, true, dc));
2480 } else {
2481 pos = S.pos();
2482 name = ident();
2483 if (S.token() == LPAREN) {
2484 return List.of(methodDeclaratorRest(
2485 pos, mods, type, name, typarams,
2486 isInterface, isVoid, dc));
2487 } else if (!isVoid && typarams.isEmpty()) {
2488 List<JCTree> defs =
2489 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2490 new ListBuffer<JCTree>()).toList();
2491 storeEnd(defs.last(), S.endPos());
2492 accept(SEMI);
2493 return defs;
2494 } else {
2495 pos = S.pos();
2496 List<JCTree> err = isVoid
2497 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2498 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2499 : null;
2500 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
2501 }
2502 }
2503 }
2504 }
2505 }
2507 /** MethodDeclaratorRest =
2508 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2509 * VoidMethodDeclaratorRest =
2510 * FormalParameters [Throws TypeList] ( MethodBody | ";")
2511 * InterfaceMethodDeclaratorRest =
2512 * FormalParameters BracketsOpt [THROWS TypeList] ";"
2513 * VoidInterfaceMethodDeclaratorRest =
2514 * FormalParameters [THROWS TypeList] ";"
2515 * ConstructorDeclaratorRest =
2516 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2517 */
2518 JCTree methodDeclaratorRest(int pos,
2519 JCModifiers mods,
2520 JCExpression type,
2521 Name name,
2522 List<JCTypeParameter> typarams,
2523 boolean isInterface, boolean isVoid,
2524 String dc) {
2525 List<JCVariableDecl> params = formalParameters();
2526 if (!isVoid) type = bracketsOpt(type);
2527 List<JCExpression> thrown = List.nil();
2528 if (S.token() == THROWS) {
2529 S.nextToken();
2530 thrown = qualidentList();
2531 }
2532 JCBlock body = null;
2533 JCExpression defaultValue;
2534 if (S.token() == LBRACE) {
2535 body = block();
2536 defaultValue = null;
2537 } else {
2538 if (S.token() == DEFAULT) {
2539 accept(DEFAULT);
2540 defaultValue = annotationValue();
2541 } else {
2542 defaultValue = null;
2543 }
2544 accept(SEMI);
2545 if (S.pos() <= errorEndPos) {
2546 // error recovery
2547 skip(false, true, false, false);
2548 if (S.token() == LBRACE) {
2549 body = block();
2550 }
2551 }
2552 }
2553 JCMethodDecl result =
2554 toP(F.at(pos).MethodDef(mods, name, type, typarams,
2555 params, thrown,
2556 body, defaultValue));
2557 attach(result, dc);
2558 return result;
2559 }
2561 /** QualidentList = Qualident {"," Qualident}
2562 */
2563 List<JCExpression> qualidentList() {
2564 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2565 ts.append(qualident());
2566 while (S.token() == COMMA) {
2567 S.nextToken();
2568 ts.append(qualident());
2569 }
2570 return ts.toList();
2571 }
2573 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2574 */
2575 List<JCTypeParameter> typeParametersOpt() {
2576 if (S.token() == LT) {
2577 checkGenerics();
2578 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
2579 S.nextToken();
2580 typarams.append(typeParameter());
2581 while (S.token() == COMMA) {
2582 S.nextToken();
2583 typarams.append(typeParameter());
2584 }
2585 accept(GT);
2586 return typarams.toList();
2587 } else {
2588 return List.nil();
2589 }
2590 }
2592 /** TypeParameter = TypeVariable [TypeParameterBound]
2593 * TypeParameterBound = EXTENDS Type {"&" Type}
2594 * TypeVariable = Ident
2595 */
2596 JCTypeParameter typeParameter() {
2597 int pos = S.pos();
2598 Name name = ident();
2599 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
2600 if (S.token() == EXTENDS) {
2601 S.nextToken();
2602 bounds.append(parseType());
2603 while (S.token() == AMP) {
2604 S.nextToken();
2605 bounds.append(parseType());
2606 }
2607 }
2608 return toP(F.at(pos).TypeParameter(name, bounds.toList()));
2609 }
2611 /** FormalParameters = "(" [ FormalParameterList ] ")"
2612 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
2613 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
2614 */
2615 List<JCVariableDecl> formalParameters() {
2616 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
2617 JCVariableDecl lastParam = null;
2618 accept(LPAREN);
2619 if (S.token() != RPAREN) {
2620 params.append(lastParam = formalParameter());
2621 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
2622 S.nextToken();
2623 params.append(lastParam = formalParameter());
2624 }
2625 }
2626 accept(RPAREN);
2627 return params.toList();
2628 }
2630 JCModifiers optFinal(long flags) {
2631 JCModifiers mods = modifiersOpt();
2632 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
2633 mods.flags |= flags;
2634 return mods;
2635 }
2637 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
2638 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
2639 */
2640 JCVariableDecl formalParameter() {
2641 JCModifiers mods = optFinal(Flags.PARAMETER);
2642 JCExpression type = parseType();
2643 if (S.token() == ELLIPSIS) {
2644 checkVarargs();
2645 mods.flags |= Flags.VARARGS;
2646 type = to(F.at(S.pos()).TypeArray(type));
2647 S.nextToken();
2648 }
2649 return variableDeclaratorId(mods, type);
2650 }
2652 /* ---------- auxiliary methods -------------- */
2654 /** Check that given tree is a legal expression statement.
2655 */
2656 protected JCExpression checkExprStat(JCExpression t) {
2657 switch(t.getTag()) {
2658 case JCTree.PREINC: case JCTree.PREDEC:
2659 case JCTree.POSTINC: case JCTree.POSTDEC:
2660 case JCTree.ASSIGN:
2661 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
2662 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
2663 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
2664 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
2665 case JCTree.APPLY: case JCTree.NEWCLASS:
2666 case JCTree.ERRONEOUS:
2667 return t;
2668 default:
2669 log.error(t.pos, "not.stmt");
2670 return F.at(t.pos).Erroneous(List.<JCTree>of(t));
2671 }
2672 }
2674 /** Return precedence of operator represented by token,
2675 * -1 if token is not a binary operator. @see TreeInfo.opPrec
2676 */
2677 static int prec(Token token) {
2678 int oc = optag(token);
2679 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
2680 }
2682 /** Return operation tag of binary operator represented by token,
2683 * -1 if token is not a binary operator.
2684 */
2685 static int optag(Token token) {
2686 switch (token) {
2687 case BARBAR:
2688 return JCTree.OR;
2689 case AMPAMP:
2690 return JCTree.AND;
2691 case BAR:
2692 return JCTree.BITOR;
2693 case BAREQ:
2694 return JCTree.BITOR_ASG;
2695 case CARET:
2696 return JCTree.BITXOR;
2697 case CARETEQ:
2698 return JCTree.BITXOR_ASG;
2699 case AMP:
2700 return JCTree.BITAND;
2701 case AMPEQ:
2702 return JCTree.BITAND_ASG;
2703 case EQEQ:
2704 return JCTree.EQ;
2705 case BANGEQ:
2706 return JCTree.NE;
2707 case LT:
2708 return JCTree.LT;
2709 case GT:
2710 return JCTree.GT;
2711 case LTEQ:
2712 return JCTree.LE;
2713 case GTEQ:
2714 return JCTree.GE;
2715 case LTLT:
2716 return JCTree.SL;
2717 case LTLTEQ:
2718 return JCTree.SL_ASG;
2719 case GTGT:
2720 return JCTree.SR;
2721 case GTGTEQ:
2722 return JCTree.SR_ASG;
2723 case GTGTGT:
2724 return JCTree.USR;
2725 case GTGTGTEQ:
2726 return JCTree.USR_ASG;
2727 case PLUS:
2728 return JCTree.PLUS;
2729 case PLUSEQ:
2730 return JCTree.PLUS_ASG;
2731 case SUB:
2732 return JCTree.MINUS;
2733 case SUBEQ:
2734 return JCTree.MINUS_ASG;
2735 case STAR:
2736 return JCTree.MUL;
2737 case STAREQ:
2738 return JCTree.MUL_ASG;
2739 case SLASH:
2740 return JCTree.DIV;
2741 case SLASHEQ:
2742 return JCTree.DIV_ASG;
2743 case PERCENT:
2744 return JCTree.MOD;
2745 case PERCENTEQ:
2746 return JCTree.MOD_ASG;
2747 case INSTANCEOF:
2748 return JCTree.TYPETEST;
2749 default:
2750 return -1;
2751 }
2752 }
2754 /** Return operation tag of unary operator represented by token,
2755 * -1 if token is not a binary operator.
2756 */
2757 static int unoptag(Token token) {
2758 switch (token) {
2759 case PLUS:
2760 return JCTree.POS;
2761 case SUB:
2762 return JCTree.NEG;
2763 case BANG:
2764 return JCTree.NOT;
2765 case TILDE:
2766 return JCTree.COMPL;
2767 case PLUSPLUS:
2768 return JCTree.PREINC;
2769 case SUBSUB:
2770 return JCTree.PREDEC;
2771 default:
2772 return -1;
2773 }
2774 }
2776 /** Return type tag of basic type represented by token,
2777 * -1 if token is not a basic type identifier.
2778 */
2779 static int typetag(Token token) {
2780 switch (token) {
2781 case BYTE:
2782 return TypeTags.BYTE;
2783 case CHAR:
2784 return TypeTags.CHAR;
2785 case SHORT:
2786 return TypeTags.SHORT;
2787 case INT:
2788 return TypeTags.INT;
2789 case LONG:
2790 return TypeTags.LONG;
2791 case FLOAT:
2792 return TypeTags.FLOAT;
2793 case DOUBLE:
2794 return TypeTags.DOUBLE;
2795 case BOOLEAN:
2796 return TypeTags.BOOLEAN;
2797 default:
2798 return -1;
2799 }
2800 }
2802 void checkGenerics() {
2803 if (!allowGenerics) {
2804 log.error(S.pos(), "generics.not.supported.in.source", source.name);
2805 allowGenerics = true;
2806 }
2807 }
2808 void checkVarargs() {
2809 if (!allowVarargs) {
2810 log.error(S.pos(), "varargs.not.supported.in.source", source.name);
2811 allowVarargs = true;
2812 }
2813 }
2814 void checkForeach() {
2815 if (!allowForeach) {
2816 log.error(S.pos(), "foreach.not.supported.in.source", source.name);
2817 allowForeach = true;
2818 }
2819 }
2820 void checkStaticImports() {
2821 if (!allowStaticImport) {
2822 log.error(S.pos(), "static.import.not.supported.in.source", source.name);
2823 allowStaticImport = true;
2824 }
2825 }
2826 void checkAnnotations() {
2827 if (!allowAnnotations) {
2828 log.error(S.pos(), "annotations.not.supported.in.source", source.name);
2829 allowAnnotations = true;
2830 }
2831 }
2832 }