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