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