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