Wed, 15 Aug 2012 13:48:46 -0700
7191449: update copyright year to match last edit in jdk8 langtools repository
Reviewed-by: jjh
Contributed-by: steve.sides@oracle.com
1 /*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.parser;
28 import java.util.*;
30 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
32 import com.sun.tools.javac.code.*;
33 import com.sun.tools.javac.parser.Tokens.*;
34 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
35 import com.sun.tools.javac.tree.*;
36 import com.sun.tools.javac.tree.JCTree.*;
37 import com.sun.tools.javac.util.*;
38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
40 import com.sun.tools.javac.util.List;
42 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
43 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
44 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
45 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
46 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
47 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
48 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
49 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
50 import static com.sun.tools.javac.util.ListBuffer.lb;
51 import static com.sun.tools.javac.tree.JCTree.Tag.*;
53 /** The parser maps a token sequence into an abstract syntax
54 * tree. It operates by recursive descent, with code derived
55 * systematically from an LL(1) grammar. For efficiency reasons, an
56 * operator precedence scheme is used for parsing binary operation
57 * expressions.
58 *
59 * <p><b>This is NOT part of any supported API.
60 * If you write code that depends on this, you do so at your own risk.
61 * This code and its internal interfaces are subject to change or
62 * deletion without notice.</b>
63 */
64 public class JavacParser implements Parser {
66 /** The number of precedence levels of infix operators.
67 */
68 private static final int infixPrecedenceLevels = 10;
70 /** The scanner used for lexical analysis.
71 */
72 protected Lexer S;
74 /** The factory to be used for abstract syntax tree construction.
75 */
76 protected TreeMaker F;
78 /** The log to be used for error diagnostics.
79 */
80 private Log log;
82 /** The Source language setting. */
83 private Source source;
85 /** The name table. */
86 private Names names;
88 /** End position mappings container */
89 private final AbstractEndPosTable endPosTable;
91 /** Construct a parser from a given scanner, tree factory and log.
92 */
93 protected JavacParser(ParserFactory fac,
94 Lexer S,
95 boolean keepDocComments,
96 boolean keepLineMap,
97 boolean keepEndPositions) {
98 this.S = S;
99 nextToken(); // prime the pump
100 this.F = fac.F;
101 this.log = fac.log;
102 this.names = fac.names;
103 this.source = fac.source;
104 this.allowGenerics = source.allowGenerics();
105 this.allowVarargs = source.allowVarargs();
106 this.allowAsserts = source.allowAsserts();
107 this.allowEnums = source.allowEnums();
108 this.allowForeach = source.allowForeach();
109 this.allowStaticImport = source.allowStaticImport();
110 this.allowAnnotations = source.allowAnnotations();
111 this.allowTWR = source.allowTryWithResources();
112 this.allowDiamond = source.allowDiamond();
113 this.allowMulticatch = source.allowMulticatch();
114 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
115 this.allowLambda = source.allowLambda() &&
116 fac.options.isSet("allowLambda"); //pre-lambda guard
117 this.allowMethodReferences = source.allowMethodReferences() &&
118 fac.options.isSet("allowMethodReferences"); //pre-lambda guard
119 this.keepDocComments = keepDocComments;
120 docComments = newDocCommentTable(keepDocComments);
121 this.keepLineMap = keepLineMap;
122 this.errorTree = F.Erroneous();
123 endPosTable = newEndPosTable(keepEndPositions);
124 }
126 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
127 return keepEndPositions
128 ? new SimpleEndPosTable()
129 : new EmptyEndPosTable();
130 }
132 protected DocCommentTable newDocCommentTable(boolean keepDocComments) {
133 return keepDocComments ? new SimpleDocCommentTable() : null;
134 }
136 /** Switch: Should generics be recognized?
137 */
138 boolean allowGenerics;
140 /** Switch: Should diamond operator be recognized?
141 */
142 boolean allowDiamond;
144 /** Switch: Should multicatch clause be accepted?
145 */
146 boolean allowMulticatch;
148 /** Switch: Should varargs be recognized?
149 */
150 boolean allowVarargs;
152 /** Switch: should we recognize assert statements, or just give a warning?
153 */
154 boolean allowAsserts;
156 /** Switch: should we recognize enums, or just give a warning?
157 */
158 boolean allowEnums;
160 /** Switch: should we recognize foreach?
161 */
162 boolean allowForeach;
164 /** Switch: should we recognize foreach?
165 */
166 boolean allowStaticImport;
168 /** Switch: should we recognize annotations?
169 */
170 boolean allowAnnotations;
172 /** Switch: should we recognize try-with-resources?
173 */
174 boolean allowTWR;
176 /** Switch: should we fold strings?
177 */
178 boolean allowStringFolding;
180 /** Switch: should we recognize lambda expressions?
181 */
182 boolean allowLambda;
184 /** Switch: should we allow method/constructor references?
185 */
186 boolean allowMethodReferences;
188 /** Switch: should we keep docComments?
189 */
190 boolean keepDocComments;
192 /** Switch: should we keep line table?
193 */
194 boolean keepLineMap;
196 /** When terms are parsed, the mode determines which is expected:
197 * mode = EXPR : an expression
198 * mode = TYPE : a type
199 * mode = NOPARAMS : no parameters allowed for type
200 * mode = TYPEARG : type argument
201 */
202 static final int EXPR = 0x1;
203 static final int TYPE = 0x2;
204 static final int NOPARAMS = 0x4;
205 static final int TYPEARG = 0x8;
206 static final int DIAMOND = 0x10;
208 /** The current mode.
209 */
210 private int mode = 0;
212 /** The mode of the term that was parsed last.
213 */
214 private int lastmode = 0;
216 /* ---------- token management -------------- */
218 protected Token token;
220 protected void nextToken() {
221 S.nextToken();
222 token = S.token();
223 }
225 protected boolean peekToken(TokenKind tk) {
226 return S.token(1).kind == tk;
227 }
229 protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
230 return S.token(1).kind == tk1 &&
231 S.token(2).kind == tk2;
232 }
234 protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
235 return S.token(1).kind == tk1 &&
236 S.token(2).kind == tk2 &&
237 S.token(3).kind == tk3;
238 }
240 protected boolean peekToken(TokenKind... kinds) {
241 for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) {
242 if (S.token(lookahead + 1).kind != kinds[lookahead]) {
243 return false;
244 }
245 }
246 return true;
247 }
249 /* ---------- error recovery -------------- */
251 private JCErroneous errorTree;
253 /** Skip forward until a suitable stop token is found.
254 */
255 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
256 while (true) {
257 switch (token.kind) {
258 case SEMI:
259 nextToken();
260 return;
261 case PUBLIC:
262 case FINAL:
263 case ABSTRACT:
264 case MONKEYS_AT:
265 case EOF:
266 case CLASS:
267 case INTERFACE:
268 case ENUM:
269 return;
270 case IMPORT:
271 if (stopAtImport)
272 return;
273 break;
274 case LBRACE:
275 case RBRACE:
276 case PRIVATE:
277 case PROTECTED:
278 case STATIC:
279 case TRANSIENT:
280 case NATIVE:
281 case VOLATILE:
282 case SYNCHRONIZED:
283 case STRICTFP:
284 case LT:
285 case BYTE:
286 case SHORT:
287 case CHAR:
288 case INT:
289 case LONG:
290 case FLOAT:
291 case DOUBLE:
292 case BOOLEAN:
293 case VOID:
294 if (stopAtMemberDecl)
295 return;
296 break;
297 case IDENTIFIER:
298 if (stopAtIdentifier)
299 return;
300 break;
301 case CASE:
302 case DEFAULT:
303 case IF:
304 case FOR:
305 case WHILE:
306 case DO:
307 case TRY:
308 case SWITCH:
309 case RETURN:
310 case THROW:
311 case BREAK:
312 case CONTINUE:
313 case ELSE:
314 case FINALLY:
315 case CATCH:
316 if (stopAtStatement)
317 return;
318 break;
319 }
320 nextToken();
321 }
322 }
324 private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
325 return syntaxError(pos, List.<JCTree>nil(), key, args);
326 }
328 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
329 setErrorEndPos(pos);
330 JCErroneous err = F.at(pos).Erroneous(errs);
331 reportSyntaxError(err, key, (Object[])args);
332 if (errs != null) {
333 JCTree last = errs.last();
334 if (last != null)
335 storeEnd(last, pos);
336 }
337 return toP(err);
338 }
340 private int errorPos = Position.NOPOS;
342 /**
343 * Report a syntax using the given the position parameter and arguments,
344 * unless one was already reported at the same position.
345 */
346 private void reportSyntaxError(int pos, String key, Object... args) {
347 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
348 reportSyntaxError(diag, key, args);
349 }
351 /**
352 * Report a syntax error using the given DiagnosticPosition object and
353 * arguments, unless one was already reported at the same position.
354 */
355 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
356 int pos = diagPos.getPreferredPosition();
357 if (pos > S.errPos() || pos == Position.NOPOS) {
358 if (token.kind == EOF) {
359 error(diagPos, "premature.eof");
360 } else {
361 error(diagPos, key, args);
362 }
363 }
364 S.errPos(pos);
365 if (token.pos == errorPos)
366 nextToken(); // guarantee progress
367 errorPos = token.pos;
368 }
371 /** Generate a syntax error at current position unless one was already
372 * reported at the same position.
373 */
374 private JCErroneous syntaxError(String key) {
375 return syntaxError(token.pos, key);
376 }
378 /** Generate a syntax error at current position unless one was
379 * already reported at the same position.
380 */
381 private JCErroneous syntaxError(String key, TokenKind arg) {
382 return syntaxError(token.pos, key, arg);
383 }
385 /** If next input token matches given token, skip it, otherwise report
386 * an error.
387 */
388 public void accept(TokenKind tk) {
389 if (token.kind == tk) {
390 nextToken();
391 } else {
392 setErrorEndPos(token.pos);
393 reportSyntaxError(S.prevToken().endPos, "expected", tk);
394 }
395 }
397 /** Report an illegal start of expression/type error at given position.
398 */
399 JCExpression illegal(int pos) {
400 setErrorEndPos(pos);
401 if ((mode & EXPR) != 0)
402 return syntaxError(pos, "illegal.start.of.expr");
403 else
404 return syntaxError(pos, "illegal.start.of.type");
406 }
408 /** Report an illegal start of expression/type error at current position.
409 */
410 JCExpression illegal() {
411 return illegal(token.pos);
412 }
414 /** Diagnose a modifier flag from the set, if any. */
415 void checkNoMods(long mods) {
416 if (mods != 0) {
417 long lowestMod = mods & -mods;
418 error(token.pos, "mod.not.allowed.here",
419 Flags.asFlagSet(lowestMod));
420 }
421 }
423 /* ---------- doc comments --------- */
425 /** A table to store all documentation comments
426 * indexed by the tree nodes they refer to.
427 * defined only if option flag keepDocComment is set.
428 */
429 private final DocCommentTable docComments;
431 /** Make an entry into docComments hashtable,
432 * provided flag keepDocComments is set and given doc comment is non-null.
433 * @param tree The tree to be used as index in the hashtable
434 * @param dc The doc comment to associate with the tree, or null.
435 */
436 void attach(JCTree tree, Comment dc) {
437 if (keepDocComments && dc != null) {
438 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
439 docComments.putComment(tree, dc);
440 }
441 }
443 /* -------- source positions ------- */
445 private void setErrorEndPos(int errPos) {
446 endPosTable.setErrorEndPos(errPos);
447 }
449 private void storeEnd(JCTree tree, int endpos) {
450 endPosTable.storeEnd(tree, endpos);
451 }
453 private <T extends JCTree> T to(T t) {
454 return endPosTable.to(t);
455 }
457 private <T extends JCTree> T toP(T t) {
458 return endPosTable.toP(t);
459 }
461 /** Get the start position for a tree node. The start position is
462 * defined to be the position of the first character of the first
463 * token of the node's source text.
464 * @param tree The tree node
465 */
466 public int getStartPos(JCTree tree) {
467 return TreeInfo.getStartPos(tree);
468 }
470 /**
471 * Get the end position for a tree node. The end position is
472 * defined to be the position of the last character of the last
473 * token of the node's source text. Returns Position.NOPOS if end
474 * positions are not generated or the position is otherwise not
475 * found.
476 * @param tree The tree node
477 */
478 public int getEndPos(JCTree tree) {
479 return endPosTable.getEndPos(tree);
480 }
484 /* ---------- parsing -------------- */
486 /**
487 * Ident = IDENTIFIER
488 */
489 Name ident() {
490 if (token.kind == IDENTIFIER) {
491 Name name = token.name();
492 nextToken();
493 return name;
494 } else if (token.kind == ASSERT) {
495 if (allowAsserts) {
496 error(token.pos, "assert.as.identifier");
497 nextToken();
498 return names.error;
499 } else {
500 warning(token.pos, "assert.as.identifier");
501 Name name = token.name();
502 nextToken();
503 return name;
504 }
505 } else if (token.kind == ENUM) {
506 if (allowEnums) {
507 error(token.pos, "enum.as.identifier");
508 nextToken();
509 return names.error;
510 } else {
511 warning(token.pos, "enum.as.identifier");
512 Name name = token.name();
513 nextToken();
514 return name;
515 }
516 } else {
517 accept(IDENTIFIER);
518 return names.error;
519 }
520 }
522 /**
523 * Qualident = Ident { DOT Ident }
524 */
525 public JCExpression qualident() {
526 JCExpression t = toP(F.at(token.pos).Ident(ident()));
527 while (token.kind == DOT) {
528 int pos = token.pos;
529 nextToken();
530 t = toP(F.at(pos).Select(t, ident()));
531 }
532 return t;
533 }
535 JCExpression literal(Name prefix) {
536 return literal(prefix, token.pos);
537 }
539 /**
540 * Literal =
541 * INTLITERAL
542 * | LONGLITERAL
543 * | FLOATLITERAL
544 * | DOUBLELITERAL
545 * | CHARLITERAL
546 * | STRINGLITERAL
547 * | TRUE
548 * | FALSE
549 * | NULL
550 */
551 JCExpression literal(Name prefix, int pos) {
552 JCExpression t = errorTree;
553 switch (token.kind) {
554 case INTLITERAL:
555 try {
556 t = F.at(pos).Literal(
557 TypeTags.INT,
558 Convert.string2int(strval(prefix), token.radix()));
559 } catch (NumberFormatException ex) {
560 error(token.pos, "int.number.too.large", strval(prefix));
561 }
562 break;
563 case LONGLITERAL:
564 try {
565 t = F.at(pos).Literal(
566 TypeTags.LONG,
567 new Long(Convert.string2long(strval(prefix), token.radix())));
568 } catch (NumberFormatException ex) {
569 error(token.pos, "int.number.too.large", strval(prefix));
570 }
571 break;
572 case FLOATLITERAL: {
573 String proper = token.radix() == 16 ?
574 ("0x"+ token.stringVal()) :
575 token.stringVal();
576 Float n;
577 try {
578 n = Float.valueOf(proper);
579 } catch (NumberFormatException ex) {
580 // error already reported in scanner
581 n = Float.NaN;
582 }
583 if (n.floatValue() == 0.0f && !isZero(proper))
584 error(token.pos, "fp.number.too.small");
585 else if (n.floatValue() == Float.POSITIVE_INFINITY)
586 error(token.pos, "fp.number.too.large");
587 else
588 t = F.at(pos).Literal(TypeTags.FLOAT, n);
589 break;
590 }
591 case DOUBLELITERAL: {
592 String proper = token.radix() == 16 ?
593 ("0x"+ token.stringVal()) :
594 token.stringVal();
595 Double n;
596 try {
597 n = Double.valueOf(proper);
598 } catch (NumberFormatException ex) {
599 // error already reported in scanner
600 n = Double.NaN;
601 }
602 if (n.doubleValue() == 0.0d && !isZero(proper))
603 error(token.pos, "fp.number.too.small");
604 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
605 error(token.pos, "fp.number.too.large");
606 else
607 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
608 break;
609 }
610 case CHARLITERAL:
611 t = F.at(pos).Literal(
612 TypeTags.CHAR,
613 token.stringVal().charAt(0) + 0);
614 break;
615 case STRINGLITERAL:
616 t = F.at(pos).Literal(
617 TypeTags.CLASS,
618 token.stringVal());
619 break;
620 case TRUE: case FALSE:
621 t = F.at(pos).Literal(
622 TypeTags.BOOLEAN,
623 (token.kind == TRUE ? 1 : 0));
624 break;
625 case NULL:
626 t = F.at(pos).Literal(
627 TypeTags.BOT,
628 null);
629 break;
630 default:
631 Assert.error();
632 }
633 if (t == errorTree)
634 t = F.at(pos).Erroneous();
635 storeEnd(t, token.endPos);
636 nextToken();
637 return t;
638 }
639 //where
640 boolean isZero(String s) {
641 char[] cs = s.toCharArray();
642 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
643 int i = ((base==16) ? 2 : 0);
644 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
645 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
646 }
648 String strval(Name prefix) {
649 String s = token.stringVal();
650 return prefix.isEmpty() ? s : prefix + s;
651 }
653 /** terms can be either expressions or types.
654 */
655 public JCExpression parseExpression() {
656 return term(EXPR);
657 }
659 public JCExpression parseType() {
660 return term(TYPE);
661 }
663 JCExpression term(int newmode) {
664 int prevmode = mode;
665 mode = newmode;
666 JCExpression t = term();
667 lastmode = mode;
668 mode = prevmode;
669 return t;
670 }
672 /**
673 * Expression = Expression1 [ExpressionRest]
674 * ExpressionRest = [AssignmentOperator Expression1]
675 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
676 * "&=" | "|=" | "^=" |
677 * "%=" | "<<=" | ">>=" | ">>>="
678 * Type = Type1
679 * TypeNoParams = TypeNoParams1
680 * StatementExpression = Expression
681 * ConstantExpression = Expression
682 */
683 JCExpression term() {
684 JCExpression t = term1();
685 if ((mode & EXPR) != 0 &&
686 token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
687 return termRest(t);
688 else
689 return t;
690 }
692 JCExpression termRest(JCExpression t) {
693 switch (token.kind) {
694 case EQ: {
695 int pos = token.pos;
696 nextToken();
697 mode = EXPR;
698 JCExpression t1 = term();
699 return toP(F.at(pos).Assign(t, t1));
700 }
701 case PLUSEQ:
702 case SUBEQ:
703 case STAREQ:
704 case SLASHEQ:
705 case PERCENTEQ:
706 case AMPEQ:
707 case BAREQ:
708 case CARETEQ:
709 case LTLTEQ:
710 case GTGTEQ:
711 case GTGTGTEQ:
712 int pos = token.pos;
713 TokenKind tk = token.kind;
714 nextToken();
715 mode = EXPR;
716 JCExpression t1 = term();
717 return F.at(pos).Assignop(optag(tk), t, t1);
718 default:
719 return t;
720 }
721 }
723 /** Expression1 = Expression2 [Expression1Rest]
724 * Type1 = Type2
725 * TypeNoParams1 = TypeNoParams2
726 */
727 JCExpression term1() {
728 JCExpression t = term2();
729 if ((mode & EXPR) != 0 && token.kind == QUES) {
730 mode = EXPR;
731 return term1Rest(t);
732 } else {
733 return t;
734 }
735 }
737 /** Expression1Rest = ["?" Expression ":" Expression1]
738 */
739 JCExpression term1Rest(JCExpression t) {
740 if (token.kind == QUES) {
741 int pos = token.pos;
742 nextToken();
743 JCExpression t1 = term();
744 accept(COLON);
745 JCExpression t2 = term1();
746 return F.at(pos).Conditional(t, t1, t2);
747 } else {
748 return t;
749 }
750 }
752 /** Expression2 = Expression3 [Expression2Rest]
753 * Type2 = Type3
754 * TypeNoParams2 = TypeNoParams3
755 */
756 JCExpression term2() {
757 JCExpression t = term3();
758 if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
759 mode = EXPR;
760 return term2Rest(t, TreeInfo.orPrec);
761 } else {
762 return t;
763 }
764 }
766 /* Expression2Rest = {infixop Expression3}
767 * | Expression3 instanceof Type
768 * infixop = "||"
769 * | "&&"
770 * | "|"
771 * | "^"
772 * | "&"
773 * | "==" | "!="
774 * | "<" | ">" | "<=" | ">="
775 * | "<<" | ">>" | ">>>"
776 * | "+" | "-"
777 * | "*" | "/" | "%"
778 */
779 JCExpression term2Rest(JCExpression t, int minprec) {
780 List<JCExpression[]> savedOd = odStackSupply.elems;
781 JCExpression[] odStack = newOdStack();
782 List<Token[]> savedOp = opStackSupply.elems;
783 Token[] opStack = newOpStack();
785 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
786 int top = 0;
787 odStack[0] = t;
788 int startPos = token.pos;
789 Token topOp = Tokens.DUMMY;
790 while (prec(token.kind) >= minprec) {
791 opStack[top] = topOp;
792 top++;
793 topOp = token;
794 nextToken();
795 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
796 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
797 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
798 odStack[top]);
799 top--;
800 topOp = opStack[top];
801 }
802 }
803 Assert.check(top == 0);
804 t = odStack[0];
806 if (t.hasTag(JCTree.Tag.PLUS)) {
807 StringBuffer buf = foldStrings(t);
808 if (buf != null) {
809 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
810 }
811 }
813 odStackSupply.elems = savedOd; // optimization
814 opStackSupply.elems = savedOp; // optimization
815 return t;
816 }
817 //where
818 /** Construct a binary or type test node.
819 */
820 private JCExpression makeOp(int pos,
821 TokenKind topOp,
822 JCExpression od1,
823 JCExpression od2)
824 {
825 if (topOp == INSTANCEOF) {
826 return F.at(pos).TypeTest(od1, od2);
827 } else {
828 return F.at(pos).Binary(optag(topOp), od1, od2);
829 }
830 }
831 /** If tree is a concatenation of string literals, replace it
832 * by a single literal representing the concatenated string.
833 */
834 protected StringBuffer foldStrings(JCTree tree) {
835 if (!allowStringFolding)
836 return null;
837 List<String> buf = List.nil();
838 while (true) {
839 if (tree.hasTag(LITERAL)) {
840 JCLiteral lit = (JCLiteral) tree;
841 if (lit.typetag == TypeTags.CLASS) {
842 StringBuffer sbuf =
843 new StringBuffer((String)lit.value);
844 while (buf.nonEmpty()) {
845 sbuf.append(buf.head);
846 buf = buf.tail;
847 }
848 return sbuf;
849 }
850 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
851 JCBinary op = (JCBinary)tree;
852 if (op.rhs.hasTag(LITERAL)) {
853 JCLiteral lit = (JCLiteral) op.rhs;
854 if (lit.typetag == TypeTags.CLASS) {
855 buf = buf.prepend((String) lit.value);
856 tree = op.lhs;
857 continue;
858 }
859 }
860 }
861 return null;
862 }
863 }
865 /** optimization: To save allocating a new operand/operator stack
866 * for every binary operation, we use supplys.
867 */
868 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
869 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
871 private JCExpression[] newOdStack() {
872 if (odStackSupply.elems == odStackSupply.last)
873 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
874 JCExpression[] odStack = odStackSupply.elems.head;
875 odStackSupply.elems = odStackSupply.elems.tail;
876 return odStack;
877 }
879 private Token[] newOpStack() {
880 if (opStackSupply.elems == opStackSupply.last)
881 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
882 Token[] opStack = opStackSupply.elems.head;
883 opStackSupply.elems = opStackSupply.elems.tail;
884 return opStack;
885 }
887 /** Expression3 = PrefixOp Expression3
888 * | "(" Expr | TypeNoParams ")" Expression3
889 * | Primary {Selector} {PostfixOp}
890 * Primary = "(" Expression ")"
891 * | Literal
892 * | [TypeArguments] THIS [Arguments]
893 * | [TypeArguments] SUPER SuperSuffix
894 * | NEW [TypeArguments] Creator
895 * | "(" Arguments ")" "->" ( Expression | Block )
896 * | Ident "->" ( Expression | Block )
897 * | Ident { "." Ident }
898 * | Expression3 MemberReferenceSuffix
899 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
900 * | Arguments
901 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
902 * ]
903 * | BasicType BracketsOpt "." CLASS
904 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
905 * PostfixOp = "++" | "--"
906 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
907 * | BasicType
908 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
909 * Selector = "." [TypeArguments] Ident [Arguments]
910 * | "." THIS
911 * | "." [TypeArguments] SUPER SuperSuffix
912 * | "." NEW [TypeArguments] InnerCreator
913 * | "[" Expression "]"
914 * TypeSelector = "." Ident [TypeArguments]
915 * SuperSuffix = Arguments | "." Ident [Arguments]
916 */
917 protected JCExpression term3() {
918 int pos = token.pos;
919 JCExpression t;
920 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
921 switch (token.kind) {
922 case QUES:
923 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
924 mode = TYPE;
925 return typeArgument();
926 } else
927 return illegal();
928 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
929 if (typeArgs == null && (mode & EXPR) != 0) {
930 TokenKind tk = token.kind;
931 nextToken();
932 mode = EXPR;
933 if (tk == SUB &&
934 (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
935 token.radix() == 10) {
936 mode = EXPR;
937 t = literal(names.hyphen, pos);
938 } else {
939 t = term3();
940 return F.at(pos).Unary(unoptag(tk), t);
941 }
942 } else return illegal();
943 break;
944 case LPAREN:
945 if (typeArgs == null && (mode & EXPR) != 0) {
946 if (peekToken(FINAL) ||
947 peekToken(RPAREN) ||
948 peekToken(IDENTIFIER, COMMA) ||
949 peekToken(IDENTIFIER, RPAREN, ARROW)) {
950 //implicit n-ary lambda
951 t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos);
952 break;
953 } else {
954 nextToken();
955 mode = EXPR | TYPE | NOPARAMS;
956 t = term3();
957 if ((mode & TYPE) != 0 && token.kind == LT) {
958 // Could be a cast to a parameterized type
959 JCTree.Tag op = JCTree.Tag.LT;
960 int pos1 = token.pos;
961 nextToken();
962 mode &= (EXPR | TYPE);
963 mode |= TYPEARG;
964 JCExpression t1 = term3();
965 if ((mode & TYPE) != 0 &&
966 (token.kind == COMMA || token.kind == GT)) {
967 mode = TYPE;
968 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
969 args.append(t1);
970 while (token.kind == COMMA) {
971 nextToken();
972 args.append(typeArgument());
973 }
974 accept(GT);
975 t = toP(F.at(pos1).TypeApply(t, args.toList()));
976 checkGenerics();
977 mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type
978 t = term3Rest(t, typeArgs);
979 if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) {
980 //explicit lambda (w/ generic type)
981 mode = EXPR;
982 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
983 if (token.kind == ELLIPSIS) {
984 mods.flags = Flags.VARARGS;
985 t = to(F.at(token.pos).TypeArray(t));
986 nextToken();
987 }
988 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
989 break;
990 }
991 } else if ((mode & EXPR) != 0) {
992 mode = EXPR;
993 JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
994 t = F.at(pos1).Binary(op, t, e);
995 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
996 } else {
997 accept(GT);
998 }
999 } else if ((mode & TYPE) != 0 &&
1000 (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) {
1001 //explicit lambda (w/ non-generic type)
1002 mode = EXPR;
1003 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
1004 if (token.kind == ELLIPSIS) {
1005 mods.flags = Flags.VARARGS;
1006 t = to(F.at(token.pos).TypeArray(t));
1007 nextToken();
1008 }
1009 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
1010 break;
1011 } else {
1012 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
1013 }
1014 }
1016 accept(RPAREN);
1017 lastmode = mode;
1018 mode = EXPR;
1019 if ((lastmode & EXPR) == 0) {
1020 JCExpression t1 = term3();
1021 return F.at(pos).TypeCast(t, t1);
1022 } else if ((lastmode & TYPE) != 0) {
1023 switch (token.kind) {
1024 /*case PLUSPLUS: case SUBSUB: */
1025 case BANG: case TILDE:
1026 case LPAREN: case THIS: case SUPER:
1027 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
1028 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
1029 case TRUE: case FALSE: case NULL:
1030 case NEW: case IDENTIFIER: case ASSERT: case ENUM:
1031 case BYTE: case SHORT: case CHAR: case INT:
1032 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
1033 JCExpression t1 = term3();
1034 return F.at(pos).TypeCast(t, t1);
1035 }
1036 }
1037 } else {
1038 return illegal();
1039 }
1040 t = toP(F.at(pos).Parens(t));
1041 break;
1042 case THIS:
1043 if ((mode & EXPR) != 0) {
1044 mode = EXPR;
1045 t = to(F.at(pos).Ident(names._this));
1046 nextToken();
1047 if (typeArgs == null)
1048 t = argumentsOpt(null, t);
1049 else
1050 t = arguments(typeArgs, t);
1051 typeArgs = null;
1052 } else return illegal();
1053 break;
1054 case SUPER:
1055 if ((mode & EXPR) != 0) {
1056 mode = EXPR;
1057 t = to(F.at(pos).Ident(names._super));
1058 t = superSuffix(typeArgs, t);
1059 typeArgs = null;
1060 } else return illegal();
1061 break;
1062 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1063 case CHARLITERAL: case STRINGLITERAL:
1064 case TRUE: case FALSE: case NULL:
1065 if (typeArgs == null && (mode & EXPR) != 0) {
1066 mode = EXPR;
1067 t = literal(names.empty);
1068 } else return illegal();
1069 break;
1070 case NEW:
1071 if (typeArgs != null) return illegal();
1072 if ((mode & EXPR) != 0) {
1073 mode = EXPR;
1074 nextToken();
1075 if (token.kind == LT) typeArgs = typeArguments(false);
1076 t = creator(pos, typeArgs);
1077 typeArgs = null;
1078 } else return illegal();
1079 break;
1080 case IDENTIFIER: case ASSERT: case ENUM:
1081 if (typeArgs != null) return illegal();
1082 if ((mode & EXPR) != 0 && peekToken(ARROW)) {
1083 t = lambdaExpressionOrStatement(false, false, pos);
1084 } else {
1085 t = toP(F.at(token.pos).Ident(ident()));
1086 loop: while (true) {
1087 pos = token.pos;
1088 switch (token.kind) {
1089 case LBRACKET:
1090 nextToken();
1091 if (token.kind == RBRACKET) {
1092 nextToken();
1093 t = bracketsOpt(t);
1094 t = toP(F.at(pos).TypeArray(t));
1095 t = bracketsSuffix(t);
1096 } else {
1097 if ((mode & EXPR) != 0) {
1098 mode = EXPR;
1099 JCExpression t1 = term();
1100 t = to(F.at(pos).Indexed(t, t1));
1101 }
1102 accept(RBRACKET);
1103 }
1104 break loop;
1105 case LPAREN:
1106 if ((mode & EXPR) != 0) {
1107 mode = EXPR;
1108 t = arguments(typeArgs, t);
1109 typeArgs = null;
1110 }
1111 break loop;
1112 case DOT:
1113 nextToken();
1114 int oldmode = mode;
1115 mode &= ~NOPARAMS;
1116 typeArgs = typeArgumentsOpt(EXPR);
1117 mode = oldmode;
1118 if ((mode & EXPR) != 0) {
1119 switch (token.kind) {
1120 case CLASS:
1121 if (typeArgs != null) return illegal();
1122 mode = EXPR;
1123 t = to(F.at(pos).Select(t, names._class));
1124 nextToken();
1125 break loop;
1126 case THIS:
1127 if (typeArgs != null) return illegal();
1128 mode = EXPR;
1129 t = to(F.at(pos).Select(t, names._this));
1130 nextToken();
1131 break loop;
1132 case SUPER:
1133 mode = EXPR;
1134 t = to(F.at(pos).Select(t, names._super));
1135 t = superSuffix(typeArgs, t);
1136 typeArgs = null;
1137 break loop;
1138 case NEW:
1139 if (typeArgs != null) return illegal();
1140 mode = EXPR;
1141 int pos1 = token.pos;
1142 nextToken();
1143 if (token.kind == LT) typeArgs = typeArguments(false);
1144 t = innerCreator(pos1, typeArgs, t);
1145 typeArgs = null;
1146 break loop;
1147 }
1148 }
1149 // typeArgs saved for next loop iteration.
1150 t = toP(F.at(pos).Select(t, ident()));
1151 break;
1152 case LT:
1153 if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
1154 //this is an unbound method reference whose qualifier
1155 //is a generic type i.e. A<S>#m
1156 int pos1 = token.pos;
1157 accept(LT);
1158 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
1159 args.append(typeArgument());
1160 while (token.kind == COMMA) {
1161 nextToken();
1162 args.append(typeArgument());
1163 }
1164 accept(GT);
1165 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1166 checkGenerics();
1167 while (token.kind == DOT) {
1168 nextToken();
1169 mode = TYPE;
1170 t = toP(F.at(token.pos).Select(t, ident()));
1171 t = typeArgumentsOpt(t);
1172 }
1173 if (token.kind != HASH) {
1174 //method reference expected here
1175 t = illegal();
1176 }
1177 mode = EXPR;
1178 return term3Rest(t, typeArgs);
1179 }
1180 break loop;
1181 default:
1182 break loop;
1183 }
1184 }
1185 }
1186 if (typeArgs != null) illegal();
1187 t = typeArgumentsOpt(t);
1188 break;
1189 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1190 case DOUBLE: case BOOLEAN:
1191 if (typeArgs != null) illegal();
1192 t = bracketsSuffix(bracketsOpt(basicType()));
1193 break;
1194 case VOID:
1195 if (typeArgs != null) illegal();
1196 if ((mode & EXPR) != 0) {
1197 nextToken();
1198 if (token.kind == DOT) {
1199 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
1200 t = bracketsSuffix(ti);
1201 } else {
1202 return illegal(pos);
1203 }
1204 } else {
1205 // Support the corner case of myMethodHandle.<void>invoke() by passing
1206 // a void type (like other primitive types) to the next phase.
1207 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1208 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
1209 nextToken();
1210 return ti;
1211 //return illegal();
1212 }
1213 break;
1214 default:
1215 return illegal();
1216 }
1217 return term3Rest(t, typeArgs);
1218 }
1220 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1221 if (typeArgs != null) illegal();
1222 while (true) {
1223 int pos1 = token.pos;
1224 if (token.kind == LBRACKET) {
1225 nextToken();
1226 if ((mode & TYPE) != 0) {
1227 int oldmode = mode;
1228 mode = TYPE;
1229 if (token.kind == RBRACKET) {
1230 nextToken();
1231 t = bracketsOpt(t);
1232 t = toP(F.at(pos1).TypeArray(t));
1233 return t;
1234 }
1235 mode = oldmode;
1236 }
1237 if ((mode & EXPR) != 0) {
1238 mode = EXPR;
1239 JCExpression t1 = term();
1240 t = to(F.at(pos1).Indexed(t, t1));
1241 }
1242 accept(RBRACKET);
1243 } else if (token.kind == DOT) {
1244 nextToken();
1245 typeArgs = typeArgumentsOpt(EXPR);
1246 if (token.kind == SUPER && (mode & EXPR) != 0) {
1247 mode = EXPR;
1248 t = to(F.at(pos1).Select(t, names._super));
1249 nextToken();
1250 t = arguments(typeArgs, t);
1251 typeArgs = null;
1252 } else if (token.kind == NEW && (mode & EXPR) != 0) {
1253 if (typeArgs != null) return illegal();
1254 mode = EXPR;
1255 int pos2 = token.pos;
1256 nextToken();
1257 if (token.kind == LT) typeArgs = typeArguments(false);
1258 t = innerCreator(pos2, typeArgs, t);
1259 typeArgs = null;
1260 } else {
1261 t = toP(F.at(pos1).Select(t, ident()));
1262 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1263 typeArgs = null;
1264 }
1265 } else if ((mode & EXPR) != 0 && token.kind == HASH) {
1266 mode = EXPR;
1267 if (typeArgs != null) return illegal();
1268 accept(HASH);
1269 t = memberReferenceSuffix(pos1, t);
1270 } else {
1271 break;
1272 }
1273 }
1274 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
1275 mode = EXPR;
1276 t = to(F.at(token.pos).Unary(
1277 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1278 nextToken();
1279 }
1280 return toP(t);
1281 }
1283 /**
1284 * If we see an identifier followed by a '<' it could be an unbound
1285 * method reference or a binary expression. To disambiguate, look for a
1286 * matching '>' and see if the subsequent terminal is either '.' or '#'.
1287 */
1288 @SuppressWarnings("fallthrough")
1289 boolean isUnboundMemberRef() {
1290 int pos = 0, depth = 0;
1291 for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1292 switch (t.kind) {
1293 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
1294 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1295 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1296 case DOUBLE: case BOOLEAN: case CHAR:
1297 break;
1298 case LT:
1299 depth++; break;
1300 case GTGTGT:
1301 depth--;
1302 case GTGT:
1303 depth--;
1304 case GT:
1305 depth--;
1306 if (depth == 0) {
1307 return
1308 S.token(pos + 1).kind == TokenKind.DOT ||
1309 S.token(pos + 1).kind == TokenKind.HASH;
1310 }
1311 break;
1312 default:
1313 return false;
1314 }
1315 }
1316 }
1318 JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
1319 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
1320 params.append(firstParam);
1321 JCVariableDecl lastParam = firstParam;
1322 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
1323 nextToken();
1324 params.append(lastParam = formalParameter());
1325 }
1326 accept(RPAREN);
1327 return lambdaExpressionOrStatementRest(params.toList(), pos);
1328 }
1330 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
1331 List<JCVariableDecl> params = explicitParams ?
1332 formalParameters() :
1333 implicitParameters(hasParens);
1335 return lambdaExpressionOrStatementRest(params, pos);
1336 }
1338 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
1339 if (token.kind != ARROW) {
1340 //better error recovery
1341 return F.at(pos).Erroneous(args);
1342 }
1344 checkLambda();
1345 accept(ARROW);
1347 return token.kind == LBRACE ?
1348 lambdaStatement(args, pos, pos) :
1349 lambdaExpression(args, pos);
1350 }
1352 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
1353 JCBlock block = block(pos2, 0);
1354 return toP(F.at(pos).Lambda(args, block));
1355 }
1357 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
1358 JCTree expr = parseExpression();
1359 return toP(F.at(pos).Lambda(args, expr));
1360 }
1362 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1363 */
1364 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1365 nextToken();
1366 if (token.kind == LPAREN || typeArgs != null) {
1367 t = arguments(typeArgs, t);
1368 } else if (token.kind == HASH) {
1369 if (typeArgs != null) return illegal();
1370 t = memberReferenceSuffix(t);
1371 } else {
1372 int pos = token.pos;
1373 accept(DOT);
1374 typeArgs = (token.kind == LT) ? typeArguments(false) : null;
1375 t = toP(F.at(pos).Select(t, ident()));
1376 t = argumentsOpt(typeArgs, t);
1377 }
1378 return t;
1379 }
1381 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1382 */
1383 JCPrimitiveTypeTree basicType() {
1384 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
1385 nextToken();
1386 return t;
1387 }
1389 /** ArgumentsOpt = [ Arguments ]
1390 */
1391 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1392 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
1393 mode = EXPR;
1394 return arguments(typeArgs, t);
1395 } else {
1396 return t;
1397 }
1398 }
1400 /** Arguments = "(" [Expression { COMMA Expression }] ")"
1401 */
1402 List<JCExpression> arguments() {
1403 ListBuffer<JCExpression> args = lb();
1404 if (token.kind == LPAREN) {
1405 nextToken();
1406 if (token.kind != RPAREN) {
1407 args.append(parseExpression());
1408 while (token.kind == COMMA) {
1409 nextToken();
1410 args.append(parseExpression());
1411 }
1412 }
1413 accept(RPAREN);
1414 } else {
1415 syntaxError(token.pos, "expected", LPAREN);
1416 }
1417 return args.toList();
1418 }
1420 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1421 int pos = token.pos;
1422 List<JCExpression> args = arguments();
1423 return toP(F.at(pos).Apply(typeArgs, t, args));
1424 }
1426 /** TypeArgumentsOpt = [ TypeArguments ]
1427 */
1428 JCExpression typeArgumentsOpt(JCExpression t) {
1429 if (token.kind == LT &&
1430 (mode & TYPE) != 0 &&
1431 (mode & NOPARAMS) == 0) {
1432 mode = TYPE;
1433 checkGenerics();
1434 return typeArguments(t, false);
1435 } else {
1436 return t;
1437 }
1438 }
1439 List<JCExpression> typeArgumentsOpt() {
1440 return typeArgumentsOpt(TYPE);
1441 }
1443 List<JCExpression> typeArgumentsOpt(int useMode) {
1444 if (token.kind == LT) {
1445 checkGenerics();
1446 if ((mode & useMode) == 0 ||
1447 (mode & NOPARAMS) != 0) {
1448 illegal();
1449 }
1450 mode = useMode;
1451 return typeArguments(false);
1452 }
1453 return null;
1454 }
1456 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1457 */
1458 List<JCExpression> typeArguments(boolean diamondAllowed) {
1459 if (token.kind == LT) {
1460 nextToken();
1461 if (token.kind == GT && diamondAllowed) {
1462 checkDiamond();
1463 mode |= DIAMOND;
1464 nextToken();
1465 return List.nil();
1466 } else {
1467 ListBuffer<JCExpression> args = ListBuffer.lb();
1468 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1469 while (token.kind == COMMA) {
1470 nextToken();
1471 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1472 }
1473 switch (token.kind) {
1475 case GTGTGTEQ: case GTGTEQ: case GTEQ:
1476 case GTGTGT: case GTGT:
1477 token = S.split();
1478 break;
1479 case GT:
1480 nextToken();
1481 break;
1482 default:
1483 args.append(syntaxError(token.pos, "expected", GT));
1484 break;
1485 }
1486 return args.toList();
1487 }
1488 } else {
1489 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
1490 }
1491 }
1493 /** TypeArgument = Type
1494 * | "?"
1495 * | "?" EXTENDS Type {"&" Type}
1496 * | "?" SUPER Type
1497 */
1498 JCExpression typeArgument() {
1499 if (token.kind != QUES) return parseType();
1500 int pos = token.pos;
1501 nextToken();
1502 if (token.kind == EXTENDS) {
1503 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
1504 nextToken();
1505 JCExpression bound = parseType();
1506 return F.at(pos).Wildcard(t, bound);
1507 } else if (token.kind == SUPER) {
1508 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
1509 nextToken();
1510 JCExpression bound = parseType();
1511 return F.at(pos).Wildcard(t, bound);
1512 } else if (token.kind == IDENTIFIER) {
1513 //error recovery
1514 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1515 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1516 JCIdent id = toP(F.at(token.pos).Ident(ident()));
1517 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1518 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
1519 return err;
1520 } else {
1521 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
1522 return toP(F.at(pos).Wildcard(t, null));
1523 }
1524 }
1526 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
1527 int pos = token.pos;
1528 List<JCExpression> args = typeArguments(diamondAllowed);
1529 return toP(F.at(pos).TypeApply(t, args));
1530 }
1532 /** BracketsOpt = {"[" "]"}
1533 */
1534 private JCExpression bracketsOpt(JCExpression t) {
1535 if (token.kind == LBRACKET) {
1536 int pos = token.pos;
1537 nextToken();
1538 t = bracketsOptCont(t, pos);
1539 F.at(pos);
1540 }
1541 return t;
1542 }
1544 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1545 accept(RBRACKET);
1546 t = bracketsOpt(t);
1547 return toP(F.at(pos).TypeArray(t));
1548 }
1550 /** BracketsSuffixExpr = "." CLASS
1551 * BracketsSuffixType =
1552 */
1553 JCExpression bracketsSuffix(JCExpression t) {
1554 if ((mode & EXPR) != 0 && token.kind == DOT) {
1555 mode = EXPR;
1556 int pos = token.pos;
1557 nextToken();
1558 accept(CLASS);
1559 if (token.pos == endPosTable.errorEndPos) {
1560 // error recovery
1561 Name name = null;
1562 if (token.kind == IDENTIFIER) {
1563 name = token.name();
1564 nextToken();
1565 } else {
1566 name = names.error;
1567 }
1568 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1569 } else {
1570 t = toP(F.at(pos).Select(t, names._class));
1571 }
1572 } else if ((mode & TYPE) != 0) {
1573 mode = TYPE;
1574 } else {
1575 syntaxError(token.pos, "dot.class.expected");
1576 }
1577 return t;
1578 }
1580 /**
1581 * MemberReferenceSuffix = "#" [TypeArguments] Ident
1582 * | "#" [TypeArguments] "new"
1583 */
1584 JCExpression memberReferenceSuffix(JCExpression t) {
1585 int pos1 = token.pos;
1586 accept(HASH);
1587 return memberReferenceSuffix(pos1, t);
1588 }
1590 JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
1591 checkMethodReferences();
1592 mode = EXPR;
1593 List<JCExpression> typeArgs = null;
1594 if (token.kind == LT) {
1595 typeArgs = typeArguments(false);
1596 }
1597 Name refName = null;
1598 ReferenceMode refMode = null;
1599 if (token.kind == NEW) {
1600 refMode = ReferenceMode.NEW;
1601 refName = names.init;
1602 nextToken();
1603 } else {
1604 refMode = ReferenceMode.INVOKE;
1605 refName = ident();
1606 }
1607 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
1608 }
1610 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1611 */
1612 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1613 switch (token.kind) {
1614 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1615 case DOUBLE: case BOOLEAN:
1616 if (typeArgs == null)
1617 return arrayCreatorRest(newpos, basicType());
1618 break;
1619 default:
1620 }
1621 JCExpression t = qualident();
1622 int oldmode = mode;
1623 mode = TYPE;
1624 boolean diamondFound = false;
1625 int lastTypeargsPos = -1;
1626 if (token.kind == LT) {
1627 checkGenerics();
1628 lastTypeargsPos = token.pos;
1629 t = typeArguments(t, true);
1630 diamondFound = (mode & DIAMOND) != 0;
1631 }
1632 while (token.kind == DOT) {
1633 if (diamondFound) {
1634 //cannot select after a diamond
1635 illegal();
1636 }
1637 int pos = token.pos;
1638 nextToken();
1639 t = toP(F.at(pos).Select(t, ident()));
1640 if (token.kind == LT) {
1641 lastTypeargsPos = token.pos;
1642 checkGenerics();
1643 t = typeArguments(t, true);
1644 diamondFound = (mode & DIAMOND) != 0;
1645 }
1646 }
1647 mode = oldmode;
1648 if (token.kind == LBRACKET) {
1649 JCExpression e = arrayCreatorRest(newpos, t);
1650 if (diamondFound) {
1651 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
1652 return toP(F.at(newpos).Erroneous(List.of(e)));
1653 }
1654 else if (typeArgs != null) {
1655 int pos = newpos;
1656 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1657 // note: this should always happen but we should
1658 // not rely on this as the parser is continuously
1659 // modified to improve error recovery.
1660 pos = typeArgs.head.pos;
1661 }
1662 setErrorEndPos(S.prevToken().endPos);
1663 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
1664 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
1665 return toP(err);
1666 }
1667 return e;
1668 } else if (token.kind == LPAREN) {
1669 return classCreatorRest(newpos, null, typeArgs, t);
1670 } else {
1671 setErrorEndPos(token.pos);
1672 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
1673 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1674 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1675 }
1676 }
1678 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1679 */
1680 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1681 JCExpression t = toP(F.at(token.pos).Ident(ident()));
1682 if (token.kind == LT) {
1683 int oldmode = mode;
1684 checkGenerics();
1685 t = typeArguments(t, true);
1686 mode = oldmode;
1687 }
1688 return classCreatorRest(newpos, encl, typeArgs, t);
1689 }
1691 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1692 * | Expression "]" {"[" Expression "]"} BracketsOpt )
1693 */
1694 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1695 accept(LBRACKET);
1696 if (token.kind == RBRACKET) {
1697 accept(RBRACKET);
1698 elemtype = bracketsOpt(elemtype);
1699 if (token.kind == LBRACE) {
1700 return arrayInitializer(newpos, elemtype);
1701 } else {
1702 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
1703 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
1704 }
1705 } else {
1706 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1707 dims.append(parseExpression());
1708 accept(RBRACKET);
1709 while (token.kind == LBRACKET) {
1710 int pos = token.pos;
1711 nextToken();
1712 if (token.kind == RBRACKET) {
1713 elemtype = bracketsOptCont(elemtype, pos);
1714 } else {
1715 dims.append(parseExpression());
1716 accept(RBRACKET);
1717 }
1718 }
1719 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1720 }
1721 }
1723 /** ClassCreatorRest = Arguments [ClassBody]
1724 */
1725 JCNewClass classCreatorRest(int newpos,
1726 JCExpression encl,
1727 List<JCExpression> typeArgs,
1728 JCExpression t)
1729 {
1730 List<JCExpression> args = arguments();
1731 JCClassDecl body = null;
1732 if (token.kind == LBRACE) {
1733 int pos = token.pos;
1734 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1735 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1736 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1737 }
1738 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1739 }
1741 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1742 */
1743 JCExpression arrayInitializer(int newpos, JCExpression t) {
1744 accept(LBRACE);
1745 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1746 if (token.kind == COMMA) {
1747 nextToken();
1748 } else if (token.kind != RBRACE) {
1749 elems.append(variableInitializer());
1750 while (token.kind == COMMA) {
1751 nextToken();
1752 if (token.kind == RBRACE) break;
1753 elems.append(variableInitializer());
1754 }
1755 }
1756 accept(RBRACE);
1757 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1758 }
1760 /** VariableInitializer = ArrayInitializer | Expression
1761 */
1762 public JCExpression variableInitializer() {
1763 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
1764 }
1766 /** ParExpression = "(" Expression ")"
1767 */
1768 JCExpression parExpression() {
1769 int pos = token.pos;
1770 accept(LPAREN);
1771 JCExpression t = parseExpression();
1772 accept(RPAREN);
1773 return toP(F.at(pos).Parens(t));
1774 }
1776 /** Block = "{" BlockStatements "}"
1777 */
1778 JCBlock block(int pos, long flags) {
1779 accept(LBRACE);
1780 List<JCStatement> stats = blockStatements();
1781 JCBlock t = F.at(pos).Block(flags, stats);
1782 while (token.kind == CASE || token.kind == DEFAULT) {
1783 syntaxError("orphaned", token.kind);
1784 switchBlockStatementGroups();
1785 }
1786 // the Block node has a field "endpos" for first char of last token, which is
1787 // usually but not necessarily the last char of the last token.
1788 t.endpos = token.pos;
1789 accept(RBRACE);
1790 return toP(t);
1791 }
1793 public JCBlock block() {
1794 return block(token.pos, 0);
1795 }
1797 /** BlockStatements = { BlockStatement }
1798 * BlockStatement = LocalVariableDeclarationStatement
1799 * | ClassOrInterfaceOrEnumDeclaration
1800 * | [Ident ":"] Statement
1801 * LocalVariableDeclarationStatement
1802 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1803 */
1804 @SuppressWarnings("fallthrough")
1805 List<JCStatement> blockStatements() {
1806 //todo: skip to anchor on error(?)
1807 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1808 while (true) {
1809 List<JCStatement> stat = blockStatement();
1810 if (stat.isEmpty()) {
1811 return stats.toList();
1812 } else {
1813 if (token.pos <= endPosTable.errorEndPos) {
1814 skip(false, true, true, true);
1815 }
1816 stats.addAll(stat);
1817 }
1818 }
1819 }
1821 /*
1822 * This method parses a statement treating it as a block, relaxing the
1823 * JLS restrictions, allows us to parse more faulty code, doing so
1824 * enables us to provide better and accurate diagnostics to the user.
1825 */
1826 JCStatement parseStatementAsBlock() {
1827 int pos = token.pos;
1828 List<JCStatement> stats = blockStatement();
1829 if (stats.isEmpty()) {
1830 JCErroneous e = F.at(pos).Erroneous();
1831 error(e, "illegal.start.of.stmt");
1832 return F.at(pos).Exec(e);
1833 } else {
1834 JCStatement first = stats.head;
1835 String error = null;
1836 switch (first.getTag()) {
1837 case CLASSDEF:
1838 error = "class.not.allowed";
1839 break;
1840 case VARDEF:
1841 error = "variable.not.allowed";
1842 break;
1843 }
1844 if (error != null) {
1845 error(first, error);
1846 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
1847 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
1848 }
1849 return first;
1850 }
1851 }
1853 @SuppressWarnings("fallthrough")
1854 List<JCStatement> blockStatement() {
1855 //todo: skip to anchor on error(?)
1856 int pos = token.pos;
1857 switch (token.kind) {
1858 case RBRACE: case CASE: case DEFAULT: case EOF:
1859 return List.nil();
1860 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1861 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1862 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1863 return List.of(parseStatement());
1864 case MONKEYS_AT:
1865 case FINAL: {
1866 Comment dc = token.comment(CommentStyle.JAVADOC);
1867 JCModifiers mods = modifiersOpt();
1868 if (token.kind == INTERFACE ||
1869 token.kind == CLASS ||
1870 allowEnums && token.kind == ENUM) {
1871 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
1872 } else {
1873 JCExpression t = parseType();
1874 ListBuffer<JCStatement> stats =
1875 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
1876 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1877 storeEnd(stats.elems.last(), token.endPos);
1878 accept(SEMI);
1879 return stats.toList();
1880 }
1881 }
1882 case ABSTRACT: case STRICTFP: {
1883 Comment dc = token.comment(CommentStyle.JAVADOC);
1884 JCModifiers mods = modifiersOpt();
1885 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
1886 }
1887 case INTERFACE:
1888 case CLASS:
1889 Comment dc = token.comment(CommentStyle.JAVADOC);
1890 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
1891 case ENUM:
1892 case ASSERT:
1893 if (allowEnums && token.kind == ENUM) {
1894 error(token.pos, "local.enum");
1895 dc = token.comment(CommentStyle.JAVADOC);
1896 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
1897 } else if (allowAsserts && token.kind == ASSERT) {
1898 return List.of(parseStatement());
1899 }
1900 /* fall through to default */
1901 default:
1902 Token prevToken = token;
1903 JCExpression t = term(EXPR | TYPE);
1904 if (token.kind == COLON && t.hasTag(IDENT)) {
1905 nextToken();
1906 JCStatement stat = parseStatement();
1907 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
1908 } else if ((lastmode & TYPE) != 0 &&
1909 (token.kind == IDENTIFIER ||
1910 token.kind == ASSERT ||
1911 token.kind == ENUM)) {
1912 pos = token.pos;
1913 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1914 F.at(pos);
1915 ListBuffer<JCStatement> stats =
1916 variableDeclarators(mods, t, new ListBuffer<JCStatement>());
1917 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1918 storeEnd(stats.elems.last(), token.endPos);
1919 accept(SEMI);
1920 return stats.toList();
1921 } else {
1922 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1923 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
1924 accept(SEMI);
1925 return List.<JCStatement>of(expr);
1926 }
1927 }
1928 }
1930 /** Statement =
1931 * Block
1932 * | IF ParExpression Statement [ELSE Statement]
1933 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1934 * | FOR "(" FormalParameter : Expression ")" Statement
1935 * | WHILE ParExpression Statement
1936 * | DO Statement WHILE ParExpression ";"
1937 * | TRY Block ( Catches | [Catches] FinallyPart )
1938 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
1939 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1940 * | SYNCHRONIZED ParExpression Block
1941 * | RETURN [Expression] ";"
1942 * | THROW Expression ";"
1943 * | BREAK [Ident] ";"
1944 * | CONTINUE [Ident] ";"
1945 * | ASSERT Expression [ ":" Expression ] ";"
1946 * | ";"
1947 * | ExpressionStatement
1948 * | Ident ":" Statement
1949 */
1950 @SuppressWarnings("fallthrough")
1951 public JCStatement parseStatement() {
1952 int pos = token.pos;
1953 switch (token.kind) {
1954 case LBRACE:
1955 return block();
1956 case IF: {
1957 nextToken();
1958 JCExpression cond = parExpression();
1959 JCStatement thenpart = parseStatementAsBlock();
1960 JCStatement elsepart = null;
1961 if (token.kind == ELSE) {
1962 nextToken();
1963 elsepart = parseStatementAsBlock();
1964 }
1965 return F.at(pos).If(cond, thenpart, elsepart);
1966 }
1967 case FOR: {
1968 nextToken();
1969 accept(LPAREN);
1970 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
1971 if (inits.length() == 1 &&
1972 inits.head.hasTag(VARDEF) &&
1973 ((JCVariableDecl) inits.head).init == null &&
1974 token.kind == COLON) {
1975 checkForeach();
1976 JCVariableDecl var = (JCVariableDecl)inits.head;
1977 accept(COLON);
1978 JCExpression expr = parseExpression();
1979 accept(RPAREN);
1980 JCStatement body = parseStatementAsBlock();
1981 return F.at(pos).ForeachLoop(var, expr, body);
1982 } else {
1983 accept(SEMI);
1984 JCExpression cond = token.kind == SEMI ? null : parseExpression();
1985 accept(SEMI);
1986 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
1987 accept(RPAREN);
1988 JCStatement body = parseStatementAsBlock();
1989 return F.at(pos).ForLoop(inits, cond, steps, body);
1990 }
1991 }
1992 case WHILE: {
1993 nextToken();
1994 JCExpression cond = parExpression();
1995 JCStatement body = parseStatementAsBlock();
1996 return F.at(pos).WhileLoop(cond, body);
1997 }
1998 case DO: {
1999 nextToken();
2000 JCStatement body = parseStatementAsBlock();
2001 accept(WHILE);
2002 JCExpression cond = parExpression();
2003 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
2004 accept(SEMI);
2005 return t;
2006 }
2007 case TRY: {
2008 nextToken();
2009 List<JCTree> resources = List.<JCTree>nil();
2010 if (token.kind == LPAREN) {
2011 checkTryWithResources();
2012 nextToken();
2013 resources = resources();
2014 accept(RPAREN);
2015 }
2016 JCBlock body = block();
2017 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
2018 JCBlock finalizer = null;
2019 if (token.kind == CATCH || token.kind == FINALLY) {
2020 while (token.kind == CATCH) catchers.append(catchClause());
2021 if (token.kind == FINALLY) {
2022 nextToken();
2023 finalizer = block();
2024 }
2025 } else {
2026 if (allowTWR) {
2027 if (resources.isEmpty())
2028 error(pos, "try.without.catch.finally.or.resource.decls");
2029 } else
2030 error(pos, "try.without.catch.or.finally");
2031 }
2032 return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
2033 }
2034 case SWITCH: {
2035 nextToken();
2036 JCExpression selector = parExpression();
2037 accept(LBRACE);
2038 List<JCCase> cases = switchBlockStatementGroups();
2039 JCSwitch t = to(F.at(pos).Switch(selector, cases));
2040 accept(RBRACE);
2041 return t;
2042 }
2043 case SYNCHRONIZED: {
2044 nextToken();
2045 JCExpression lock = parExpression();
2046 JCBlock body = block();
2047 return F.at(pos).Synchronized(lock, body);
2048 }
2049 case RETURN: {
2050 nextToken();
2051 JCExpression result = token.kind == SEMI ? null : parseExpression();
2052 JCReturn t = to(F.at(pos).Return(result));
2053 accept(SEMI);
2054 return t;
2055 }
2056 case THROW: {
2057 nextToken();
2058 JCExpression exc = parseExpression();
2059 JCThrow t = to(F.at(pos).Throw(exc));
2060 accept(SEMI);
2061 return t;
2062 }
2063 case BREAK: {
2064 nextToken();
2065 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
2066 JCBreak t = to(F.at(pos).Break(label));
2067 accept(SEMI);
2068 return t;
2069 }
2070 case CONTINUE: {
2071 nextToken();
2072 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
2073 JCContinue t = to(F.at(pos).Continue(label));
2074 accept(SEMI);
2075 return t;
2076 }
2077 case SEMI:
2078 nextToken();
2079 return toP(F.at(pos).Skip());
2080 case ELSE:
2081 return toP(F.Exec(syntaxError("else.without.if")));
2082 case FINALLY:
2083 return toP(F.Exec(syntaxError("finally.without.try")));
2084 case CATCH:
2085 return toP(F.Exec(syntaxError("catch.without.try")));
2086 case ASSERT: {
2087 if (allowAsserts && token.kind == ASSERT) {
2088 nextToken();
2089 JCExpression assertion = parseExpression();
2090 JCExpression message = null;
2091 if (token.kind == COLON) {
2092 nextToken();
2093 message = parseExpression();
2094 }
2095 JCAssert t = to(F.at(pos).Assert(assertion, message));
2096 accept(SEMI);
2097 return t;
2098 }
2099 /* else fall through to default case */
2100 }
2101 case ENUM:
2102 default:
2103 Token prevToken = token;
2104 JCExpression expr = parseExpression();
2105 if (token.kind == COLON && expr.hasTag(IDENT)) {
2106 nextToken();
2107 JCStatement stat = parseStatement();
2108 return F.at(pos).Labelled(prevToken.name(), stat);
2109 } else {
2110 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2111 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
2112 accept(SEMI);
2113 return stat;
2114 }
2115 }
2116 }
2118 /** CatchClause = CATCH "(" FormalParameter ")" Block
2119 */
2120 protected JCCatch catchClause() {
2121 int pos = token.pos;
2122 accept(CATCH);
2123 accept(LPAREN);
2124 JCModifiers mods = optFinal(Flags.PARAMETER);
2125 List<JCExpression> catchTypes = catchTypes();
2126 JCExpression paramType = catchTypes.size() > 1 ?
2127 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
2128 catchTypes.head;
2129 JCVariableDecl formal = variableDeclaratorId(mods, paramType);
2130 accept(RPAREN);
2131 JCBlock body = block();
2132 return F.at(pos).Catch(formal, body);
2133 }
2135 List<JCExpression> catchTypes() {
2136 ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
2137 catchTypes.add(parseType());
2138 while (token.kind == BAR) {
2139 checkMulticatch();
2140 nextToken();
2141 catchTypes.add(qualident());
2142 }
2143 return catchTypes.toList();
2144 }
2146 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
2147 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
2148 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
2149 */
2150 List<JCCase> switchBlockStatementGroups() {
2151 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
2152 while (true) {
2153 int pos = token.pos;
2154 switch (token.kind) {
2155 case CASE: {
2156 nextToken();
2157 JCExpression pat = parseExpression();
2158 accept(COLON);
2159 List<JCStatement> stats = blockStatements();
2160 JCCase c = F.at(pos).Case(pat, stats);
2161 if (stats.isEmpty())
2162 storeEnd(c, S.prevToken().endPos);
2163 cases.append(c);
2164 break;
2165 }
2166 case DEFAULT: {
2167 nextToken();
2168 accept(COLON);
2169 List<JCStatement> stats = blockStatements();
2170 JCCase c = F.at(pos).Case(null, stats);
2171 if (stats.isEmpty())
2172 storeEnd(c, S.prevToken().endPos);
2173 cases.append(c);
2174 break;
2175 }
2176 case RBRACE: case EOF:
2177 return cases.toList();
2178 default:
2179 nextToken(); // to ensure progress
2180 syntaxError(pos, "expected3",
2181 CASE, DEFAULT, RBRACE);
2182 }
2183 }
2184 }
2186 /** MoreStatementExpressions = { COMMA StatementExpression }
2187 */
2188 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
2189 JCExpression first,
2190 T stats) {
2191 // This Exec is a "StatementExpression"; it subsumes no terminating token
2192 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
2193 while (token.kind == COMMA) {
2194 nextToken();
2195 pos = token.pos;
2196 JCExpression t = parseExpression();
2197 // This Exec is a "StatementExpression"; it subsumes no terminating token
2198 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
2199 }
2200 return stats;
2201 }
2203 /** ForInit = StatementExpression MoreStatementExpressions
2204 * | { FINAL | '@' Annotation } Type VariableDeclarators
2205 */
2206 List<JCStatement> forInit() {
2207 ListBuffer<JCStatement> stats = lb();
2208 int pos = token.pos;
2209 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
2210 return variableDeclarators(optFinal(0), parseType(), stats).toList();
2211 } else {
2212 JCExpression t = term(EXPR | TYPE);
2213 if ((lastmode & TYPE) != 0 &&
2214 (token.kind == IDENTIFIER || token.kind == ASSERT ||
2215 token.kind == ENUM)) {
2216 return variableDeclarators(modifiersOpt(), t, stats).toList();
2217 } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
2218 error(pos, "bad.initializer", "for-loop");
2219 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
2220 } else {
2221 return moreStatementExpressions(pos, t, stats).toList();
2222 }
2223 }
2224 }
2226 /** ForUpdate = StatementExpression MoreStatementExpressions
2227 */
2228 List<JCExpressionStatement> forUpdate() {
2229 return moreStatementExpressions(token.pos,
2230 parseExpression(),
2231 new ListBuffer<JCExpressionStatement>()).toList();
2232 }
2234 /** AnnotationsOpt = { '@' Annotation }
2235 */
2236 List<JCAnnotation> annotationsOpt() {
2237 if (token.kind != MONKEYS_AT) return List.nil(); // optimization
2238 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
2239 while (token.kind == MONKEYS_AT) {
2240 int pos = token.pos;
2241 nextToken();
2242 buf.append(annotation(pos));
2243 }
2244 return buf.toList();
2245 }
2247 /** ModifiersOpt = { Modifier }
2248 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
2249 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
2250 * | "@" Annotation
2251 */
2252 JCModifiers modifiersOpt() {
2253 return modifiersOpt(null);
2254 }
2255 protected JCModifiers modifiersOpt(JCModifiers partial) {
2256 long flags;
2257 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
2258 int pos;
2259 if (partial == null) {
2260 flags = 0;
2261 pos = token.pos;
2262 } else {
2263 flags = partial.flags;
2264 annotations.appendList(partial.annotations);
2265 pos = partial.pos;
2266 }
2267 if (token.deprecatedFlag()) {
2268 flags |= Flags.DEPRECATED;
2269 }
2270 int lastPos = Position.NOPOS;
2271 loop:
2272 while (true) {
2273 long flag;
2274 switch (token.kind) {
2275 case PRIVATE : flag = Flags.PRIVATE; break;
2276 case PROTECTED : flag = Flags.PROTECTED; break;
2277 case PUBLIC : flag = Flags.PUBLIC; break;
2278 case STATIC : flag = Flags.STATIC; break;
2279 case TRANSIENT : flag = Flags.TRANSIENT; break;
2280 case FINAL : flag = Flags.FINAL; break;
2281 case ABSTRACT : flag = Flags.ABSTRACT; break;
2282 case NATIVE : flag = Flags.NATIVE; break;
2283 case VOLATILE : flag = Flags.VOLATILE; break;
2284 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
2285 case STRICTFP : flag = Flags.STRICTFP; break;
2286 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
2287 case ERROR : flag = 0; nextToken(); break;
2288 default: break loop;
2289 }
2290 if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
2291 lastPos = token.pos;
2292 nextToken();
2293 if (flag == Flags.ANNOTATION) {
2294 checkAnnotations();
2295 if (token.kind != INTERFACE) {
2296 JCAnnotation ann = annotation(lastPos);
2297 // if first modifier is an annotation, set pos to annotation's.
2298 if (flags == 0 && annotations.isEmpty())
2299 pos = ann.pos;
2300 annotations.append(ann);
2301 lastPos = ann.pos;
2302 flag = 0;
2303 }
2304 }
2305 flags |= flag;
2306 }
2307 switch (token.kind) {
2308 case ENUM: flags |= Flags.ENUM; break;
2309 case INTERFACE: flags |= Flags.INTERFACE; break;
2310 default: break;
2311 }
2313 /* A modifiers tree with no modifier tokens or annotations
2314 * has no text position. */
2315 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
2316 pos = Position.NOPOS;
2318 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
2319 if (pos != Position.NOPOS)
2320 storeEnd(mods, S.prevToken().endPos);
2321 return mods;
2322 }
2324 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2325 * @param pos position of "@" token
2326 */
2327 JCAnnotation annotation(int pos) {
2328 // accept(AT); // AT consumed by caller
2329 checkAnnotations();
2330 JCTree ident = qualident();
2331 List<JCExpression> fieldValues = annotationFieldValuesOpt();
2332 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
2333 storeEnd(ann, S.prevToken().endPos);
2334 return ann;
2335 }
2337 List<JCExpression> annotationFieldValuesOpt() {
2338 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2339 }
2341 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2342 List<JCExpression> annotationFieldValues() {
2343 accept(LPAREN);
2344 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2345 if (token.kind != RPAREN) {
2346 buf.append(annotationFieldValue());
2347 while (token.kind == COMMA) {
2348 nextToken();
2349 buf.append(annotationFieldValue());
2350 }
2351 }
2352 accept(RPAREN);
2353 return buf.toList();
2354 }
2356 /** AnnotationFieldValue = AnnotationValue
2357 * | Identifier "=" AnnotationValue
2358 */
2359 JCExpression annotationFieldValue() {
2360 if (token.kind == IDENTIFIER) {
2361 mode = EXPR;
2362 JCExpression t1 = term1();
2363 if (t1.hasTag(IDENT) && token.kind == EQ) {
2364 int pos = token.pos;
2365 accept(EQ);
2366 JCExpression v = annotationValue();
2367 return toP(F.at(pos).Assign(t1, v));
2368 } else {
2369 return t1;
2370 }
2371 }
2372 return annotationValue();
2373 }
2375 /* AnnotationValue = ConditionalExpression
2376 * | Annotation
2377 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2378 */
2379 JCExpression annotationValue() {
2380 int pos;
2381 switch (token.kind) {
2382 case MONKEYS_AT:
2383 pos = token.pos;
2384 nextToken();
2385 return annotation(pos);
2386 case LBRACE:
2387 pos = token.pos;
2388 accept(LBRACE);
2389 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2390 if (token.kind != RBRACE) {
2391 buf.append(annotationValue());
2392 while (token.kind == COMMA) {
2393 nextToken();
2394 if (token.kind == RBRACE) break;
2395 buf.append(annotationValue());
2396 }
2397 }
2398 accept(RBRACE);
2399 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2400 default:
2401 mode = EXPR;
2402 return term1();
2403 }
2404 }
2406 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2407 */
2408 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2409 JCExpression type,
2410 T vdefs)
2411 {
2412 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
2413 }
2415 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2416 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2417 *
2418 * @param reqInit Is an initializer always required?
2419 * @param dc The documentation comment for the variable declarations, or null.
2420 */
2421 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2422 JCModifiers mods,
2423 JCExpression type,
2424 Name name,
2425 boolean reqInit,
2426 Comment dc,
2427 T vdefs)
2428 {
2429 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2430 while (token.kind == COMMA) {
2431 // All but last of multiple declarators subsume a comma
2432 storeEnd((JCTree)vdefs.elems.last(), token.endPos);
2433 nextToken();
2434 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2435 }
2436 return vdefs;
2437 }
2439 /** VariableDeclarator = Ident VariableDeclaratorRest
2440 * ConstantDeclarator = Ident ConstantDeclaratorRest
2441 */
2442 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
2443 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
2444 }
2446 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2447 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2448 *
2449 * @param reqInit Is an initializer always required?
2450 * @param dc The documentation comment for the variable declarations, or null.
2451 */
2452 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2453 boolean reqInit, Comment dc) {
2454 type = bracketsOpt(type);
2455 JCExpression init = null;
2456 if (token.kind == EQ) {
2457 nextToken();
2458 init = variableInitializer();
2459 }
2460 else if (reqInit) syntaxError(token.pos, "expected", EQ);
2461 JCVariableDecl result =
2462 toP(F.at(pos).VarDef(mods, name, type, init));
2463 attach(result, dc);
2464 return result;
2465 }
2467 /** VariableDeclaratorId = Ident BracketsOpt
2468 */
2469 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2470 int pos = token.pos;
2471 Name name = ident();
2472 if ((mods.flags & Flags.VARARGS) != 0 &&
2473 token.kind == LBRACKET) {
2474 log.error(token.pos, "varargs.and.old.array.syntax");
2475 }
2476 type = bracketsOpt(type);
2477 return toP(F.at(pos).VarDef(mods, name, type, null));
2478 }
2480 /** Resources = Resource { ";" Resources }
2481 */
2482 List<JCTree> resources() {
2483 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2484 defs.append(resource());
2485 while (token.kind == SEMI) {
2486 // All but last of multiple declarators must subsume a semicolon
2487 storeEnd(defs.elems.last(), token.endPos);
2488 int semiColonPos = token.pos;
2489 nextToken();
2490 if (token.kind == RPAREN) { // Optional trailing semicolon
2491 // after last resource
2492 break;
2493 }
2494 defs.append(resource());
2495 }
2496 return defs.toList();
2497 }
2499 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
2500 */
2501 protected JCTree resource() {
2502 JCModifiers optFinal = optFinal(Flags.FINAL);
2503 JCExpression type = parseType();
2504 int pos = token.pos;
2505 Name ident = ident();
2506 return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
2507 }
2509 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2510 */
2511 public JCTree.JCCompilationUnit parseCompilationUnit() {
2512 Token firstToken = token;
2513 JCExpression pid = null;
2514 JCModifiers mods = null;
2515 boolean consumedToplevelDoc = false;
2516 boolean seenImport = false;
2517 boolean seenPackage = false;
2518 List<JCAnnotation> packageAnnotations = List.nil();
2519 if (token.kind == MONKEYS_AT)
2520 mods = modifiersOpt();
2522 if (token.kind == PACKAGE) {
2523 seenPackage = true;
2524 if (mods != null) {
2525 checkNoMods(mods.flags);
2526 packageAnnotations = mods.annotations;
2527 mods = null;
2528 }
2529 nextToken();
2530 pid = qualident();
2531 accept(SEMI);
2532 }
2533 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2534 boolean checkForImports = true;
2535 boolean firstTypeDecl = true;
2536 while (token.kind != EOF) {
2537 if (token.pos <= endPosTable.errorEndPos) {
2538 // error recovery
2539 skip(checkForImports, false, false, false);
2540 if (token.kind == EOF)
2541 break;
2542 }
2543 if (checkForImports && mods == null && token.kind == IMPORT) {
2544 seenImport = true;
2545 defs.append(importDeclaration());
2546 } else {
2547 Comment docComment = token.comment(CommentStyle.JAVADOC);
2548 if (firstTypeDecl && !seenImport && !seenPackage) {
2549 docComment = firstToken.comment(CommentStyle.JAVADOC);
2550 consumedToplevelDoc = true;
2551 }
2552 JCTree def = typeDeclaration(mods, docComment);
2553 if (def instanceof JCExpressionStatement)
2554 def = ((JCExpressionStatement)def).expr;
2555 defs.append(def);
2556 if (def instanceof JCClassDecl)
2557 checkForImports = false;
2558 mods = null;
2559 firstTypeDecl = false;
2560 }
2561 }
2562 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
2563 if (!consumedToplevelDoc)
2564 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
2565 if (defs.elems.isEmpty())
2566 storeEnd(toplevel, S.prevToken().endPos);
2567 if (keepDocComments)
2568 toplevel.docComments = docComments;
2569 if (keepLineMap)
2570 toplevel.lineMap = S.getLineMap();
2571 toplevel.endPositions = this.endPosTable;
2572 return toplevel;
2573 }
2575 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2576 */
2577 JCTree importDeclaration() {
2578 int pos = token.pos;
2579 nextToken();
2580 boolean importStatic = false;
2581 if (token.kind == STATIC) {
2582 checkStaticImports();
2583 importStatic = true;
2584 nextToken();
2585 }
2586 JCExpression pid = toP(F.at(token.pos).Ident(ident()));
2587 do {
2588 int pos1 = token.pos;
2589 accept(DOT);
2590 if (token.kind == STAR) {
2591 pid = to(F.at(pos1).Select(pid, names.asterisk));
2592 nextToken();
2593 break;
2594 } else {
2595 pid = toP(F.at(pos1).Select(pid, ident()));
2596 }
2597 } while (token.kind == DOT);
2598 accept(SEMI);
2599 return toP(F.at(pos).Import(pid, importStatic));
2600 }
2602 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2603 * | ";"
2604 */
2605 JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
2606 int pos = token.pos;
2607 if (mods == null && token.kind == SEMI) {
2608 nextToken();
2609 return toP(F.at(pos).Skip());
2610 } else {
2611 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
2612 }
2613 }
2615 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2616 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2617 * @param mods Any modifiers starting the class or interface declaration
2618 * @param dc The documentation comment for the class, or null.
2619 */
2620 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
2621 if (token.kind == CLASS) {
2622 return classDeclaration(mods, dc);
2623 } else if (token.kind == INTERFACE) {
2624 return interfaceDeclaration(mods, dc);
2625 } else if (allowEnums) {
2626 if (token.kind == ENUM) {
2627 return enumDeclaration(mods, dc);
2628 } else {
2629 int pos = token.pos;
2630 List<JCTree> errs;
2631 if (token.kind == IDENTIFIER) {
2632 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2633 setErrorEndPos(token.pos);
2634 } else {
2635 errs = List.<JCTree>of(mods);
2636 }
2637 return toP(F.Exec(syntaxError(pos, errs, "expected3",
2638 CLASS, INTERFACE, ENUM)));
2639 }
2640 } else {
2641 if (token.kind == ENUM) {
2642 error(token.pos, "enums.not.supported.in.source", source.name);
2643 allowEnums = true;
2644 return enumDeclaration(mods, dc);
2645 }
2646 int pos = token.pos;
2647 List<JCTree> errs;
2648 if (token.kind == IDENTIFIER) {
2649 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2650 setErrorEndPos(token.pos);
2651 } else {
2652 errs = List.<JCTree>of(mods);
2653 }
2654 return toP(F.Exec(syntaxError(pos, errs, "expected2",
2655 CLASS, INTERFACE)));
2656 }
2657 }
2659 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2660 * [IMPLEMENTS TypeList] ClassBody
2661 * @param mods The modifiers starting the class declaration
2662 * @param dc The documentation comment for the class, or null.
2663 */
2664 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
2665 int pos = token.pos;
2666 accept(CLASS);
2667 Name name = ident();
2669 List<JCTypeParameter> typarams = typeParametersOpt();
2671 JCExpression extending = null;
2672 if (token.kind == EXTENDS) {
2673 nextToken();
2674 extending = parseType();
2675 }
2676 List<JCExpression> implementing = List.nil();
2677 if (token.kind == IMPLEMENTS) {
2678 nextToken();
2679 implementing = typeList();
2680 }
2681 List<JCTree> defs = classOrInterfaceBody(name, false);
2682 JCClassDecl result = toP(F.at(pos).ClassDef(
2683 mods, name, typarams, extending, implementing, defs));
2684 attach(result, dc);
2685 return result;
2686 }
2688 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2689 * [EXTENDS TypeList] InterfaceBody
2690 * @param mods The modifiers starting the interface declaration
2691 * @param dc The documentation comment for the interface, or null.
2692 */
2693 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
2694 int pos = token.pos;
2695 accept(INTERFACE);
2696 Name name = ident();
2698 List<JCTypeParameter> typarams = typeParametersOpt();
2700 List<JCExpression> extending = List.nil();
2701 if (token.kind == EXTENDS) {
2702 nextToken();
2703 extending = typeList();
2704 }
2705 List<JCTree> defs = classOrInterfaceBody(name, true);
2706 JCClassDecl result = toP(F.at(pos).ClassDef(
2707 mods, name, typarams, null, extending, defs));
2708 attach(result, dc);
2709 return result;
2710 }
2712 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2713 * @param mods The modifiers starting the enum declaration
2714 * @param dc The documentation comment for the enum, or null.
2715 */
2716 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
2717 int pos = token.pos;
2718 accept(ENUM);
2719 Name name = ident();
2721 List<JCExpression> implementing = List.nil();
2722 if (token.kind == IMPLEMENTS) {
2723 nextToken();
2724 implementing = typeList();
2725 }
2727 List<JCTree> defs = enumBody(name);
2728 mods.flags |= Flags.ENUM;
2729 JCClassDecl result = toP(F.at(pos).
2730 ClassDef(mods, name, List.<JCTypeParameter>nil(),
2731 null, implementing, defs));
2732 attach(result, dc);
2733 return result;
2734 }
2736 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2737 * [ ";" {ClassBodyDeclaration} ] "}"
2738 */
2739 List<JCTree> enumBody(Name enumName) {
2740 accept(LBRACE);
2741 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2742 if (token.kind == COMMA) {
2743 nextToken();
2744 } else if (token.kind != RBRACE && token.kind != SEMI) {
2745 defs.append(enumeratorDeclaration(enumName));
2746 while (token.kind == COMMA) {
2747 nextToken();
2748 if (token.kind == RBRACE || token.kind == SEMI) break;
2749 defs.append(enumeratorDeclaration(enumName));
2750 }
2751 if (token.kind != SEMI && token.kind != RBRACE) {
2752 defs.append(syntaxError(token.pos, "expected3",
2753 COMMA, RBRACE, SEMI));
2754 nextToken();
2755 }
2756 }
2757 if (token.kind == SEMI) {
2758 nextToken();
2759 while (token.kind != RBRACE && token.kind != EOF) {
2760 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2761 false));
2762 if (token.pos <= endPosTable.errorEndPos) {
2763 // error recovery
2764 skip(false, true, true, false);
2765 }
2766 }
2767 }
2768 accept(RBRACE);
2769 return defs.toList();
2770 }
2772 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2773 */
2774 JCTree enumeratorDeclaration(Name enumName) {
2775 Comment dc = token.comment(CommentStyle.JAVADOC);
2776 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2777 if (token.deprecatedFlag()) {
2778 flags |= Flags.DEPRECATED;
2779 }
2780 int pos = token.pos;
2781 List<JCAnnotation> annotations = annotationsOpt();
2782 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2783 List<JCExpression> typeArgs = typeArgumentsOpt();
2784 int identPos = token.pos;
2785 Name name = ident();
2786 int createPos = token.pos;
2787 List<JCExpression> args = (token.kind == LPAREN)
2788 ? arguments() : List.<JCExpression>nil();
2789 JCClassDecl body = null;
2790 if (token.kind == LBRACE) {
2791 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2792 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2793 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2794 }
2795 if (args.isEmpty() && body == null)
2796 createPos = identPos;
2797 JCIdent ident = F.at(identPos).Ident(enumName);
2798 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2799 if (createPos != identPos)
2800 storeEnd(create, S.prevToken().endPos);
2801 ident = F.at(identPos).Ident(enumName);
2802 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2803 attach(result, dc);
2804 return result;
2805 }
2807 /** TypeList = Type {"," Type}
2808 */
2809 List<JCExpression> typeList() {
2810 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2811 ts.append(parseType());
2812 while (token.kind == COMMA) {
2813 nextToken();
2814 ts.append(parseType());
2815 }
2816 return ts.toList();
2817 }
2819 /** ClassBody = "{" {ClassBodyDeclaration} "}"
2820 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2821 */
2822 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2823 accept(LBRACE);
2824 if (token.pos <= endPosTable.errorEndPos) {
2825 // error recovery
2826 skip(false, true, false, false);
2827 if (token.kind == LBRACE)
2828 nextToken();
2829 }
2830 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2831 while (token.kind != RBRACE && token.kind != EOF) {
2832 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2833 if (token.pos <= endPosTable.errorEndPos) {
2834 // error recovery
2835 skip(false, true, true, false);
2836 }
2837 }
2838 accept(RBRACE);
2839 return defs.toList();
2840 }
2842 /** ClassBodyDeclaration =
2843 * ";"
2844 * | [STATIC] Block
2845 * | ModifiersOpt
2846 * ( Type Ident
2847 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2848 * | VOID Ident MethodDeclaratorRest
2849 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2850 * | Ident ConstructorDeclaratorRest
2851 * | TypeParameters Ident ConstructorDeclaratorRest
2852 * | ClassOrInterfaceOrEnumDeclaration
2853 * )
2854 * InterfaceBodyDeclaration =
2855 * ";"
2856 * | ModifiersOpt Type Ident
2857 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2858 */
2859 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2860 if (token.kind == SEMI) {
2861 nextToken();
2862 return List.<JCTree>nil();
2863 } else {
2864 Comment dc = token.comment(CommentStyle.JAVADOC);
2865 int pos = token.pos;
2866 JCModifiers mods = modifiersOpt();
2867 if (token.kind == CLASS ||
2868 token.kind == INTERFACE ||
2869 allowEnums && token.kind == ENUM) {
2870 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2871 } else if (token.kind == LBRACE && !isInterface &&
2872 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2873 mods.annotations.isEmpty()) {
2874 return List.<JCTree>of(block(pos, mods.flags));
2875 } else {
2876 pos = token.pos;
2877 List<JCTypeParameter> typarams = typeParametersOpt();
2878 // if there are type parameters but no modifiers, save the start
2879 // position of the method in the modifiers.
2880 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
2881 mods.pos = pos;
2882 storeEnd(mods, pos);
2883 }
2884 Token tk = token;
2885 pos = token.pos;
2886 JCExpression type;
2887 boolean isVoid = token.kind == VOID;
2888 if (isVoid) {
2889 type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2890 nextToken();
2891 } else {
2892 type = parseType();
2893 }
2894 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
2895 if (isInterface || tk.name() != className)
2896 error(pos, "invalid.meth.decl.ret.type.req");
2897 return List.of(methodDeclaratorRest(
2898 pos, mods, null, names.init, typarams,
2899 isInterface, true, dc));
2900 } else {
2901 pos = token.pos;
2902 Name name = ident();
2903 if (token.kind == LPAREN) {
2904 return List.of(methodDeclaratorRest(
2905 pos, mods, type, name, typarams,
2906 isInterface, isVoid, dc));
2907 } else if (!isVoid && typarams.isEmpty()) {
2908 List<JCTree> defs =
2909 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2910 new ListBuffer<JCTree>()).toList();
2911 storeEnd(defs.last(), token.endPos);
2912 accept(SEMI);
2913 return defs;
2914 } else {
2915 pos = token.pos;
2916 List<JCTree> err = isVoid
2917 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2918 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2919 : null;
2920 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
2921 }
2922 }
2923 }
2924 }
2925 }
2927 /** MethodDeclaratorRest =
2928 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2929 * VoidMethodDeclaratorRest =
2930 * FormalParameters [Throws TypeList] ( MethodBody | ";")
2931 * InterfaceMethodDeclaratorRest =
2932 * FormalParameters BracketsOpt [THROWS TypeList] ";"
2933 * VoidInterfaceMethodDeclaratorRest =
2934 * FormalParameters [THROWS TypeList] ";"
2935 * ConstructorDeclaratorRest =
2936 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2937 */
2938 protected JCTree methodDeclaratorRest(int pos,
2939 JCModifiers mods,
2940 JCExpression type,
2941 Name name,
2942 List<JCTypeParameter> typarams,
2943 boolean isInterface, boolean isVoid,
2944 Comment dc) {
2945 List<JCVariableDecl> params = formalParameters();
2946 if (!isVoid) type = bracketsOpt(type);
2947 List<JCExpression> thrown = List.nil();
2948 if (token.kind == THROWS) {
2949 nextToken();
2950 thrown = qualidentList();
2951 }
2952 JCBlock body = null;
2953 JCExpression defaultValue;
2954 if (token.kind == LBRACE) {
2955 body = block();
2956 defaultValue = null;
2957 } else {
2958 if (token.kind == DEFAULT) {
2959 accept(DEFAULT);
2960 defaultValue = annotationValue();
2961 } else {
2962 defaultValue = null;
2963 }
2964 accept(SEMI);
2965 if (token.pos <= endPosTable.errorEndPos) {
2966 // error recovery
2967 skip(false, true, false, false);
2968 if (token.kind == LBRACE) {
2969 body = block();
2970 }
2971 }
2972 }
2974 JCMethodDecl result =
2975 toP(F.at(pos).MethodDef(mods, name, type, typarams,
2976 params, thrown,
2977 body, defaultValue));
2978 attach(result, dc);
2979 return result;
2980 }
2982 /** QualidentList = Qualident {"," Qualident}
2983 */
2984 List<JCExpression> qualidentList() {
2985 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2986 ts.append(qualident());
2987 while (token.kind == COMMA) {
2988 nextToken();
2989 ts.append(qualident());
2990 }
2991 return ts.toList();
2992 }
2994 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2995 */
2996 List<JCTypeParameter> typeParametersOpt() {
2997 if (token.kind == LT) {
2998 checkGenerics();
2999 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
3000 nextToken();
3001 typarams.append(typeParameter());
3002 while (token.kind == COMMA) {
3003 nextToken();
3004 typarams.append(typeParameter());
3005 }
3006 accept(GT);
3007 return typarams.toList();
3008 } else {
3009 return List.nil();
3010 }
3011 }
3013 /** TypeParameter = TypeVariable [TypeParameterBound]
3014 * TypeParameterBound = EXTENDS Type {"&" Type}
3015 * TypeVariable = Ident
3016 */
3017 JCTypeParameter typeParameter() {
3018 int pos = token.pos;
3019 Name name = ident();
3020 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
3021 if (token.kind == EXTENDS) {
3022 nextToken();
3023 bounds.append(parseType());
3024 while (token.kind == AMP) {
3025 nextToken();
3026 bounds.append(parseType());
3027 }
3028 }
3029 return toP(F.at(pos).TypeParameter(name, bounds.toList()));
3030 }
3032 /** FormalParameters = "(" [ FormalParameterList ] ")"
3033 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
3034 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
3035 */
3036 List<JCVariableDecl> formalParameters() {
3037 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3038 JCVariableDecl lastParam = null;
3039 accept(LPAREN);
3040 if (token.kind != RPAREN) {
3041 params.append(lastParam = formalParameter());
3042 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
3043 nextToken();
3044 params.append(lastParam = formalParameter());
3045 }
3046 }
3047 accept(RPAREN);
3048 return params.toList();
3049 }
3051 List<JCVariableDecl> implicitParameters(boolean hasParens) {
3052 if (hasParens) {
3053 accept(LPAREN);
3054 }
3055 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
3056 if (token.kind != RPAREN && token.kind != ARROW) {
3057 params.append(implicitParameter());
3058 while (token.kind == COMMA) {
3059 nextToken();
3060 params.append(implicitParameter());
3061 }
3062 }
3063 if (hasParens) {
3064 accept(RPAREN);
3065 }
3066 return params.toList();
3067 }
3069 JCModifiers optFinal(long flags) {
3070 JCModifiers mods = modifiersOpt();
3071 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
3072 mods.flags |= flags;
3073 return mods;
3074 }
3076 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
3077 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
3078 */
3079 protected JCVariableDecl formalParameter() {
3080 JCModifiers mods = optFinal(Flags.PARAMETER);
3081 JCExpression type = parseType();
3082 if (token.kind == ELLIPSIS) {
3083 checkVarargs();
3084 mods.flags |= Flags.VARARGS;
3085 type = to(F.at(token.pos).TypeArray(type));
3086 nextToken();
3087 }
3088 return variableDeclaratorId(mods, type);
3089 }
3091 protected JCVariableDecl implicitParameter() {
3092 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
3093 return variableDeclaratorId(mods, null);
3094 }
3096 /* ---------- auxiliary methods -------------- */
3098 void error(int pos, String key, Object ... args) {
3099 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3100 }
3102 void error(DiagnosticPosition pos, String key, Object ... args) {
3103 log.error(DiagnosticFlag.SYNTAX, pos, key, args);
3104 }
3106 void warning(int pos, String key, Object ... args) {
3107 log.warning(pos, key, args);
3108 }
3110 /** Check that given tree is a legal expression statement.
3111 */
3112 protected JCExpression checkExprStat(JCExpression t) {
3113 switch(t.getTag()) {
3114 case PREINC: case PREDEC:
3115 case POSTINC: case POSTDEC:
3116 case ASSIGN:
3117 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
3118 case SL_ASG: case SR_ASG: case USR_ASG:
3119 case PLUS_ASG: case MINUS_ASG:
3120 case MUL_ASG: case DIV_ASG: case MOD_ASG:
3121 case APPLY: case NEWCLASS:
3122 case ERRONEOUS:
3123 return t;
3124 default:
3125 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
3126 error(ret, "not.stmt");
3127 return ret;
3128 }
3129 }
3131 /** Return precedence of operator represented by token,
3132 * -1 if token is not a binary operator. @see TreeInfo.opPrec
3133 */
3134 static int prec(TokenKind token) {
3135 JCTree.Tag oc = optag(token);
3136 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
3137 }
3139 /**
3140 * Return the lesser of two positions, making allowance for either one
3141 * being unset.
3142 */
3143 static int earlier(int pos1, int pos2) {
3144 if (pos1 == Position.NOPOS)
3145 return pos2;
3146 if (pos2 == Position.NOPOS)
3147 return pos1;
3148 return (pos1 < pos2 ? pos1 : pos2);
3149 }
3151 /** Return operation tag of binary operator represented by token,
3152 * No_TAG if token is not a binary operator.
3153 */
3154 static JCTree.Tag optag(TokenKind token) {
3155 switch (token) {
3156 case BARBAR:
3157 return OR;
3158 case AMPAMP:
3159 return AND;
3160 case BAR:
3161 return BITOR;
3162 case BAREQ:
3163 return BITOR_ASG;
3164 case CARET:
3165 return BITXOR;
3166 case CARETEQ:
3167 return BITXOR_ASG;
3168 case AMP:
3169 return BITAND;
3170 case AMPEQ:
3171 return BITAND_ASG;
3172 case EQEQ:
3173 return JCTree.Tag.EQ;
3174 case BANGEQ:
3175 return NE;
3176 case LT:
3177 return JCTree.Tag.LT;
3178 case GT:
3179 return JCTree.Tag.GT;
3180 case LTEQ:
3181 return LE;
3182 case GTEQ:
3183 return GE;
3184 case LTLT:
3185 return SL;
3186 case LTLTEQ:
3187 return SL_ASG;
3188 case GTGT:
3189 return SR;
3190 case GTGTEQ:
3191 return SR_ASG;
3192 case GTGTGT:
3193 return USR;
3194 case GTGTGTEQ:
3195 return USR_ASG;
3196 case PLUS:
3197 return JCTree.Tag.PLUS;
3198 case PLUSEQ:
3199 return PLUS_ASG;
3200 case SUB:
3201 return MINUS;
3202 case SUBEQ:
3203 return MINUS_ASG;
3204 case STAR:
3205 return MUL;
3206 case STAREQ:
3207 return MUL_ASG;
3208 case SLASH:
3209 return DIV;
3210 case SLASHEQ:
3211 return DIV_ASG;
3212 case PERCENT:
3213 return MOD;
3214 case PERCENTEQ:
3215 return MOD_ASG;
3216 case INSTANCEOF:
3217 return TYPETEST;
3218 default:
3219 return NO_TAG;
3220 }
3221 }
3223 /** Return operation tag of unary operator represented by token,
3224 * No_TAG if token is not a binary operator.
3225 */
3226 static JCTree.Tag unoptag(TokenKind token) {
3227 switch (token) {
3228 case PLUS:
3229 return POS;
3230 case SUB:
3231 return NEG;
3232 case BANG:
3233 return NOT;
3234 case TILDE:
3235 return COMPL;
3236 case PLUSPLUS:
3237 return PREINC;
3238 case SUBSUB:
3239 return PREDEC;
3240 default:
3241 return NO_TAG;
3242 }
3243 }
3245 /** Return type tag of basic type represented by token,
3246 * -1 if token is not a basic type identifier.
3247 */
3248 static int typetag(TokenKind token) {
3249 switch (token) {
3250 case BYTE:
3251 return TypeTags.BYTE;
3252 case CHAR:
3253 return TypeTags.CHAR;
3254 case SHORT:
3255 return TypeTags.SHORT;
3256 case INT:
3257 return TypeTags.INT;
3258 case LONG:
3259 return TypeTags.LONG;
3260 case FLOAT:
3261 return TypeTags.FLOAT;
3262 case DOUBLE:
3263 return TypeTags.DOUBLE;
3264 case BOOLEAN:
3265 return TypeTags.BOOLEAN;
3266 default:
3267 return -1;
3268 }
3269 }
3271 void checkGenerics() {
3272 if (!allowGenerics) {
3273 error(token.pos, "generics.not.supported.in.source", source.name);
3274 allowGenerics = true;
3275 }
3276 }
3277 void checkVarargs() {
3278 if (!allowVarargs) {
3279 error(token.pos, "varargs.not.supported.in.source", source.name);
3280 allowVarargs = true;
3281 }
3282 }
3283 void checkForeach() {
3284 if (!allowForeach) {
3285 error(token.pos, "foreach.not.supported.in.source", source.name);
3286 allowForeach = true;
3287 }
3288 }
3289 void checkStaticImports() {
3290 if (!allowStaticImport) {
3291 error(token.pos, "static.import.not.supported.in.source", source.name);
3292 allowStaticImport = true;
3293 }
3294 }
3295 void checkAnnotations() {
3296 if (!allowAnnotations) {
3297 error(token.pos, "annotations.not.supported.in.source", source.name);
3298 allowAnnotations = true;
3299 }
3300 }
3301 void checkDiamond() {
3302 if (!allowDiamond) {
3303 error(token.pos, "diamond.not.supported.in.source", source.name);
3304 allowDiamond = true;
3305 }
3306 }
3307 void checkMulticatch() {
3308 if (!allowMulticatch) {
3309 error(token.pos, "multicatch.not.supported.in.source", source.name);
3310 allowMulticatch = true;
3311 }
3312 }
3313 void checkTryWithResources() {
3314 if (!allowTWR) {
3315 error(token.pos, "try.with.resources.not.supported.in.source", source.name);
3316 allowTWR = true;
3317 }
3318 }
3319 void checkLambda() {
3320 if (!allowLambda) {
3321 log.error(token.pos, "lambda.not.supported.in.source", source.name);
3322 allowLambda = true;
3323 }
3324 }
3325 void checkMethodReferences() {
3326 if (!allowMethodReferences) {
3327 log.error(token.pos, "method.references.not.supported.in.source", source.name);
3328 allowMethodReferences = true;
3329 }
3330 }
3332 /*
3333 * a functional source tree and end position mappings
3334 */
3335 protected class SimpleEndPosTable extends AbstractEndPosTable {
3337 private final Map<JCTree, Integer> endPosMap;
3339 SimpleEndPosTable() {
3340 endPosMap = new HashMap<JCTree, Integer>();
3341 }
3343 protected void storeEnd(JCTree tree, int endpos) {
3344 endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
3345 }
3347 protected <T extends JCTree> T to(T t) {
3348 storeEnd(t, token.endPos);
3349 return t;
3350 }
3352 protected <T extends JCTree> T toP(T t) {
3353 storeEnd(t, S.prevToken().endPos);
3354 return t;
3355 }
3357 public int getEndPos(JCTree tree) {
3358 Integer value = endPosMap.get(tree);
3359 return (value == null) ? Position.NOPOS : value;
3360 }
3362 public int replaceTree(JCTree oldTree, JCTree newTree) {
3363 Integer pos = endPosMap.remove(oldTree);
3364 if (pos != null) {
3365 endPosMap.put(newTree, pos);
3366 return pos;
3367 }
3368 return Position.NOPOS;
3369 }
3370 }
3372 /*
3373 * a default skeletal implementation without any mapping overhead.
3374 */
3375 protected class EmptyEndPosTable extends AbstractEndPosTable {
3377 protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
3379 protected <T extends JCTree> T to(T t) {
3380 return t;
3381 }
3383 protected <T extends JCTree> T toP(T t) {
3384 return t;
3385 }
3387 public int getEndPos(JCTree tree) {
3388 return Position.NOPOS;
3389 }
3391 public int replaceTree(JCTree oldTree, JCTree newTree) {
3392 return Position.NOPOS;
3393 }
3395 }
3397 protected abstract class AbstractEndPosTable implements EndPosTable {
3399 /**
3400 * Store the last error position.
3401 */
3402 protected int errorEndPos;
3404 /**
3405 * Store ending position for a tree, the value of which is the greater
3406 * of last error position and the given ending position.
3407 * @param tree The tree.
3408 * @param endpos The ending position to associate with the tree.
3409 */
3410 protected abstract void storeEnd(JCTree tree, int endpos);
3412 /**
3413 * Store current token's ending position for a tree, the value of which
3414 * will be the greater of last error position and the ending position of
3415 * the current token.
3416 * @param t The tree.
3417 */
3418 protected abstract <T extends JCTree> T to(T t);
3420 /**
3421 * Store current token's ending position for a tree, the value of which
3422 * will be the greater of last error position and the ending position of
3423 * the previous token.
3424 * @param t The tree.
3425 */
3426 protected abstract <T extends JCTree> T toP(T t);
3428 /**
3429 * Set the error position during the parsing phases, the value of which
3430 * will be set only if it is greater than the last stored error position.
3431 * @param errPos The error position
3432 */
3433 protected void setErrorEndPos(int errPos) {
3434 if (errPos > errorEndPos) {
3435 errorEndPos = errPos;
3436 }
3437 }
3438 }
3439 }