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