src/share/classes/com/sun/tools/javac/parser/Parser.java

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

mercurial