0001: /*
0002: * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package com.sun.tools.javac.parser;
0027:
0028: import java.util.*;
0029:
0030: import com.sun.tools.javac.tree.*;
0031: import com.sun.tools.javac.code.*;
0032: import com.sun.tools.javac.util.*;
0033: import com.sun.tools.javac.util.List;
0034: import static com.sun.tools.javac.util.ListBuffer.lb;
0035:
0036: import com.sun.tools.javac.tree.JCTree.*;
0037:
0038: import static com.sun.tools.javac.parser.Token.*;
0039:
0040: /** The parser maps a token sequence into an abstract syntax
0041: * tree. It operates by recursive descent, with code derived
0042: * systematically from an LL(1) grammar. For efficiency reasons, an
0043: * operator precedence scheme is used for parsing binary operation
0044: * expressions.
0045: *
0046: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
0047: * you write code that depends on this, you do so at your own risk.
0048: * This code and its internal interfaces are subject to change or
0049: * deletion without notice.</b>
0050: */
0051: @Version("@(#)Parser.java 1.108 07/06/14")
0052: public class Parser {
0053:
0054: /** A factory for creating parsers. */
0055: public static class Factory {
0056: /** The context key for the parser factory. */
0057: protected static final Context.Key<Parser.Factory> parserFactoryKey = new Context.Key<Parser.Factory>();
0058:
0059: /** Get the Factory instance for this context. */
0060: public static Factory instance(Context context) {
0061: Factory instance = context.get(parserFactoryKey);
0062: if (instance == null)
0063: instance = new Factory(context);
0064: return instance;
0065: }
0066:
0067: final TreeMaker F;
0068: final Log log;
0069: final Keywords keywords;
0070: final Source source;
0071: final Name.Table names;
0072: final Options options;
0073:
0074: /** Create a new parser factory. */
0075: protected Factory(Context context) {
0076: context.put(parserFactoryKey, this );
0077: this .F = TreeMaker.instance(context);
0078: this .log = Log.instance(context);
0079: this .names = Name.Table.instance(context);
0080: this .keywords = Keywords.instance(context);
0081: this .source = Source.instance(context);
0082: this .options = Options.instance(context);
0083: }
0084:
0085: /**
0086: * Create a new Parser.
0087: * @param S Lexer for getting tokens while parsing
0088: * @param keepDocComments true if javadoc comments should be kept
0089: * @param genEndPos true if end positions should be generated
0090: */
0091: public Parser newParser(Lexer S, boolean keepDocComments,
0092: boolean genEndPos) {
0093: if (!genEndPos)
0094: return new Parser(this , S, keepDocComments);
0095: else
0096: return new EndPosParser(this , S, keepDocComments);
0097: }
0098: }
0099:
0100: /** The number of precedence levels of infix operators.
0101: */
0102: private static final int infixPrecedenceLevels = 10;
0103:
0104: /** The scanner used for lexical analysis.
0105: */
0106: private Lexer S;
0107:
0108: /** The factory to be used for abstract syntax tree construction.
0109: */
0110: protected TreeMaker F;
0111:
0112: /** The log to be used for error diagnostics.
0113: */
0114: private Log log;
0115:
0116: /** The keyword table. */
0117: private Keywords keywords;
0118:
0119: /** The Source language setting. */
0120: private Source source;
0121:
0122: /** The name table. */
0123: private Name.Table names;
0124:
0125: /** Construct a parser from a given scanner, tree factory and log.
0126: */
0127: protected Parser(Factory fac, Lexer S, boolean keepDocComments) {
0128: this .S = S;
0129: S.nextToken(); // prime the pump
0130: this .F = fac.F;
0131: this .log = fac.log;
0132: this .names = fac.names;
0133: this .keywords = fac.keywords;
0134: this .source = fac.source;
0135: Options options = fac.options;
0136: this .allowGenerics = source.allowGenerics();
0137: this .allowVarargs = source.allowVarargs();
0138: this .allowAsserts = source.allowAsserts();
0139: this .allowEnums = source.allowEnums();
0140: this .allowForeach = source.allowForeach();
0141: this .allowStaticImport = source.allowStaticImport();
0142: this .allowAnnotations = source.allowAnnotations();
0143: this .keepDocComments = keepDocComments;
0144: if (keepDocComments)
0145: docComments = new HashMap<JCTree, String>();
0146: this .errorTree = F.Erroneous();
0147: }
0148:
0149: /** Switch: Should generics be recognized?
0150: */
0151: boolean allowGenerics;
0152:
0153: /** Switch: Should varargs be recognized?
0154: */
0155: boolean allowVarargs;
0156:
0157: /** Switch: should we recognize assert statements, or just give a warning?
0158: */
0159: boolean allowAsserts;
0160:
0161: /** Switch: should we recognize enums, or just give a warning?
0162: */
0163: boolean allowEnums;
0164:
0165: /** Switch: should we recognize foreach?
0166: */
0167: boolean allowForeach;
0168:
0169: /** Switch: should we recognize foreach?
0170: */
0171: boolean allowStaticImport;
0172:
0173: /** Switch: should we recognize annotations?
0174: */
0175: boolean allowAnnotations;
0176:
0177: /** Switch: should we keep docComments?
0178: */
0179: boolean keepDocComments;
0180:
0181: /** When terms are parsed, the mode determines which is expected:
0182: * mode = EXPR : an expression
0183: * mode = TYPE : a type
0184: * mode = NOPARAMS : no parameters allowed for type
0185: * mode = TYPEARG : type argument
0186: */
0187: static final int EXPR = 1;
0188: static final int TYPE = 2;
0189: static final int NOPARAMS = 4;
0190: static final int TYPEARG = 8;
0191:
0192: /** The current mode.
0193: */
0194: private int mode = 0;
0195:
0196: /** The mode of the term that was parsed last.
0197: */
0198: private int lastmode = 0;
0199:
0200: /* ---------- error recovery -------------- */
0201:
0202: private JCErroneous errorTree;
0203:
0204: /** Skip forward until a suitable stop token is found.
0205: */
0206: private void skip(boolean stopAtImport, boolean stopAtMemberDecl,
0207: boolean stopAtIdentifier, boolean stopAtStatement) {
0208: while (true) {
0209: switch (S.token()) {
0210: case SEMI:
0211: S.nextToken();
0212: return;
0213: case PUBLIC:
0214: case FINAL:
0215: case ABSTRACT:
0216: case MONKEYS_AT:
0217: case EOF:
0218: case CLASS:
0219: case INTERFACE:
0220: case ENUM:
0221: return;
0222: case IMPORT:
0223: if (stopAtImport)
0224: return;
0225: break;
0226: case LBRACE:
0227: case RBRACE:
0228: case PRIVATE:
0229: case PROTECTED:
0230: case STATIC:
0231: case TRANSIENT:
0232: case NATIVE:
0233: case VOLATILE:
0234: case SYNCHRONIZED:
0235: case STRICTFP:
0236: case LT:
0237: case BYTE:
0238: case SHORT:
0239: case CHAR:
0240: case INT:
0241: case LONG:
0242: case FLOAT:
0243: case DOUBLE:
0244: case BOOLEAN:
0245: case VOID:
0246: if (stopAtMemberDecl)
0247: return;
0248: break;
0249: case IDENTIFIER:
0250: if (stopAtIdentifier)
0251: return;
0252: break;
0253: case CASE:
0254: case DEFAULT:
0255: case IF:
0256: case FOR:
0257: case WHILE:
0258: case DO:
0259: case TRY:
0260: case SWITCH:
0261: case RETURN:
0262: case THROW:
0263: case BREAK:
0264: case CONTINUE:
0265: case ELSE:
0266: case FINALLY:
0267: case CATCH:
0268: if (stopAtStatement)
0269: return;
0270: break;
0271: }
0272: S.nextToken();
0273: }
0274: }
0275:
0276: private JCErroneous syntaxError(int pos, String key, Object... arg) {
0277: return syntaxError(pos, null, key, arg);
0278: }
0279:
0280: private JCErroneous syntaxError(int pos, List<JCTree> errs,
0281: String key, Object... arg) {
0282: setErrorEndPos(pos);
0283: reportSyntaxError(pos, key, arg);
0284: return toP(F.at(pos).Erroneous(errs));
0285: }
0286:
0287: private int errorPos = Position.NOPOS;
0288:
0289: /**
0290: * Report a syntax error at given position using the given
0291: * argument unless one was already reported at the same position.
0292: */
0293: private void reportSyntaxError(int pos, String key, Object... arg) {
0294: if (pos > S.errPos() || pos == Position.NOPOS) {
0295: if (S.token() == EOF)
0296: log.error(pos, "premature.eof");
0297: else
0298: log.error(pos, key, arg);
0299: }
0300: S.errPos(pos);
0301: if (S.pos() == errorPos)
0302: S.nextToken(); // guarantee progress
0303: errorPos = S.pos();
0304: }
0305:
0306: /** Generate a syntax error at current position unless one was already
0307: * reported at the same position.
0308: */
0309: private JCErroneous syntaxError(String key) {
0310: return syntaxError(S.pos(), key);
0311: }
0312:
0313: /** Generate a syntax error at current position unless one was
0314: * already reported at the same position.
0315: */
0316: private JCErroneous syntaxError(String key, String arg) {
0317: return syntaxError(S.pos(), key, arg);
0318: }
0319:
0320: /** If next input token matches given token, skip it, otherwise report
0321: * an error.
0322: */
0323: public void accept(Token token) {
0324: if (S.token() == token) {
0325: S.nextToken();
0326: } else {
0327: setErrorEndPos(S.pos());
0328: reportSyntaxError(S.prevEndPos(), "expected", keywords
0329: .token2string(token));
0330: }
0331: }
0332:
0333: /** Report an illegal start of expression/type error at given position.
0334: */
0335: JCExpression illegal(int pos) {
0336: setErrorEndPos(S.pos());
0337: if ((mode & EXPR) != 0)
0338: return syntaxError(pos, "illegal.start.of.expr");
0339: else
0340: return syntaxError(pos, "illegal.start.of.type");
0341:
0342: }
0343:
0344: /** Report an illegal start of expression/type error at current position.
0345: */
0346: JCExpression illegal() {
0347: return illegal(S.pos());
0348: }
0349:
0350: /** Diagnose a modifier flag from the set, if any. */
0351: void checkNoMods(long mods) {
0352: if (mods != 0) {
0353: long lowestMod = mods & -mods;
0354: log.error(S.pos(), "mod.not.allowed.here", Flags.toString(
0355: lowestMod).trim());
0356: }
0357: }
0358:
0359: /* ---------- doc comments --------- */
0360:
0361: /** A hashtable to store all documentation comments
0362: * indexed by the tree nodes they refer to.
0363: * defined only if option flag keepDocComment is set.
0364: */
0365: Map<JCTree, String> docComments;
0366:
0367: /** Make an entry into docComments hashtable,
0368: * provided flag keepDocComments is set and given doc comment is non-null.
0369: * @param tree The tree to be used as index in the hashtable
0370: * @param dc The doc comment to associate with the tree, or null.
0371: */
0372: void attach(JCTree tree, String dc) {
0373: if (keepDocComments && dc != null) {
0374: // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
0375: docComments.put(tree, dc);
0376: }
0377: }
0378:
0379: /* -------- source positions ------- */
0380:
0381: private int errorEndPos = -1;
0382:
0383: private void setErrorEndPos(int errPos) {
0384: if (errPos > errorEndPos)
0385: errorEndPos = errPos;
0386: }
0387:
0388: protected int getErrorEndPos() {
0389: return errorEndPos;
0390: }
0391:
0392: /**
0393: * Store ending position for a tree.
0394: * @param tree The tree.
0395: * @param endpos The ending position to associate with the tree.
0396: */
0397: protected void storeEnd(JCTree tree, int endpos) {
0398: }
0399:
0400: /**
0401: * Store ending position for a tree. The ending position should
0402: * be the ending position of the current token.
0403: * @param t The tree.
0404: */
0405: protected <T extends JCTree> T to(T t) {
0406: return t;
0407: }
0408:
0409: /**
0410: * Store ending position for a tree. The ending position should
0411: * be greater of the ending position of the previous token and errorEndPos.
0412: * @param t The tree.
0413: */
0414: protected <T extends JCTree> T toP(T t) {
0415: return t;
0416: }
0417:
0418: /** Get the start position for a tree node. The start position is
0419: * defined to be the position of the first character of the first
0420: * token of the node's source text.
0421: * @param tree The tree node
0422: */
0423: public int getStartPos(JCTree tree) {
0424: return TreeInfo.getStartPos(tree);
0425: }
0426:
0427: /**
0428: * Get the end position for a tree node. The end position is
0429: * defined to be the position of the last character of the last
0430: * token of the node's source text. Returns Position.NOPOS if end
0431: * positions are not generated or the position is otherwise not
0432: * found.
0433: * @param tree The tree node
0434: */
0435: public int getEndPos(JCTree tree) {
0436: return Position.NOPOS;
0437: }
0438:
0439: /* ---------- parsing -------------- */
0440:
0441: /**
0442: * Ident = IDENTIFIER
0443: */
0444: Name ident() {
0445: if (S.token() == IDENTIFIER) {
0446: Name name = S.name();
0447: S.nextToken();
0448: return name;
0449: } else if (S.token() == ASSERT) {
0450: if (allowAsserts) {
0451: log.error(S.pos(), "assert.as.identifier");
0452: S.nextToken();
0453: return names.error;
0454: } else {
0455: log.warning(S.pos(), "assert.as.identifier");
0456: Name name = S.name();
0457: S.nextToken();
0458: return name;
0459: }
0460: } else if (S.token() == ENUM) {
0461: if (allowEnums) {
0462: log.error(S.pos(), "enum.as.identifier");
0463: S.nextToken();
0464: return names.error;
0465: } else {
0466: log.warning(S.pos(), "enum.as.identifier");
0467: Name name = S.name();
0468: S.nextToken();
0469: return name;
0470: }
0471: } else {
0472: accept(IDENTIFIER);
0473: return names.error;
0474: }
0475: }
0476:
0477: /**
0478: * Qualident = Ident { DOT Ident }
0479: */
0480: public JCExpression qualident() {
0481: JCExpression t = toP(F.at(S.pos()).Ident(ident()));
0482: while (S.token() == DOT) {
0483: int pos = S.pos();
0484: S.nextToken();
0485: t = toP(F.at(pos).Select(t, ident()));
0486: }
0487: return t;
0488: }
0489:
0490: /**
0491: * Literal =
0492: * INTLITERAL
0493: * | LONGLITERAL
0494: * | FLOATLITERAL
0495: * | DOUBLELITERAL
0496: * | CHARLITERAL
0497: * | STRINGLITERAL
0498: * | TRUE
0499: * | FALSE
0500: * | NULL
0501: */
0502: JCExpression literal(Name prefix) {
0503: int pos = S.pos();
0504: JCExpression t = errorTree;
0505: switch (S.token()) {
0506: case INTLITERAL:
0507: try {
0508: t = F.at(pos).Literal(TypeTags.INT,
0509: Convert.string2int(strval(prefix), S.radix()));
0510: } catch (NumberFormatException ex) {
0511: log.error(S.pos(), "int.number.too.large",
0512: strval(prefix));
0513: }
0514: break;
0515: case LONGLITERAL:
0516: try {
0517: t = F.at(pos).Literal(
0518: TypeTags.LONG,
0519: new Long(Convert.string2long(strval(prefix), S
0520: .radix())));
0521: } catch (NumberFormatException ex) {
0522: log.error(S.pos(), "int.number.too.large",
0523: strval(prefix));
0524: }
0525: break;
0526: case FLOATLITERAL: {
0527: String proper = (S.radix() == 16 ? ("0x" + S.stringVal())
0528: : S.stringVal());
0529: Float n;
0530: try {
0531: n = Float.valueOf(proper);
0532: } catch (NumberFormatException ex) {
0533: // error already repoted in scanner
0534: n = Float.NaN;
0535: }
0536: if (n.floatValue() == 0.0f && !isZero(proper))
0537: log.error(S.pos(), "fp.number.too.small");
0538: else if (n.floatValue() == Float.POSITIVE_INFINITY)
0539: log.error(S.pos(), "fp.number.too.large");
0540: else
0541: t = F.at(pos).Literal(TypeTags.FLOAT, n);
0542: break;
0543: }
0544: case DOUBLELITERAL: {
0545: String proper = (S.radix() == 16 ? ("0x" + S.stringVal())
0546: : S.stringVal());
0547: Double n;
0548: try {
0549: n = Double.valueOf(proper);
0550: } catch (NumberFormatException ex) {
0551: // error already reported in scanner
0552: n = Double.NaN;
0553: }
0554: if (n.doubleValue() == 0.0d && !isZero(proper))
0555: log.error(S.pos(), "fp.number.too.small");
0556: else if (n.doubleValue() == Double.POSITIVE_INFINITY)
0557: log.error(S.pos(), "fp.number.too.large");
0558: else
0559: t = F.at(pos).Literal(TypeTags.DOUBLE, n);
0560: break;
0561: }
0562: case CHARLITERAL:
0563: t = F.at(pos).Literal(TypeTags.CHAR,
0564: S.stringVal().charAt(0) + 0);
0565: break;
0566: case STRINGLITERAL:
0567: t = F.at(pos).Literal(TypeTags.CLASS, S.stringVal());
0568: break;
0569: case TRUE:
0570: case FALSE:
0571: t = F.at(pos).Literal(TypeTags.BOOLEAN,
0572: (S.token() == TRUE ? 1 : 0));
0573: break;
0574: case NULL:
0575: t = F.at(pos).Literal(TypeTags.BOT, null);
0576: break;
0577: default:
0578: assert false;
0579: }
0580: if (t == errorTree)
0581: t = F.at(pos).Erroneous();
0582: storeEnd(t, S.endPos());
0583: S.nextToken();
0584: return t;
0585: }
0586:
0587: //where
0588: boolean isZero(String s) {
0589: char[] cs = s.toCharArray();
0590: int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16
0591: : 10);
0592: int i = ((base == 16) ? 2 : 0);
0593: while (i < cs.length && (cs[i] == '0' || cs[i] == '.'))
0594: i++;
0595: return !(i < cs.length && (Character.digit(cs[i], base) > 0));
0596: }
0597:
0598: String strval(Name prefix) {
0599: String s = S.stringVal();
0600: return (prefix.len == 0) ? s : prefix + s;
0601: }
0602:
0603: /** terms can be either expressions or types.
0604: */
0605: public JCExpression expression() {
0606: return term(EXPR);
0607: }
0608:
0609: public JCExpression type() {
0610: return term(TYPE);
0611: }
0612:
0613: JCExpression term(int newmode) {
0614: int prevmode = mode;
0615: mode = newmode;
0616: JCExpression t = term();
0617: lastmode = mode;
0618: mode = prevmode;
0619: return t;
0620: }
0621:
0622: /**
0623: * Expression = Expression1 [ExpressionRest]
0624: * ExpressionRest = [AssignmentOperator Expression1]
0625: * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
0626: * "&=" | "|=" | "^=" |
0627: * "%=" | "<<=" | ">>=" | ">>>="
0628: * Type = Type1
0629: * TypeNoParams = TypeNoParams1
0630: * StatementExpression = Expression
0631: * ConstantExpression = Expression
0632: */
0633: JCExpression term() {
0634: JCExpression t = term1();
0635: if ((mode & EXPR) != 0 && S.token() == EQ
0636: || PLUSEQ.compareTo(S.token()) <= 0
0637: && S.token().compareTo(GTGTGTEQ) <= 0)
0638: return termRest(t);
0639: else
0640: return t;
0641: }
0642:
0643: JCExpression termRest(JCExpression t) {
0644: switch (S.token()) {
0645: case EQ: {
0646: int pos = S.pos();
0647: S.nextToken();
0648: mode = EXPR;
0649: JCExpression t1 = term();
0650: return toP(F.at(pos).Assign(t, t1));
0651: }
0652: case PLUSEQ:
0653: case SUBEQ:
0654: case STAREQ:
0655: case SLASHEQ:
0656: case PERCENTEQ:
0657: case AMPEQ:
0658: case BAREQ:
0659: case CARETEQ:
0660: case LTLTEQ:
0661: case GTGTEQ:
0662: case GTGTGTEQ:
0663: int pos = S.pos();
0664: Token token = S.token();
0665: S.nextToken();
0666: mode = EXPR;
0667: JCExpression t1 = term();
0668: return F.at(pos).Assignop(optag(token), t, t1);
0669: default:
0670: return t;
0671: }
0672: }
0673:
0674: /** Expression1 = Expression2 [Expression1Rest]
0675: * Type1 = Type2
0676: * TypeNoParams1 = TypeNoParams2
0677: */
0678: JCExpression term1() {
0679: JCExpression t = term2();
0680: if ((mode & EXPR) != 0 && S.token() == QUES) {
0681: mode = EXPR;
0682: return term1Rest(t);
0683: } else {
0684: return t;
0685: }
0686: }
0687:
0688: /** Expression1Rest = ["?" Expression ":" Expression1]
0689: */
0690: JCExpression term1Rest(JCExpression t) {
0691: if (S.token() == QUES) {
0692: int pos = S.pos();
0693: S.nextToken();
0694: JCExpression t1 = term();
0695: accept(COLON);
0696: JCExpression t2 = term1();
0697: return F.at(pos).Conditional(t, t1, t2);
0698: } else {
0699: return t;
0700: }
0701: }
0702:
0703: /** Expression2 = Expression3 [Expression2Rest]
0704: * Type2 = Type3
0705: * TypeNoParams2 = TypeNoParams3
0706: */
0707: JCExpression term2() {
0708: JCExpression t = term3();
0709: if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
0710: mode = EXPR;
0711: return term2Rest(t, TreeInfo.orPrec);
0712: } else {
0713: return t;
0714: }
0715: }
0716:
0717: /* Expression2Rest = {infixop Expression3}
0718: * | Expression3 instanceof Type
0719: * infixop = "||"
0720: * | "&&"
0721: * | "|"
0722: * | "^"
0723: * | "&"
0724: * | "==" | "!="
0725: * | "<" | ">" | "<=" | ">="
0726: * | "<<" | ">>" | ">>>"
0727: * | "+" | "-"
0728: * | "*" | "/" | "%"
0729: */
0730: JCExpression term2Rest(JCExpression t, int minprec) {
0731: List<JCExpression[]> savedOd = odStackSupply.elems;
0732: JCExpression[] odStack = newOdStack();
0733: List<Token[]> savedOp = opStackSupply.elems;
0734: Token[] opStack = newOpStack();
0735: // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
0736: int top = 0;
0737: odStack[0] = t;
0738: int startPos = S.pos();
0739: Token topOp = ERROR;
0740: while (prec(S.token()) >= minprec) {
0741: opStack[top] = topOp;
0742: top++;
0743: topOp = S.token();
0744: int pos = S.pos();
0745: S.nextToken();
0746: odStack[top] = topOp == INSTANCEOF ? type() : term3();
0747: while (top > 0 && prec(topOp) >= prec(S.token())) {
0748: odStack[top - 1] = makeOp(pos, topOp, odStack[top - 1],
0749: odStack[top]);
0750: top--;
0751: topOp = opStack[top];
0752: }
0753: }
0754: assert top == 0;
0755: t = odStack[0];
0756:
0757: if (t.getTag() == JCTree.PLUS) {
0758: StringBuffer buf = foldStrings(t);
0759: if (buf != null) {
0760: t = toP(F.at(startPos).Literal(TypeTags.CLASS,
0761: buf.toString()));
0762: }
0763: }
0764:
0765: odStackSupply.elems = savedOd; // optimization
0766: opStackSupply.elems = savedOp; // optimization
0767: return t;
0768: }
0769:
0770: //where
0771: /** Construct a binary or type test node.
0772: */
0773: private JCExpression makeOp(int pos, Token topOp, JCExpression od1,
0774: JCExpression od2) {
0775: if (topOp == INSTANCEOF) {
0776: return F.at(pos).TypeTest(od1, od2);
0777: } else {
0778: return F.at(pos).Binary(optag(topOp), od1, od2);
0779: }
0780: }
0781:
0782: /** If tree is a concatenation of string literals, replace it
0783: * by a single literal representing the concatenated string.
0784: */
0785: protected StringBuffer foldStrings(JCTree tree) {
0786: List<String> buf = List.nil();
0787: while (true) {
0788: if (tree.getTag() == JCTree.LITERAL) {
0789: JCLiteral lit = (JCLiteral) tree;
0790: if (lit.typetag == TypeTags.CLASS) {
0791: StringBuffer sbuf = new StringBuffer(
0792: (String) lit.value);
0793: while (buf.nonEmpty()) {
0794: sbuf.append(buf.head);
0795: buf = buf.tail;
0796: }
0797: return sbuf;
0798: }
0799: } else if (tree.getTag() == JCTree.PLUS) {
0800: JCBinary op = (JCBinary) tree;
0801: if (op.rhs.getTag() == JCTree.LITERAL) {
0802: JCLiteral lit = (JCLiteral) op.rhs;
0803: if (lit.typetag == TypeTags.CLASS) {
0804: buf = buf.prepend((String) lit.value);
0805: tree = op.lhs;
0806: continue;
0807: }
0808: }
0809: }
0810: return null;
0811: }
0812: }
0813:
0814: /** optimization: To save allocating a new operand/operator stack
0815: * for every binary operation, we use supplys.
0816: */
0817: ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
0818: ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
0819:
0820: private JCExpression[] newOdStack() {
0821: if (odStackSupply.elems == odStackSupply.last)
0822: odStackSupply
0823: .append(new JCExpression[infixPrecedenceLevels + 1]);
0824: JCExpression[] odStack = odStackSupply.elems.head;
0825: odStackSupply.elems = odStackSupply.elems.tail;
0826: return odStack;
0827: }
0828:
0829: private Token[] newOpStack() {
0830: if (opStackSupply.elems == opStackSupply.last)
0831: opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
0832: Token[] opStack = opStackSupply.elems.head;
0833: opStackSupply.elems = opStackSupply.elems.tail;
0834: return opStack;
0835: }
0836:
0837: /** Expression3 = PrefixOp Expression3
0838: * | "(" Expr | TypeNoParams ")" Expression3
0839: * | Primary {Selector} {PostfixOp}
0840: * Primary = "(" Expression ")"
0841: * | Literal
0842: * | [TypeArguments] THIS [Arguments]
0843: * | [TypeArguments] SUPER SuperSuffix
0844: * | NEW [TypeArguments] Creator
0845: * | Ident { "." Ident }
0846: * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
0847: * | Arguments
0848: * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
0849: * ]
0850: * | BasicType BracketsOpt "." CLASS
0851: * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
0852: * PostfixOp = "++" | "--"
0853: * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
0854: * | BasicType
0855: * TypeNoParams3 = Ident { "." Ident } BracketsOpt
0856: * Selector = "." [TypeArguments] Ident [Arguments]
0857: * | "." THIS
0858: * | "." [TypeArguments] SUPER SuperSuffix
0859: * | "." NEW [TypeArguments] InnerCreator
0860: * | "[" Expression "]"
0861: * TypeSelector = "." Ident [TypeArguments]
0862: * SuperSuffix = Arguments | "." Ident [Arguments]
0863: */
0864: protected JCExpression term3() {
0865: int pos = S.pos();
0866: JCExpression t;
0867: List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
0868: switch (S.token()) {
0869: case QUES:
0870: if ((mode & TYPE) != 0
0871: && (mode & (TYPEARG | NOPARAMS)) == TYPEARG) {
0872: mode = TYPE;
0873: return typeArgument();
0874: } else
0875: return illegal();
0876: case PLUSPLUS:
0877: case SUBSUB:
0878: case BANG:
0879: case TILDE:
0880: case PLUS:
0881: case SUB:
0882: if (typeArgs == null && (mode & EXPR) != 0) {
0883: Token token = S.token();
0884: S.nextToken();
0885: mode = EXPR;
0886: if (token == SUB
0887: && (S.token() == INTLITERAL || S.token() == LONGLITERAL)
0888: && S.radix() == 10) {
0889: mode = EXPR;
0890: t = literal(names.hyphen);
0891: } else {
0892: t = term3();
0893: return F.at(pos).Unary(unoptag(token), t);
0894: }
0895: } else
0896: return illegal();
0897: break;
0898: case LPAREN:
0899: if (typeArgs == null && (mode & EXPR) != 0) {
0900: S.nextToken();
0901: mode = EXPR | TYPE | NOPARAMS;
0902: t = term3();
0903: if ((mode & TYPE) != 0 && S.token() == LT) {
0904: // Could be a cast to a parameterized type
0905: int op = JCTree.LT;
0906: int pos1 = S.pos();
0907: S.nextToken();
0908: mode &= (EXPR | TYPE);
0909: mode |= TYPEARG;
0910: JCExpression t1 = term3();
0911: if ((mode & TYPE) != 0
0912: && (S.token() == COMMA || S.token() == GT)) {
0913: mode = TYPE;
0914: ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
0915: args.append(t1);
0916: while (S.token() == COMMA) {
0917: S.nextToken();
0918: args.append(typeArgument());
0919: }
0920: accept(GT);
0921: t = F.at(pos1).TypeApply(t, args.toList());
0922: checkGenerics();
0923: t = bracketsOpt(toP(t));
0924: } else if ((mode & EXPR) != 0) {
0925: mode = EXPR;
0926: t = F.at(pos1).Binary(op, t,
0927: term2Rest(t1, TreeInfo.shiftPrec));
0928: t = termRest(term1Rest(term2Rest(t,
0929: TreeInfo.orPrec)));
0930: } else {
0931: accept(GT);
0932: }
0933: } else {
0934: t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
0935: }
0936: accept(RPAREN);
0937: lastmode = mode;
0938: mode = EXPR;
0939: if ((lastmode & EXPR) == 0) {
0940: JCExpression t1 = term3();
0941: return F.at(pos).TypeCast(t, t1);
0942: } else if ((lastmode & TYPE) != 0) {
0943: switch (S.token()) {
0944: /*case PLUSPLUS: case SUBSUB: */
0945: case BANG:
0946: case TILDE:
0947: case LPAREN:
0948: case THIS:
0949: case SUPER:
0950: case INTLITERAL:
0951: case LONGLITERAL:
0952: case FLOATLITERAL:
0953: case DOUBLELITERAL:
0954: case CHARLITERAL:
0955: case STRINGLITERAL:
0956: case TRUE:
0957: case FALSE:
0958: case NULL:
0959: case NEW:
0960: case IDENTIFIER:
0961: case ASSERT:
0962: case ENUM:
0963: case BYTE:
0964: case SHORT:
0965: case CHAR:
0966: case INT:
0967: case LONG:
0968: case FLOAT:
0969: case DOUBLE:
0970: case BOOLEAN:
0971: case VOID:
0972: JCExpression t1 = term3();
0973: return F.at(pos).TypeCast(t, t1);
0974: }
0975: }
0976: } else
0977: return illegal();
0978: t = toP(F.at(pos).Parens(t));
0979: break;
0980: case THIS:
0981: if ((mode & EXPR) != 0) {
0982: mode = EXPR;
0983: t = to(F.at(pos).Ident(names._this ));
0984: S.nextToken();
0985: if (typeArgs == null)
0986: t = argumentsOpt(null, t);
0987: else
0988: t = arguments(typeArgs, t);
0989: typeArgs = null;
0990: } else
0991: return illegal();
0992: break;
0993: case SUPER:
0994: if ((mode & EXPR) != 0) {
0995: mode = EXPR;
0996: t = to(super Suffix(typeArgs, F.at(pos).Ident(
0997: names._super )));
0998: typeArgs = null;
0999: } else
1000: return illegal();
1001: break;
1002: case INTLITERAL:
1003: case LONGLITERAL:
1004: case FLOATLITERAL:
1005: case DOUBLELITERAL:
1006: case CHARLITERAL:
1007: case STRINGLITERAL:
1008: case TRUE:
1009: case FALSE:
1010: case NULL:
1011: if (typeArgs == null && (mode & EXPR) != 0) {
1012: mode = EXPR;
1013: t = literal(names.empty);
1014: } else
1015: return illegal();
1016: break;
1017: case NEW:
1018: if (typeArgs != null)
1019: return illegal();
1020: if ((mode & EXPR) != 0) {
1021: mode = EXPR;
1022: S.nextToken();
1023: if (S.token() == LT)
1024: typeArgs = typeArguments();
1025: t = creator(pos, typeArgs);
1026: typeArgs = null;
1027: } else
1028: return illegal();
1029: break;
1030: case IDENTIFIER:
1031: case ASSERT:
1032: case ENUM:
1033: if (typeArgs != null)
1034: return illegal();
1035: t = toP(F.at(S.pos()).Ident(ident()));
1036: loop: while (true) {
1037: pos = S.pos();
1038: switch (S.token()) {
1039: case LBRACKET:
1040: S.nextToken();
1041: if (S.token() == RBRACKET) {
1042: S.nextToken();
1043: t = bracketsOpt(t);
1044: t = toP(F.at(pos).TypeArray(t));
1045: t = bracketsSuffix(t);
1046: } else {
1047: if ((mode & EXPR) != 0) {
1048: mode = EXPR;
1049: JCExpression t1 = term();
1050: t = to(F.at(pos).Indexed(t, t1));
1051: }
1052: accept(RBRACKET);
1053: }
1054: break loop;
1055: case LPAREN:
1056: if ((mode & EXPR) != 0) {
1057: mode = EXPR;
1058: t = arguments(typeArgs, t);
1059: typeArgs = null;
1060: }
1061: break loop;
1062: case DOT:
1063: S.nextToken();
1064: typeArgs = typeArgumentsOpt(EXPR);
1065: if ((mode & EXPR) != 0) {
1066: switch (S.token()) {
1067: case CLASS:
1068: if (typeArgs != null)
1069: return illegal();
1070: mode = EXPR;
1071: t = to(F.at(pos).Select(t, names._class));
1072: S.nextToken();
1073: break loop;
1074: case THIS:
1075: if (typeArgs != null)
1076: return illegal();
1077: mode = EXPR;
1078: t = to(F.at(pos).Select(t, names._this ));
1079: S.nextToken();
1080: break loop;
1081: case SUPER:
1082: mode = EXPR;
1083: t = to(F.at(pos).Select(t, names._super ));
1084: t = super Suffix(typeArgs, t);
1085: typeArgs = null;
1086: break loop;
1087: case NEW:
1088: if (typeArgs != null)
1089: return illegal();
1090: mode = EXPR;
1091: int pos1 = S.pos();
1092: S.nextToken();
1093: if (S.token() == LT)
1094: typeArgs = typeArguments();
1095: t = innerCreator(pos1, typeArgs, t);
1096: typeArgs = null;
1097: break loop;
1098: }
1099: }
1100: // typeArgs saved for next loop iteration.
1101: t = toP(F.at(pos).Select(t, ident()));
1102: break;
1103: default:
1104: break loop;
1105: }
1106: }
1107: if (typeArgs != null)
1108: illegal();
1109: t = typeArgumentsOpt(t);
1110: break;
1111: case BYTE:
1112: case SHORT:
1113: case CHAR:
1114: case INT:
1115: case LONG:
1116: case FLOAT:
1117: case DOUBLE:
1118: case BOOLEAN:
1119: if (typeArgs != null)
1120: illegal();
1121: t = bracketsSuffix(bracketsOpt(basicType()));
1122: break;
1123: case VOID:
1124: if (typeArgs != null)
1125: illegal();
1126: if ((mode & EXPR) != 0) {
1127: S.nextToken();
1128: if (S.token() == DOT) {
1129: JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(
1130: TypeTags.VOID));
1131: t = bracketsSuffix(ti);
1132: } else {
1133: return illegal(pos);
1134: }
1135: } else {
1136: return illegal();
1137: }
1138: break;
1139: default:
1140: return illegal();
1141: }
1142: if (typeArgs != null)
1143: illegal();
1144: while (true) {
1145: int pos1 = S.pos();
1146: if (S.token() == LBRACKET) {
1147: S.nextToken();
1148: if ((mode & TYPE) != 0) {
1149: int oldmode = mode;
1150: mode = TYPE;
1151: if (S.token() == RBRACKET) {
1152: S.nextToken();
1153: t = bracketsOpt(t);
1154: t = toP(F.at(pos1).TypeArray(t));
1155: return t;
1156: }
1157: mode = oldmode;
1158: }
1159: if ((mode & EXPR) != 0) {
1160: mode = EXPR;
1161: JCExpression t1 = term();
1162: t = to(F.at(pos1).Indexed(t, t1));
1163: }
1164: accept(RBRACKET);
1165: } else if (S.token() == DOT) {
1166: S.nextToken();
1167: typeArgs = typeArgumentsOpt(EXPR);
1168: if (S.token() == SUPER && (mode & EXPR) != 0) {
1169: mode = EXPR;
1170: t = to(F.at(pos1).Select(t, names._super ));
1171: S.nextToken();
1172: t = arguments(typeArgs, t);
1173: typeArgs = null;
1174: } else if (S.token() == NEW && (mode & EXPR) != 0) {
1175: if (typeArgs != null)
1176: return illegal();
1177: mode = EXPR;
1178: int pos2 = S.pos();
1179: S.nextToken();
1180: if (S.token() == LT)
1181: typeArgs = typeArguments();
1182: t = innerCreator(pos2, typeArgs, t);
1183: typeArgs = null;
1184: } else {
1185: t = toP(F.at(pos1).Select(t, ident()));
1186: t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1187: typeArgs = null;
1188: }
1189: } else {
1190: break;
1191: }
1192: }
1193: while ((S.token() == PLUSPLUS || S.token() == SUBSUB)
1194: && (mode & EXPR) != 0) {
1195: mode = EXPR;
1196: t = to(F.at(S.pos()).Unary(
1197: S.token() == PLUSPLUS ? JCTree.POSTINC
1198: : JCTree.POSTDEC, t));
1199: S.nextToken();
1200: }
1201: return toP(t);
1202: }
1203:
1204: /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1205: */
1206: JCExpression super Suffix(List<JCExpression> typeArgs, JCExpression t) {
1207: S.nextToken();
1208: if (S.token() == LPAREN || typeArgs != null) {
1209: t = arguments(typeArgs, t);
1210: } else {
1211: int pos = S.pos();
1212: accept(DOT);
1213: typeArgs = (S.token() == LT) ? typeArguments() : null;
1214: t = toP(F.at(pos).Select(t, ident()));
1215: t = argumentsOpt(typeArgs, t);
1216: }
1217: return t;
1218: }
1219:
1220: /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1221: */
1222: JCPrimitiveTypeTree basicType() {
1223: JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(
1224: typetag(S.token())));
1225: S.nextToken();
1226: return t;
1227: }
1228:
1229: /** ArgumentsOpt = [ Arguments ]
1230: */
1231: JCExpression argumentsOpt(List<JCExpression> typeArgs,
1232: JCExpression t) {
1233: if ((mode & EXPR) != 0 && S.token() == LPAREN
1234: || typeArgs != null) {
1235: mode = EXPR;
1236: return arguments(typeArgs, t);
1237: } else {
1238: return t;
1239: }
1240: }
1241:
1242: /** Arguments = "(" [Expression { COMMA Expression }] ")"
1243: */
1244: List<JCExpression> arguments() {
1245: ListBuffer<JCExpression> args = lb();
1246: if (S.token() == LPAREN) {
1247: S.nextToken();
1248: if (S.token() != RPAREN) {
1249: args.append(expression());
1250: while (S.token() == COMMA) {
1251: S.nextToken();
1252: args.append(expression());
1253: }
1254: }
1255: accept(RPAREN);
1256: } else {
1257: syntaxError(S.pos(), "expected", keywords
1258: .token2string(LPAREN));
1259: }
1260: return args.toList();
1261: }
1262:
1263: JCMethodInvocation arguments(List<JCExpression> typeArgs,
1264: JCExpression t) {
1265: int pos = S.pos();
1266: List<JCExpression> args = arguments();
1267: return toP(F.at(pos).Apply(typeArgs, t, args));
1268: }
1269:
1270: /** TypeArgumentsOpt = [ TypeArguments ]
1271: */
1272: JCExpression typeArgumentsOpt(JCExpression t) {
1273: if (S.token() == LT && (mode & TYPE) != 0
1274: && (mode & NOPARAMS) == 0) {
1275: mode = TYPE;
1276: checkGenerics();
1277: return typeArguments(t);
1278: } else {
1279: return t;
1280: }
1281: }
1282:
1283: List<JCExpression> typeArgumentsOpt() {
1284: return typeArgumentsOpt(TYPE);
1285: }
1286:
1287: List<JCExpression> typeArgumentsOpt(int useMode) {
1288: if (S.token() == LT) {
1289: checkGenerics();
1290: if ((mode & useMode) == 0 || (mode & NOPARAMS) != 0) {
1291: illegal();
1292: }
1293: mode = useMode;
1294: return typeArguments();
1295: }
1296: return null;
1297: }
1298:
1299: /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
1300: */
1301: List<JCExpression> typeArguments() {
1302: ListBuffer<JCExpression> args = lb();
1303: if (S.token() == LT) {
1304: S.nextToken();
1305: args.append(((mode & EXPR) == 0) ? typeArgument() : type());
1306: while (S.token() == COMMA) {
1307: S.nextToken();
1308: args.append(((mode & EXPR) == 0) ? typeArgument()
1309: : type());
1310: }
1311: switch (S.token()) {
1312: case GTGTGTEQ:
1313: S.token(GTGTEQ);
1314: break;
1315: case GTGTEQ:
1316: S.token(GTEQ);
1317: break;
1318: case GTEQ:
1319: S.token(EQ);
1320: break;
1321: case GTGTGT:
1322: S.token(GTGT);
1323: break;
1324: case GTGT:
1325: S.token(GT);
1326: break;
1327: default:
1328: accept(GT);
1329: break;
1330: }
1331: } else {
1332: syntaxError(S.pos(), "expected", keywords.token2string(LT));
1333: }
1334: return args.toList();
1335: }
1336:
1337: /** TypeArgument = Type
1338: * | "?"
1339: * | "?" EXTENDS Type {"&" Type}
1340: * | "?" SUPER Type
1341: */
1342: JCExpression typeArgument() {
1343: if (S.token() != QUES)
1344: return type();
1345: int pos = S.pos();
1346: S.nextToken();
1347: if (S.token() == EXTENDS) {
1348: TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(
1349: BoundKind.EXTENDS));
1350: S.nextToken();
1351: return F.at(pos).Wildcard(t, type());
1352: } else if (S.token() == SUPER) {
1353: TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(
1354: BoundKind.SUPER));
1355: S.nextToken();
1356: return F.at(pos).Wildcard(t, type());
1357: } else if (S.token() == IDENTIFIER) {
1358: //error recovery
1359: reportSyntaxError(S.prevEndPos(), "expected3", keywords
1360: .token2string(GT), keywords.token2string(EXTENDS),
1361: keywords.token2string(SUPER));
1362: TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(
1363: BoundKind.UNBOUND);
1364: JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1365: JCIdent id = toP(F.at(S.pos()).Ident(ident()));
1366: return F.at(pos).Erroneous(List.<JCTree> of(wc, id));
1367: } else {
1368: TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(
1369: BoundKind.UNBOUND);
1370: return toP(F.at(pos).Wildcard(t, null));
1371: }
1372: }
1373:
1374: JCTypeApply typeArguments(JCExpression t) {
1375: int pos = S.pos();
1376: List<JCExpression> args = typeArguments();
1377: return toP(F.at(pos).TypeApply(t, args));
1378: }
1379:
1380: /** BracketsOpt = {"[" "]"}
1381: */
1382: private JCExpression bracketsOpt(JCExpression t) {
1383: if (S.token() == LBRACKET) {
1384: int pos = S.pos();
1385: S.nextToken();
1386: t = bracketsOptCont(t, pos);
1387: F.at(pos);
1388: }
1389: return t;
1390: }
1391:
1392: private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1393: accept(RBRACKET);
1394: t = bracketsOpt(t);
1395: return toP(F.at(pos).TypeArray(t));
1396: }
1397:
1398: /** BracketsSuffixExpr = "." CLASS
1399: * BracketsSuffixType =
1400: */
1401: JCExpression bracketsSuffix(JCExpression t) {
1402: if ((mode & EXPR) != 0 && S.token() == DOT) {
1403: mode = EXPR;
1404: int pos = S.pos();
1405: S.nextToken();
1406: accept(CLASS);
1407: if (S.pos() == errorEndPos) {
1408: // error recovery
1409: Name name = null;
1410: if (S.token() == IDENTIFIER) {
1411: name = S.name();
1412: S.nextToken();
1413: } else {
1414: name = names.error;
1415: }
1416: t = F.at(pos).Erroneous(
1417: List
1418: .<JCTree> of(toP(F.at(pos).Select(t,
1419: name))));
1420: } else {
1421: t = toP(F.at(pos).Select(t, names._class));
1422: }
1423: } else if ((mode & TYPE) != 0) {
1424: mode = TYPE;
1425: } else {
1426: syntaxError(S.pos(), "dot.class.expected");
1427: }
1428: return t;
1429: }
1430:
1431: /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1432: */
1433: JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1434: switch (S.token()) {
1435: case BYTE:
1436: case SHORT:
1437: case CHAR:
1438: case INT:
1439: case LONG:
1440: case FLOAT:
1441: case DOUBLE:
1442: case BOOLEAN:
1443: if (typeArgs == null)
1444: return arrayCreatorRest(newpos, basicType());
1445: break;
1446: default:
1447: }
1448: JCExpression t = qualident();
1449: int oldmode = mode;
1450: mode = TYPE;
1451: if (S.token() == LT) {
1452: checkGenerics();
1453: t = typeArguments(t);
1454: }
1455: while (S.token() == DOT) {
1456: int pos = S.pos();
1457: S.nextToken();
1458: t = toP(F.at(pos).Select(t, ident()));
1459: if (S.token() == LT) {
1460: checkGenerics();
1461: t = typeArguments(t);
1462: }
1463: }
1464: mode = oldmode;
1465: if (S.token() == LBRACKET) {
1466: JCExpression e = arrayCreatorRest(newpos, t);
1467: if (typeArgs != null) {
1468: int pos = newpos;
1469: if (!typeArgs.isEmpty()
1470: && typeArgs.head.pos != Position.NOPOS) {
1471: // note: this should always happen but we should
1472: // not rely on this as the parser is continuously
1473: // modified to improve error recovery.
1474: pos = typeArgs.head.pos;
1475: }
1476: setErrorEndPos(S.prevEndPos());
1477: reportSyntaxError(pos,
1478: "cannot.create.array.with.type.arguments");
1479: return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
1480: }
1481: return e;
1482: } else if (S.token() == LPAREN) {
1483: return classCreatorRest(newpos, null, typeArgs, t);
1484: } else {
1485: reportSyntaxError(S.pos(), "expected2", keywords
1486: .token2string(LPAREN), keywords
1487: .token2string(LBRACKET));
1488: t = toP(F.at(newpos).NewClass(null, typeArgs, t,
1489: List.<JCExpression> nil(), null));
1490: return toP(F.at(newpos).Erroneous(List.<JCTree> of(t)));
1491: }
1492: }
1493:
1494: /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1495: */
1496: JCExpression innerCreator(int newpos, List<JCExpression> typeArgs,
1497: JCExpression encl) {
1498: JCExpression t = toP(F.at(S.pos()).Ident(ident()));
1499: if (S.token() == LT) {
1500: checkGenerics();
1501: t = typeArguments(t);
1502: }
1503: return classCreatorRest(newpos, encl, typeArgs, t);
1504: }
1505:
1506: /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1507: * | Expression "]" {"[" Expression "]"} BracketsOpt )
1508: */
1509: JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1510: accept(LBRACKET);
1511: if (S.token() == RBRACKET) {
1512: accept(RBRACKET);
1513: elemtype = bracketsOpt(elemtype);
1514: if (S.token() == LBRACE) {
1515: return arrayInitializer(newpos, elemtype);
1516: } else {
1517: return syntaxError(S.pos(), "array.dimension.missing");
1518: }
1519: } else {
1520: ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1521: dims.append(expression());
1522: accept(RBRACKET);
1523: while (S.token() == LBRACKET) {
1524: int pos = S.pos();
1525: S.nextToken();
1526: if (S.token() == RBRACKET) {
1527: elemtype = bracketsOptCont(elemtype, pos);
1528: } else {
1529: dims.append(expression());
1530: accept(RBRACKET);
1531: }
1532: }
1533: return toP(F.at(newpos).NewArray(elemtype, dims.toList(),
1534: null));
1535: }
1536: }
1537:
1538: /** ClassCreatorRest = Arguments [ClassBody]
1539: */
1540: JCExpression classCreatorRest(int newpos, JCExpression encl,
1541: List<JCExpression> typeArgs, JCExpression t) {
1542: List<JCExpression> args = arguments();
1543: JCClassDecl body = null;
1544: if (S.token() == LBRACE) {
1545: int pos = S.pos();
1546: List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1547: JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1548: body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1549: }
1550: return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1551: }
1552:
1553: /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1554: */
1555: JCExpression arrayInitializer(int newpos, JCExpression t) {
1556: accept(LBRACE);
1557: ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1558: if (S.token() == COMMA) {
1559: S.nextToken();
1560: } else if (S.token() != RBRACE) {
1561: elems.append(variableInitializer());
1562: while (S.token() == COMMA) {
1563: S.nextToken();
1564: if (S.token() == RBRACE)
1565: break;
1566: elems.append(variableInitializer());
1567: }
1568: }
1569: accept(RBRACE);
1570: return toP(F.at(newpos).NewArray(t, List.<JCExpression> nil(),
1571: elems.toList()));
1572: }
1573:
1574: /** VariableInitializer = ArrayInitializer | Expression
1575: */
1576: public JCExpression variableInitializer() {
1577: return S.token() == LBRACE ? arrayInitializer(S.pos(), null)
1578: : expression();
1579: }
1580:
1581: /** ParExpression = "(" Expression ")"
1582: */
1583: JCExpression parExpression() {
1584: accept(LPAREN);
1585: JCExpression t = expression();
1586: accept(RPAREN);
1587: return t;
1588: }
1589:
1590: /** Block = "{" BlockStatements "}"
1591: */
1592: JCBlock block(int pos, long flags) {
1593: accept(LBRACE);
1594: List<JCStatement> stats = blockStatements();
1595: JCBlock t = F.at(pos).Block(flags, stats);
1596: while (S.token() == CASE || S.token() == DEFAULT) {
1597: syntaxError("orphaned", keywords.token2string(S.token()));
1598: switchBlockStatementGroups();
1599: }
1600: // the Block node has a field "endpos" for first char of last token, which is
1601: // usually but not necessarily the last char of the last token.
1602: t.endpos = S.pos();
1603: accept(RBRACE);
1604: return toP(t);
1605: }
1606:
1607: public JCBlock block() {
1608: return block(S.pos(), 0);
1609: }
1610:
1611: /** BlockStatements = { BlockStatement }
1612: * BlockStatement = LocalVariableDeclarationStatement
1613: * | ClassOrInterfaceOrEnumDeclaration
1614: * | [Ident ":"] Statement
1615: * LocalVariableDeclarationStatement
1616: * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1617: */
1618: @SuppressWarnings("fallthrough")
1619: List<JCStatement> blockStatements() {
1620: //todo: skip to anchor on error(?)
1621: int lastErrPos = -1;
1622: ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1623: while (true) {
1624: int pos = S.pos();
1625: switch (S.token()) {
1626: case RBRACE:
1627: case CASE:
1628: case DEFAULT:
1629: case EOF:
1630: return stats.toList();
1631: case LBRACE:
1632: case IF:
1633: case FOR:
1634: case WHILE:
1635: case DO:
1636: case TRY:
1637: case SWITCH:
1638: case SYNCHRONIZED:
1639: case RETURN:
1640: case THROW:
1641: case BREAK:
1642: case CONTINUE:
1643: case SEMI:
1644: case ELSE:
1645: case FINALLY:
1646: case CATCH:
1647: stats.append(statement());
1648: break;
1649: case MONKEYS_AT:
1650: case FINAL: {
1651: String dc = S.docComment();
1652: JCModifiers mods = modifiersOpt();
1653: if (S.token() == INTERFACE || S.token() == CLASS
1654: || allowEnums && S.token() == ENUM) {
1655: stats.append(classOrInterfaceOrEnumDeclaration(
1656: mods, dc));
1657: } else {
1658: JCExpression t = type();
1659: stats.appendList(variableDeclarators(mods, t,
1660: new ListBuffer<JCStatement>()));
1661: // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1662: storeEnd(stats.elems.last(), S.endPos());
1663: accept(SEMI);
1664: }
1665: break;
1666: }
1667: case ABSTRACT:
1668: case STRICTFP: {
1669: String dc = S.docComment();
1670: JCModifiers mods = modifiersOpt();
1671: stats
1672: .append(classOrInterfaceOrEnumDeclaration(mods,
1673: dc));
1674: break;
1675: }
1676: case INTERFACE:
1677: case CLASS:
1678: stats.append(classOrInterfaceOrEnumDeclaration(
1679: modifiersOpt(), S.docComment()));
1680: break;
1681: case ENUM:
1682: case ASSERT:
1683: if (allowEnums && S.token() == ENUM) {
1684: log.error(S.pos(), "local.enum");
1685: stats.append(classOrInterfaceOrEnumDeclaration(
1686: modifiersOpt(), S.docComment()));
1687: break;
1688: } else if (allowAsserts && S.token() == ASSERT) {
1689: stats.append(statement());
1690: break;
1691: }
1692: /* fall through to default */
1693: default:
1694: Name name = S.name();
1695: JCExpression t = term(EXPR | TYPE);
1696: if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
1697: S.nextToken();
1698: JCStatement stat = statement();
1699: stats.append(F.at(pos).Labelled(name, stat));
1700: } else if ((lastmode & TYPE) != 0
1701: && (S.token() == IDENTIFIER
1702: || S.token() == ASSERT || S.token() == ENUM)) {
1703: pos = S.pos();
1704: JCModifiers mods = F.at(Position.NOPOS)
1705: .Modifiers(0);
1706: F.at(pos);
1707: stats.appendList(variableDeclarators(mods, t,
1708: new ListBuffer<JCStatement>()));
1709: // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1710: storeEnd(stats.elems.last(), S.endPos());
1711: accept(SEMI);
1712: } else {
1713: // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1714: stats.append(to(F.at(pos).Exec(checkExprStat(t))));
1715: accept(SEMI);
1716: }
1717: }
1718:
1719: // error recovery
1720: if (S.pos() == lastErrPos)
1721: return stats.toList();
1722: if (S.pos() <= errorEndPos) {
1723: skip(false, true, true, true);
1724: lastErrPos = S.pos();
1725: }
1726:
1727: // ensure no dangling /** @deprecated */ active
1728: S.resetDeprecatedFlag();
1729: }
1730: }
1731:
1732: /** Statement =
1733: * Block
1734: * | IF ParExpression Statement [ELSE Statement]
1735: * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1736: * | FOR "(" FormalParameter : Expression ")" Statement
1737: * | WHILE ParExpression Statement
1738: * | DO Statement WHILE ParExpression ";"
1739: * | TRY Block ( Catches | [Catches] FinallyPart )
1740: * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1741: * | SYNCHRONIZED ParExpression Block
1742: * | RETURN [Expression] ";"
1743: * | THROW Expression ";"
1744: * | BREAK [Ident] ";"
1745: * | CONTINUE [Ident] ";"
1746: * | ASSERT Expression [ ":" Expression ] ";"
1747: * | ";"
1748: * | ExpressionStatement
1749: * | Ident ":" Statement
1750: */
1751: @SuppressWarnings("fallthrough")
1752: public JCStatement statement() {
1753: int pos = S.pos();
1754: switch (S.token()) {
1755: case LBRACE:
1756: return block();
1757: case IF: {
1758: S.nextToken();
1759: JCExpression cond = parExpression();
1760: JCStatement thenpart = statement();
1761: JCStatement elsepart = null;
1762: if (S.token() == ELSE) {
1763: S.nextToken();
1764: elsepart = statement();
1765: }
1766: return F.at(pos).If(cond, thenpart, elsepart);
1767: }
1768: case FOR: {
1769: S.nextToken();
1770: accept(LPAREN);
1771: List<JCStatement> inits = S.token() == SEMI ? List
1772: .<JCStatement> nil() : forInit();
1773: if (inits.length() == 1
1774: && inits.head.getTag() == JCTree.VARDEF
1775: && ((JCVariableDecl) inits.head).init == null
1776: && S.token() == COLON) {
1777: checkForeach();
1778: JCVariableDecl var = (JCVariableDecl) inits.head;
1779: accept(COLON);
1780: JCExpression expr = expression();
1781: accept(RPAREN);
1782: JCStatement body = statement();
1783: return F.at(pos).ForeachLoop(var, expr, body);
1784: } else {
1785: accept(SEMI);
1786: JCExpression cond = S.token() == SEMI ? null
1787: : expression();
1788: accept(SEMI);
1789: List<JCExpressionStatement> steps = S.token() == RPAREN ? List
1790: .<JCExpressionStatement> nil()
1791: : forUpdate();
1792: accept(RPAREN);
1793: JCStatement body = statement();
1794: return F.at(pos).ForLoop(inits, cond, steps, body);
1795: }
1796: }
1797: case WHILE: {
1798: S.nextToken();
1799: JCExpression cond = parExpression();
1800: JCStatement body = statement();
1801: return F.at(pos).WhileLoop(cond, body);
1802: }
1803: case DO: {
1804: S.nextToken();
1805: JCStatement body = statement();
1806: accept(WHILE);
1807: JCExpression cond = parExpression();
1808: JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
1809: accept(SEMI);
1810: return t;
1811: }
1812: case TRY: {
1813: S.nextToken();
1814: JCBlock body = block();
1815: ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
1816: JCBlock finalizer = null;
1817: if (S.token() == CATCH || S.token() == FINALLY) {
1818: while (S.token() == CATCH)
1819: catchers.append(catchClause());
1820: if (S.token() == FINALLY) {
1821: S.nextToken();
1822: finalizer = block();
1823: }
1824: } else {
1825: log.error(pos, "try.without.catch.or.finally");
1826: }
1827: return F.at(pos).Try(body, catchers.toList(), finalizer);
1828: }
1829: case SWITCH: {
1830: S.nextToken();
1831: JCExpression selector = parExpression();
1832: accept(LBRACE);
1833: List<JCCase> cases = switchBlockStatementGroups();
1834: JCSwitch t = to(F.at(pos).Switch(selector, cases));
1835: accept(RBRACE);
1836: return t;
1837: }
1838: case SYNCHRONIZED: {
1839: S.nextToken();
1840: JCExpression lock = parExpression();
1841: JCBlock body = block();
1842: return F.at(pos).Synchronized(lock, body);
1843: }
1844: case RETURN: {
1845: S.nextToken();
1846: JCExpression result = S.token() == SEMI ? null
1847: : expression();
1848: JCReturn t = to(F.at(pos).Return(result));
1849: accept(SEMI);
1850: return t;
1851: }
1852: case THROW: {
1853: S.nextToken();
1854: JCExpression exc = expression();
1855: JCThrow t = to(F.at(pos).Throw(exc));
1856: accept(SEMI);
1857: return t;
1858: }
1859: case BREAK: {
1860: S.nextToken();
1861: Name label = (S.token() == IDENTIFIER
1862: || S.token() == ASSERT || S.token() == ENUM) ? ident()
1863: : null;
1864: JCBreak t = to(F.at(pos).Break(label));
1865: accept(SEMI);
1866: return t;
1867: }
1868: case CONTINUE: {
1869: S.nextToken();
1870: Name label = (S.token() == IDENTIFIER
1871: || S.token() == ASSERT || S.token() == ENUM) ? ident()
1872: : null;
1873: JCContinue t = to(F.at(pos).Continue(label));
1874: accept(SEMI);
1875: return t;
1876: }
1877: case SEMI:
1878: S.nextToken();
1879: return toP(F.at(pos).Skip());
1880: case ELSE:
1881: return toP(F.Exec(syntaxError("else.without.if")));
1882: case FINALLY:
1883: return toP(F.Exec(syntaxError("finally.without.try")));
1884: case CATCH:
1885: return toP(F.Exec(syntaxError("catch.without.try")));
1886: case ASSERT: {
1887: if (allowAsserts && S.token() == ASSERT) {
1888: S.nextToken();
1889: JCExpression assertion = expression();
1890: JCExpression message = null;
1891: if (S.token() == COLON) {
1892: S.nextToken();
1893: message = expression();
1894: }
1895: JCAssert t = to(F.at(pos).Assert(assertion, message));
1896: accept(SEMI);
1897: return t;
1898: }
1899: /* else fall through to default case */
1900: }
1901: case ENUM:
1902: default:
1903: Name name = S.name();
1904: JCExpression expr = expression();
1905: if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
1906: S.nextToken();
1907: JCStatement stat = statement();
1908: return F.at(pos).Labelled(name, stat);
1909: } else {
1910: // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1911: JCExpressionStatement stat = to(F.at(pos).Exec(
1912: checkExprStat(expr)));
1913: accept(SEMI);
1914: return stat;
1915: }
1916: }
1917: }
1918:
1919: /** CatchClause = CATCH "(" FormalParameter ")" Block
1920: */
1921: JCCatch catchClause() {
1922: int pos = S.pos();
1923: accept(CATCH);
1924: accept(LPAREN);
1925: JCVariableDecl formal = variableDeclaratorId(
1926: optFinal(Flags.PARAMETER), qualident());
1927: accept(RPAREN);
1928: JCBlock body = block();
1929: return F.at(pos).Catch(formal, body);
1930: }
1931:
1932: /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
1933: * SwitchBlockStatementGroup = SwitchLabel BlockStatements
1934: * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
1935: */
1936: List<JCCase> switchBlockStatementGroups() {
1937: ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
1938: while (true) {
1939: int pos = S.pos();
1940: switch (S.token()) {
1941: case CASE: {
1942: S.nextToken();
1943: JCExpression pat = expression();
1944: accept(COLON);
1945: List<JCStatement> stats = blockStatements();
1946: JCCase c = F.at(pos).Case(pat, stats);
1947: if (stats.isEmpty())
1948: storeEnd(c, S.prevEndPos());
1949: cases.append(c);
1950: break;
1951: }
1952: case DEFAULT: {
1953: S.nextToken();
1954: accept(COLON);
1955: List<JCStatement> stats = blockStatements();
1956: JCCase c = F.at(pos).Case(null, stats);
1957: if (stats.isEmpty())
1958: storeEnd(c, S.prevEndPos());
1959: cases.append(c);
1960: break;
1961: }
1962: case RBRACE:
1963: case EOF:
1964: return cases.toList();
1965: default:
1966: S.nextToken(); // to ensure progress
1967: syntaxError(pos, "expected3", keywords
1968: .token2string(CASE), keywords
1969: .token2string(DEFAULT), keywords
1970: .token2string(RBRACE));
1971: }
1972: }
1973: }
1974:
1975: /** MoreStatementExpressions = { COMMA StatementExpression }
1976: */
1977: <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(
1978: int pos, JCExpression first, T stats) {
1979: // This Exec is a "StatementExpression"; it subsumes no terminating token
1980: stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
1981: while (S.token() == COMMA) {
1982: S.nextToken();
1983: pos = S.pos();
1984: JCExpression t = expression();
1985: // This Exec is a "StatementExpression"; it subsumes no terminating token
1986: stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
1987: }
1988: return stats;
1989: }
1990:
1991: /** ForInit = StatementExpression MoreStatementExpressions
1992: * | { FINAL | '@' Annotation } Type VariableDeclarators
1993: */
1994: List<JCStatement> forInit() {
1995: ListBuffer<JCStatement> stats = lb();
1996: int pos = S.pos();
1997: if (S.token() == FINAL || S.token() == MONKEYS_AT) {
1998: return variableDeclarators(optFinal(0), type(), stats)
1999: .toList();
2000: } else {
2001: JCExpression t = term(EXPR | TYPE);
2002: if ((lastmode & TYPE) != 0
2003: && (S.token() == IDENTIFIER || S.token() == ASSERT || S
2004: .token() == ENUM))
2005: return variableDeclarators(modifiersOpt(), t, stats)
2006: .toList();
2007: else
2008: return moreStatementExpressions(pos, t, stats).toList();
2009: }
2010: }
2011:
2012: /** ForUpdate = StatementExpression MoreStatementExpressions
2013: */
2014: List<JCExpressionStatement> forUpdate() {
2015: return moreStatementExpressions(S.pos(), expression(),
2016: new ListBuffer<JCExpressionStatement>()).toList();
2017: }
2018:
2019: /** AnnotationsOpt = { '@' Annotation }
2020: */
2021: List<JCAnnotation> annotationsOpt() {
2022: if (S.token() != MONKEYS_AT)
2023: return List.nil(); // optimization
2024: ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
2025: while (S.token() == MONKEYS_AT) {
2026: int pos = S.pos();
2027: S.nextToken();
2028: buf.append(annotation(pos));
2029: }
2030: return buf.toList();
2031: }
2032:
2033: /** ModifiersOpt = { Modifier }
2034: * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
2035: * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
2036: * | "@" Annotation
2037: */
2038: JCModifiers modifiersOpt() {
2039: return modifiersOpt(null);
2040: }
2041:
2042: JCModifiers modifiersOpt(JCModifiers partial) {
2043: long flags = (partial == null) ? 0 : partial.flags;
2044: if (S.deprecatedFlag()) {
2045: flags |= Flags.DEPRECATED;
2046: S.resetDeprecatedFlag();
2047: }
2048: ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
2049: if (partial != null)
2050: annotations.appendList(partial.annotations);
2051: int pos = S.pos();
2052: int lastPos = Position.NOPOS;
2053: loop: while (true) {
2054: long flag;
2055: switch (S.token()) {
2056: case PRIVATE:
2057: flag = Flags.PRIVATE;
2058: break;
2059: case PROTECTED:
2060: flag = Flags.PROTECTED;
2061: break;
2062: case PUBLIC:
2063: flag = Flags.PUBLIC;
2064: break;
2065: case STATIC:
2066: flag = Flags.STATIC;
2067: break;
2068: case TRANSIENT:
2069: flag = Flags.TRANSIENT;
2070: break;
2071: case FINAL:
2072: flag = Flags.FINAL;
2073: break;
2074: case ABSTRACT:
2075: flag = Flags.ABSTRACT;
2076: break;
2077: case NATIVE:
2078: flag = Flags.NATIVE;
2079: break;
2080: case VOLATILE:
2081: flag = Flags.VOLATILE;
2082: break;
2083: case SYNCHRONIZED:
2084: flag = Flags.SYNCHRONIZED;
2085: break;
2086: case STRICTFP:
2087: flag = Flags.STRICTFP;
2088: break;
2089: case MONKEYS_AT:
2090: flag = Flags.ANNOTATION;
2091: break;
2092: default:
2093: break loop;
2094: }
2095: if ((flags & flag) != 0)
2096: log.error(S.pos(), "repeated.modifier");
2097: lastPos = S.pos();
2098: S.nextToken();
2099: if (flag == Flags.ANNOTATION) {
2100: checkAnnotations();
2101: if (S.token() != INTERFACE) {
2102: JCAnnotation ann = annotation(lastPos);
2103: // if first modifier is an annotation, set pos to annotation's.
2104: if (flags == 0 && annotations.isEmpty())
2105: pos = ann.pos;
2106: annotations.append(ann);
2107: lastPos = ann.pos;
2108: flag = 0;
2109: }
2110: }
2111: flags |= flag;
2112: }
2113: switch (S.token()) {
2114: case ENUM:
2115: flags |= Flags.ENUM;
2116: break;
2117: case INTERFACE:
2118: flags |= Flags.INTERFACE;
2119: break;
2120: default:
2121: break;
2122: }
2123:
2124: /* A modifiers tree with no modifier tokens or annotations
2125: * has no text position. */
2126: if (flags == 0 && annotations.isEmpty())
2127: pos = Position.NOPOS;
2128:
2129: JCModifiers mods = F.at(pos).Modifiers(flags,
2130: annotations.toList());
2131: if (pos != Position.NOPOS)
2132: storeEnd(mods, S.prevEndPos());
2133: return mods;
2134: }
2135:
2136: /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2137: * @param pos position of "@" token
2138: */
2139: JCAnnotation annotation(int pos) {
2140: // accept(AT); // AT consumed by caller
2141: checkAnnotations();
2142: JCTree ident = qualident();
2143: List<JCExpression> fieldValues = annotationFieldValuesOpt();
2144: JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
2145: storeEnd(ann, S.prevEndPos());
2146: return ann;
2147: }
2148:
2149: List<JCExpression> annotationFieldValuesOpt() {
2150: return (S.token() == LPAREN) ? annotationFieldValues() : List
2151: .<JCExpression> nil();
2152: }
2153:
2154: /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2155: List<JCExpression> annotationFieldValues() {
2156: accept(LPAREN);
2157: ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2158: if (S.token() != RPAREN) {
2159: buf.append(annotationFieldValue());
2160: while (S.token() == COMMA) {
2161: S.nextToken();
2162: buf.append(annotationFieldValue());
2163: }
2164: }
2165: accept(RPAREN);
2166: return buf.toList();
2167: }
2168:
2169: /** AnnotationFieldValue = AnnotationValue
2170: * | Identifier "=" AnnotationValue
2171: */
2172: JCExpression annotationFieldValue() {
2173: if (S.token() == IDENTIFIER) {
2174: mode = EXPR;
2175: JCExpression t1 = term1();
2176: if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
2177: int pos = S.pos();
2178: accept(EQ);
2179: return toP(F.at(pos).Assign(t1, annotationValue()));
2180: } else {
2181: return t1;
2182: }
2183: }
2184: return annotationValue();
2185: }
2186:
2187: /* AnnotationValue = ConditionalExpression
2188: * | Annotation
2189: * | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
2190: */
2191: JCExpression annotationValue() {
2192: int pos;
2193: switch (S.token()) {
2194: case MONKEYS_AT:
2195: pos = S.pos();
2196: S.nextToken();
2197: return annotation(pos);
2198: case LBRACE:
2199: pos = S.pos();
2200: accept(LBRACE);
2201: ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2202: if (S.token() != RBRACE) {
2203: buf.append(annotationValue());
2204: while (S.token() == COMMA) {
2205: S.nextToken();
2206: if (S.token() == RPAREN)
2207: break;
2208: buf.append(annotationValue());
2209: }
2210: }
2211: accept(RBRACE);
2212: return toP(F.at(pos).NewArray(null,
2213: List.<JCExpression> nil(), buf.toList()));
2214: default:
2215: mode = EXPR;
2216: return term1();
2217: }
2218: }
2219:
2220: /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2221: */
2222: public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(
2223: JCModifiers mods, JCExpression type, T vdefs) {
2224: return variableDeclaratorsRest(S.pos(), mods, type, ident(),
2225: false, null, vdefs);
2226: }
2227:
2228: /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2229: * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2230: *
2231: * @param reqInit Is an initializer always required?
2232: * @param dc The documentation comment for the variable declarations, or null.
2233: */
2234: <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(
2235: int pos, JCModifiers mods, JCExpression type, Name name,
2236: boolean reqInit, String dc, T vdefs) {
2237: vdefs.append(variableDeclaratorRest(pos, mods, type, name,
2238: reqInit, dc));
2239: while (S.token() == COMMA) {
2240: // All but last of multiple declarators subsume a comma
2241: storeEnd((JCTree) vdefs.elems.last(), S.endPos());
2242: S.nextToken();
2243: vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2244: }
2245: return vdefs;
2246: }
2247:
2248: /** VariableDeclarator = Ident VariableDeclaratorRest
2249: * ConstantDeclarator = Ident ConstantDeclaratorRest
2250: */
2251: JCVariableDecl variableDeclarator(JCModifiers mods,
2252: JCExpression type, boolean reqInit, String dc) {
2253: return variableDeclaratorRest(S.pos(), mods, type, ident(),
2254: reqInit, dc);
2255: }
2256:
2257: /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2258: * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2259: *
2260: * @param reqInit Is an initializer always required?
2261: * @param dc The documentation comment for the variable declarations, or null.
2262: */
2263: JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods,
2264: JCExpression type, Name name, boolean reqInit, String dc) {
2265: type = bracketsOpt(type);
2266: JCExpression init = null;
2267: if (S.token() == EQ) {
2268: S.nextToken();
2269: init = variableInitializer();
2270: } else if (reqInit)
2271: syntaxError(S.pos(), "expected", keywords.token2string(EQ));
2272: JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type,
2273: init));
2274: attach(result, dc);
2275: return result;
2276: }
2277:
2278: /** VariableDeclaratorId = Ident BracketsOpt
2279: */
2280: JCVariableDecl variableDeclaratorId(JCModifiers mods,
2281: JCExpression type) {
2282: int pos = S.pos();
2283: Name name = ident();
2284: if ((mods.flags & Flags.VARARGS) == 0)
2285: type = bracketsOpt(type);
2286: return toP(F.at(pos).VarDef(mods, name, type, null));
2287: }
2288:
2289: /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2290: */
2291: public JCTree.JCCompilationUnit compilationUnit() {
2292: int pos = S.pos();
2293: JCExpression pid = null;
2294: String dc = S.docComment();
2295: JCModifiers mods = null;
2296: List<JCAnnotation> packageAnnotations = List.nil();
2297: if (S.token() == MONKEYS_AT)
2298: mods = modifiersOpt();
2299:
2300: if (S.token() == PACKAGE) {
2301: if (mods != null) {
2302: checkNoMods(mods.flags);
2303: packageAnnotations = mods.annotations;
2304: mods = null;
2305: }
2306: S.nextToken();
2307: pid = qualident();
2308: accept(SEMI);
2309: }
2310: ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2311: boolean checkForImports = true;
2312: while (S.token() != EOF) {
2313: if (S.pos() <= errorEndPos) {
2314: // error recovery
2315: skip(checkForImports, false, false, false);
2316: if (S.token() == EOF)
2317: break;
2318: }
2319: if (checkForImports && mods == null && S.token() == IMPORT) {
2320: defs.append(importDeclaration());
2321: } else {
2322: JCTree def = typeDeclaration(mods);
2323: if (def instanceof JCExpressionStatement)
2324: def = ((JCExpressionStatement) def).expr;
2325: defs.append(def);
2326: if (def instanceof JCClassDecl)
2327: checkForImports = false;
2328: mods = null;
2329: }
2330: }
2331: JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(
2332: packageAnnotations, pid, defs.toList());
2333: attach(toplevel, dc);
2334: if (defs.elems.isEmpty())
2335: storeEnd(toplevel, S.prevEndPos());
2336: if (keepDocComments)
2337: toplevel.docComments = docComments;
2338: return toplevel;
2339: }
2340:
2341: /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2342: */
2343: JCTree importDeclaration() {
2344: int pos = S.pos();
2345: S.nextToken();
2346: boolean importStatic = false;
2347: if (S.token() == STATIC) {
2348: checkStaticImports();
2349: importStatic = true;
2350: S.nextToken();
2351: }
2352: JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
2353: do {
2354: int pos1 = S.pos();
2355: accept(DOT);
2356: if (S.token() == STAR) {
2357: pid = to(F.at(pos1).Select(pid, names.asterisk));
2358: S.nextToken();
2359: break;
2360: } else {
2361: pid = toP(F.at(pos1).Select(pid, ident()));
2362: }
2363: } while (S.token() == DOT);
2364: accept(SEMI);
2365: return toP(F.at(pos).Import(pid, importStatic));
2366: }
2367:
2368: /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2369: * | ";"
2370: */
2371: JCTree typeDeclaration(JCModifiers mods) {
2372: int pos = S.pos();
2373: if (mods == null && S.token() == SEMI) {
2374: S.nextToken();
2375: return toP(F.at(pos).Skip());
2376: } else {
2377: String dc = S.docComment();
2378: return classOrInterfaceOrEnumDeclaration(
2379: modifiersOpt(mods), dc);
2380: }
2381: }
2382:
2383: /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2384: * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2385: * @param mods Any modifiers starting the class or interface declaration
2386: * @param dc The documentation comment for the class, or null.
2387: */
2388: JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods,
2389: String dc) {
2390: if (S.token() == CLASS) {
2391: return classDeclaration(mods, dc);
2392: } else if (S.token() == INTERFACE) {
2393: return interfaceDeclaration(mods, dc);
2394: } else if (allowEnums) {
2395: if (S.token() == ENUM) {
2396: return enumDeclaration(mods, dc);
2397: } else {
2398: int pos = S.pos();
2399: List<JCTree> errs;
2400: if (S.token() == IDENTIFIER) {
2401: errs = List.<JCTree> of(mods, toP(F.at(pos).Ident(
2402: ident())));
2403: setErrorEndPos(S.pos());
2404: } else {
2405: errs = List.<JCTree> of(mods);
2406: }
2407: return toP(F.Exec(syntaxError(pos, errs, "expected3",
2408: keywords.token2string(CLASS), keywords
2409: .token2string(INTERFACE), keywords
2410: .token2string(ENUM))));
2411: }
2412: } else {
2413: if (S.token() == ENUM) {
2414: log.error(S.pos(), "enums.not.supported.in.source",
2415: source.name);
2416: allowEnums = true;
2417: return enumDeclaration(mods, dc);
2418: }
2419: int pos = S.pos();
2420: List<JCTree> errs;
2421: if (S.token() == IDENTIFIER) {
2422: errs = List.<JCTree> of(mods, toP(F.at(pos).Ident(
2423: ident())));
2424: setErrorEndPos(S.pos());
2425: } else {
2426: errs = List.<JCTree> of(mods);
2427: }
2428: return toP(F.Exec(syntaxError(pos, errs, "expected2",
2429: keywords.token2string(CLASS), keywords
2430: .token2string(INTERFACE))));
2431: }
2432: }
2433:
2434: /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2435: * [IMPLEMENTS TypeList] ClassBody
2436: * @param mods The modifiers starting the class declaration
2437: * @param dc The documentation comment for the class, or null.
2438: */
2439: JCClassDecl classDeclaration(JCModifiers mods, String dc) {
2440: int pos = S.pos();
2441: accept(CLASS);
2442: Name name = ident();
2443:
2444: List<JCTypeParameter> typarams = typeParametersOpt();
2445:
2446: JCTree extending = null;
2447: if (S.token() == EXTENDS) {
2448: S.nextToken();
2449: extending = type();
2450: }
2451: List<JCExpression> implementing = List.nil();
2452: if (S.token() == IMPLEMENTS) {
2453: S.nextToken();
2454: implementing = typeList();
2455: }
2456: List<JCTree> defs = classOrInterfaceBody(name, false);
2457: JCClassDecl result = toP(F.at(pos).ClassDef(mods, name,
2458: typarams, extending, implementing, defs));
2459: attach(result, dc);
2460: return result;
2461: }
2462:
2463: /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2464: * [EXTENDS TypeList] InterfaceBody
2465: * @param mods The modifiers starting the interface declaration
2466: * @param dc The documentation comment for the interface, or null.
2467: */
2468: JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
2469: int pos = S.pos();
2470: accept(INTERFACE);
2471: Name name = ident();
2472:
2473: List<JCTypeParameter> typarams = typeParametersOpt();
2474:
2475: List<JCExpression> extending = List.nil();
2476: if (S.token() == EXTENDS) {
2477: S.nextToken();
2478: extending = typeList();
2479: }
2480: List<JCTree> defs = classOrInterfaceBody(name, true);
2481: JCClassDecl result = toP(F.at(pos).ClassDef(mods, name,
2482: typarams, null, extending, defs));
2483: attach(result, dc);
2484: return result;
2485: }
2486:
2487: /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2488: * @param mods The modifiers starting the enum declaration
2489: * @param dc The documentation comment for the enum, or null.
2490: */
2491: JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
2492: int pos = S.pos();
2493: accept(ENUM);
2494: Name name = ident();
2495:
2496: List<JCExpression> implementing = List.nil();
2497: if (S.token() == IMPLEMENTS) {
2498: S.nextToken();
2499: implementing = typeList();
2500: }
2501:
2502: List<JCTree> defs = enumBody(name);
2503: JCModifiers newMods = F.at(mods.pos).Modifiers(
2504: mods.flags | Flags.ENUM, mods.annotations);
2505: JCClassDecl result = toP(F.at(pos).ClassDef(newMods, name,
2506: List.<JCTypeParameter> nil(), null, implementing, defs));
2507: attach(result, dc);
2508: return result;
2509: }
2510:
2511: /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2512: * [ ";" {ClassBodyDeclaration} ] "}"
2513: */
2514: List<JCTree> enumBody(Name enumName) {
2515: accept(LBRACE);
2516: ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2517: if (S.token() == COMMA) {
2518: S.nextToken();
2519: } else if (S.token() != RBRACE && S.token() != SEMI) {
2520: defs.append(enumeratorDeclaration(enumName));
2521: while (S.token() == COMMA) {
2522: S.nextToken();
2523: if (S.token() == RBRACE || S.token() == SEMI)
2524: break;
2525: defs.append(enumeratorDeclaration(enumName));
2526: }
2527: if (S.token() != SEMI && S.token() != RBRACE) {
2528: defs.append(syntaxError(S.pos(), "expected3", keywords
2529: .token2string(COMMA), keywords
2530: .token2string(RBRACE), keywords
2531: .token2string(SEMI)));
2532: S.nextToken();
2533: }
2534: }
2535: if (S.token() == SEMI) {
2536: S.nextToken();
2537: while (S.token() != RBRACE && S.token() != EOF) {
2538: defs.appendList(classOrInterfaceBodyDeclaration(
2539: enumName, false));
2540: if (S.pos() <= errorEndPos) {
2541: // error recovery
2542: skip(false, true, true, false);
2543: }
2544: }
2545: }
2546: accept(RBRACE);
2547: return defs.toList();
2548: }
2549:
2550: /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2551: */
2552: JCTree enumeratorDeclaration(Name enumName) {
2553: String dc = S.docComment();
2554: int flags = Flags.PUBLIC | Flags.STATIC | Flags.FINAL
2555: | Flags.ENUM;
2556: if (S.deprecatedFlag()) {
2557: flags |= Flags.DEPRECATED;
2558: S.resetDeprecatedFlag();
2559: }
2560: int pos = S.pos();
2561: List<JCAnnotation> annotations = annotationsOpt();
2562: JCModifiers mods = F.at(
2563: annotations.isEmpty() ? Position.NOPOS : pos)
2564: .Modifiers(flags, annotations);
2565: List<JCExpression> typeArgs = typeArgumentsOpt();
2566: int identPos = S.pos();
2567: Name name = ident();
2568: int createPos = S.pos();
2569: List<JCExpression> args = (S.token() == LPAREN) ? arguments()
2570: : List.<JCExpression> nil();
2571: JCClassDecl body = null;
2572: if (S.token() == LBRACE) {
2573: JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(
2574: Flags.ENUM | Flags.STATIC);
2575: List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2576: body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2577: }
2578: if (args.isEmpty() && body == null)
2579: createPos = Position.NOPOS;
2580: JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
2581: JCNewClass create = F.at(createPos).NewClass(null, typeArgs,
2582: ident, args, body);
2583: if (createPos != Position.NOPOS)
2584: storeEnd(create, S.prevEndPos());
2585: ident = F.at(Position.NOPOS).Ident(enumName);
2586: JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2587: attach(result, dc);
2588: return result;
2589: }
2590:
2591: /** TypeList = Type {"," Type}
2592: */
2593: List<JCExpression> typeList() {
2594: ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2595: ts.append(type());
2596: while (S.token() == COMMA) {
2597: S.nextToken();
2598: ts.append(type());
2599: }
2600: return ts.toList();
2601: }
2602:
2603: /** ClassBody = "{" {ClassBodyDeclaration} "}"
2604: * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2605: */
2606: List<JCTree> classOrInterfaceBody(Name className,
2607: boolean isInterface) {
2608: accept(LBRACE);
2609: if (S.pos() <= errorEndPos) {
2610: // error recovery
2611: skip(false, true, false, false);
2612: if (S.token() == LBRACE)
2613: S.nextToken();
2614: }
2615: ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2616: while (S.token() != RBRACE && S.token() != EOF) {
2617: defs.appendList(classOrInterfaceBodyDeclaration(className,
2618: isInterface));
2619: if (S.pos() <= errorEndPos) {
2620: // error recovery
2621: skip(false, true, true, false);
2622: }
2623: }
2624: accept(RBRACE);
2625: return defs.toList();
2626: }
2627:
2628: /** ClassBodyDeclaration =
2629: * ";"
2630: * | [STATIC] Block
2631: * | ModifiersOpt
2632: * ( Type Ident
2633: * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2634: * | VOID Ident MethodDeclaratorRest
2635: * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2636: * | Ident ConstructorDeclaratorRest
2637: * | TypeParameters Ident ConstructorDeclaratorRest
2638: * | ClassOrInterfaceOrEnumDeclaration
2639: * )
2640: * InterfaceBodyDeclaration =
2641: * ";"
2642: * | ModifiersOpt Type Ident
2643: * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2644: */
2645: List<JCTree> classOrInterfaceBodyDeclaration(Name className,
2646: boolean isInterface) {
2647: if (S.token() == SEMI) {
2648: S.nextToken();
2649: return List.<JCTree> of(F.at(Position.NOPOS).Block(0,
2650: List.<JCStatement> nil()));
2651: } else {
2652: String dc = S.docComment();
2653: int pos = S.pos();
2654: JCModifiers mods = modifiersOpt();
2655: if (S.token() == CLASS || S.token() == INTERFACE
2656: || allowEnums && S.token() == ENUM) {
2657: return List
2658: .<JCTree> of(classOrInterfaceOrEnumDeclaration(
2659: mods, dc));
2660: } else if (S.token() == LBRACE
2661: && !isInterface
2662: && (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0
2663: && mods.annotations.isEmpty()) {
2664: return List.<JCTree> of(block(pos, mods.flags));
2665: } else {
2666: pos = S.pos();
2667: List<JCTypeParameter> typarams = typeParametersOpt();
2668: // Hack alert: if there are type arguments but no Modifiers, the start
2669: // position will be lost unless we set the Modifiers position. There
2670: // should be an AST node for type parameters (BugId 5005090).
2671: if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
2672: mods.pos = pos;
2673: }
2674: Token token = S.token();
2675: Name name = S.name();
2676: pos = S.pos();
2677: JCExpression type;
2678: boolean isVoid = S.token() == VOID;
2679: if (isVoid) {
2680: type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2681: S.nextToken();
2682: } else {
2683: type = type();
2684: }
2685: if (S.token() == LPAREN && !isInterface
2686: && type.getTag() == JCTree.IDENT) {
2687: if (isInterface || name != className)
2688: log
2689: .error(pos,
2690: "invalid.meth.decl.ret.type.req");
2691: return List.of(methodDeclaratorRest(pos, mods,
2692: null, names.init, typarams, isInterface,
2693: true, dc));
2694: } else {
2695: pos = S.pos();
2696: name = ident();
2697: if (S.token() == LPAREN) {
2698: return List.of(methodDeclaratorRest(pos, mods,
2699: type, name, typarams, isInterface,
2700: isVoid, dc));
2701: } else if (!isVoid && typarams.isEmpty()) {
2702: List<JCTree> defs = variableDeclaratorsRest(
2703: pos, mods, type, name, isInterface, dc,
2704: new ListBuffer<JCTree>()).toList();
2705: storeEnd(defs.last(), S.endPos());
2706: accept(SEMI);
2707: return defs;
2708: } else {
2709: pos = S.pos();
2710: List<JCTree> err = isVoid ? List
2711: .<JCTree> of(toP(F.at(pos).MethodDef(
2712: mods, name, type, typarams,
2713: List.<JCVariableDecl> nil(),
2714: List.<JCExpression> nil(),
2715: null, null))) : null;
2716: return List.<JCTree> of(syntaxError(S.pos(),
2717: err, "expected", keywords
2718: .token2string(LPAREN)));
2719: }
2720: }
2721: }
2722: }
2723: }
2724:
2725: /** MethodDeclaratorRest =
2726: * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2727: * VoidMethodDeclaratorRest =
2728: * FormalParameters [Throws TypeList] ( MethodBody | ";")
2729: * InterfaceMethodDeclaratorRest =
2730: * FormalParameters BracketsOpt [THROWS TypeList] ";"
2731: * VoidInterfaceMethodDeclaratorRest =
2732: * FormalParameters [THROWS TypeList] ";"
2733: * ConstructorDeclaratorRest =
2734: * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2735: */
2736: JCTree methodDeclaratorRest(int pos, JCModifiers mods,
2737: JCExpression type, Name name,
2738: List<JCTypeParameter> typarams, boolean isInterface,
2739: boolean isVoid, String dc) {
2740: List<JCVariableDecl> params = formalParameters();
2741: if (!isVoid)
2742: type = bracketsOpt(type);
2743: List<JCExpression> thrown = List.nil();
2744: if (S.token() == THROWS) {
2745: S.nextToken();
2746: thrown = qualidentList();
2747: }
2748: JCBlock body = null;
2749: JCExpression defaultValue;
2750: if (S.token() == LBRACE) {
2751: body = block();
2752: defaultValue = null;
2753: } else {
2754: if (S.token() == DEFAULT) {
2755: accept(DEFAULT);
2756: defaultValue = annotationValue();
2757: } else {
2758: defaultValue = null;
2759: }
2760: accept(SEMI);
2761: if (S.pos() <= errorEndPos) {
2762: // error recovery
2763: skip(false, true, false, false);
2764: if (S.token() == LBRACE) {
2765: body = block();
2766: }
2767: }
2768: }
2769: JCMethodDecl result = toP(F.at(pos).MethodDef(mods, name, type,
2770: typarams, params, thrown, body, defaultValue));
2771: attach(result, dc);
2772: return result;
2773: }
2774:
2775: /** QualidentList = Qualident {"," Qualident}
2776: */
2777: List<JCExpression> qualidentList() {
2778: ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2779: ts.append(qualident());
2780: while (S.token() == COMMA) {
2781: S.nextToken();
2782: ts.append(qualident());
2783: }
2784: return ts.toList();
2785: }
2786:
2787: /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2788: */
2789: List<JCTypeParameter> typeParametersOpt() {
2790: if (S.token() == LT) {
2791: checkGenerics();
2792: ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
2793: S.nextToken();
2794: typarams.append(typeParameter());
2795: while (S.token() == COMMA) {
2796: S.nextToken();
2797: typarams.append(typeParameter());
2798: }
2799: accept(GT);
2800: return typarams.toList();
2801: } else {
2802: return List.nil();
2803: }
2804: }
2805:
2806: /** TypeParameter = TypeVariable [TypeParameterBound]
2807: * TypeParameterBound = EXTENDS Type {"&" Type}
2808: * TypeVariable = Ident
2809: */
2810: JCTypeParameter typeParameter() {
2811: int pos = S.pos();
2812: Name name = ident();
2813: ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
2814: if (S.token() == EXTENDS) {
2815: S.nextToken();
2816: bounds.append(type());
2817: while (S.token() == AMP) {
2818: S.nextToken();
2819: bounds.append(type());
2820: }
2821: }
2822: return toP(F.at(pos).TypeParameter(name, bounds.toList()));
2823: }
2824:
2825: /** FormalParameters = "(" [ FormalParameterList ] ")"
2826: * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
2827: * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
2828: */
2829: List<JCVariableDecl> formalParameters() {
2830: ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
2831: JCVariableDecl lastParam = null;
2832: accept(LPAREN);
2833: if (S.token() != RPAREN) {
2834: params.append(lastParam = formalParameter());
2835: while ((lastParam.mods.flags & Flags.VARARGS) == 0
2836: && S.token() == COMMA) {
2837: S.nextToken();
2838: params.append(lastParam = formalParameter());
2839: }
2840: }
2841: accept(RPAREN);
2842: return params.toList();
2843: }
2844:
2845: JCModifiers optFinal(long flags) {
2846: JCModifiers mods = modifiersOpt();
2847: checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
2848: mods.flags |= flags;
2849: return mods;
2850: }
2851:
2852: /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
2853: * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
2854: */
2855: JCVariableDecl formalParameter() {
2856: JCModifiers mods = optFinal(Flags.PARAMETER);
2857: JCExpression type = type();
2858: if (S.token() == ELLIPSIS) {
2859: checkVarargs();
2860: mods.flags |= Flags.VARARGS;
2861: type = to(F.at(S.pos()).TypeArray(type));
2862: S.nextToken();
2863: }
2864: return variableDeclaratorId(mods, type);
2865: }
2866:
2867: /* ---------- auxiliary methods -------------- */
2868:
2869: /** Check that given tree is a legal expression statement.
2870: */
2871: protected JCExpression checkExprStat(JCExpression t) {
2872: switch (t.getTag()) {
2873: case JCTree.PREINC:
2874: case JCTree.PREDEC:
2875: case JCTree.POSTINC:
2876: case JCTree.POSTDEC:
2877: case JCTree.ASSIGN:
2878: case JCTree.BITOR_ASG:
2879: case JCTree.BITXOR_ASG:
2880: case JCTree.BITAND_ASG:
2881: case JCTree.SL_ASG:
2882: case JCTree.SR_ASG:
2883: case JCTree.USR_ASG:
2884: case JCTree.PLUS_ASG:
2885: case JCTree.MINUS_ASG:
2886: case JCTree.MUL_ASG:
2887: case JCTree.DIV_ASG:
2888: case JCTree.MOD_ASG:
2889: case JCTree.APPLY:
2890: case JCTree.NEWCLASS:
2891: case JCTree.ERRONEOUS:
2892: return t;
2893: default:
2894: log.error(t.pos, "not.stmt");
2895: return F.at(t.pos).Erroneous(List.<JCTree> of(t));
2896: }
2897: }
2898:
2899: /** Return precedence of operator represented by token,
2900: * -1 if token is not a binary operator. @see TreeInfo.opPrec
2901: */
2902: static int prec(Token token) {
2903: int oc = optag(token);
2904: return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
2905: }
2906:
2907: /** Return operation tag of binary operator represented by token,
2908: * -1 if token is not a binary operator.
2909: */
2910: static int optag(Token token) {
2911: switch (token) {
2912: case BARBAR:
2913: return JCTree.OR;
2914: case AMPAMP:
2915: return JCTree.AND;
2916: case BAR:
2917: return JCTree.BITOR;
2918: case BAREQ:
2919: return JCTree.BITOR_ASG;
2920: case CARET:
2921: return JCTree.BITXOR;
2922: case CARETEQ:
2923: return JCTree.BITXOR_ASG;
2924: case AMP:
2925: return JCTree.BITAND;
2926: case AMPEQ:
2927: return JCTree.BITAND_ASG;
2928: case EQEQ:
2929: return JCTree.EQ;
2930: case BANGEQ:
2931: return JCTree.NE;
2932: case LT:
2933: return JCTree.LT;
2934: case GT:
2935: return JCTree.GT;
2936: case LTEQ:
2937: return JCTree.LE;
2938: case GTEQ:
2939: return JCTree.GE;
2940: case LTLT:
2941: return JCTree.SL;
2942: case LTLTEQ:
2943: return JCTree.SL_ASG;
2944: case GTGT:
2945: return JCTree.SR;
2946: case GTGTEQ:
2947: return JCTree.SR_ASG;
2948: case GTGTGT:
2949: return JCTree.USR;
2950: case GTGTGTEQ:
2951: return JCTree.USR_ASG;
2952: case PLUS:
2953: return JCTree.PLUS;
2954: case PLUSEQ:
2955: return JCTree.PLUS_ASG;
2956: case SUB:
2957: return JCTree.MINUS;
2958: case SUBEQ:
2959: return JCTree.MINUS_ASG;
2960: case STAR:
2961: return JCTree.MUL;
2962: case STAREQ:
2963: return JCTree.MUL_ASG;
2964: case SLASH:
2965: return JCTree.DIV;
2966: case SLASHEQ:
2967: return JCTree.DIV_ASG;
2968: case PERCENT:
2969: return JCTree.MOD;
2970: case PERCENTEQ:
2971: return JCTree.MOD_ASG;
2972: case INSTANCEOF:
2973: return JCTree.TYPETEST;
2974: default:
2975: return -1;
2976: }
2977: }
2978:
2979: /** Return operation tag of unary operator represented by token,
2980: * -1 if token is not a binary operator.
2981: */
2982: static int unoptag(Token token) {
2983: switch (token) {
2984: case PLUS:
2985: return JCTree.POS;
2986: case SUB:
2987: return JCTree.NEG;
2988: case BANG:
2989: return JCTree.NOT;
2990: case TILDE:
2991: return JCTree.COMPL;
2992: case PLUSPLUS:
2993: return JCTree.PREINC;
2994: case SUBSUB:
2995: return JCTree.PREDEC;
2996: default:
2997: return -1;
2998: }
2999: }
3000:
3001: /** Return type tag of basic type represented by token,
3002: * -1 if token is not a basic type identifier.
3003: */
3004: static int typetag(Token token) {
3005: switch (token) {
3006: case BYTE:
3007: return TypeTags.BYTE;
3008: case CHAR:
3009: return TypeTags.CHAR;
3010: case SHORT:
3011: return TypeTags.SHORT;
3012: case INT:
3013: return TypeTags.INT;
3014: case LONG:
3015: return TypeTags.LONG;
3016: case FLOAT:
3017: return TypeTags.FLOAT;
3018: case DOUBLE:
3019: return TypeTags.DOUBLE;
3020: case BOOLEAN:
3021: return TypeTags.BOOLEAN;
3022: default:
3023: return -1;
3024: }
3025: }
3026:
3027: void checkGenerics() {
3028: if (!allowGenerics) {
3029: log.error(S.pos(), "generics.not.supported.in.source",
3030: source.name);
3031: allowGenerics = true;
3032: }
3033: }
3034:
3035: void checkVarargs() {
3036: if (!allowVarargs) {
3037: log.error(S.pos(), "varargs.not.supported.in.source",
3038: source.name);
3039: allowVarargs = true;
3040: }
3041: }
3042:
3043: void checkForeach() {
3044: if (!allowForeach) {
3045: log.error(S.pos(), "foreach.not.supported.in.source",
3046: source.name);
3047: allowForeach = true;
3048: }
3049: }
3050:
3051: void checkStaticImports() {
3052: if (!allowStaticImport) {
3053: log.error(S.pos(), "static.import.not.supported.in.source",
3054: source.name);
3055: allowStaticImport = true;
3056: }
3057: }
3058:
3059: void checkAnnotations() {
3060: if (!allowAnnotations) {
3061: log.error(S.pos(), "annotations.not.supported.in.source",
3062: source.name);
3063: allowAnnotations = true;
3064: }
3065: }
3066: }
|