0001: /*
0002: * Copyright 1994-2004 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 sun.tools.java;
0027:
0028: import sun.tools.tree.*;
0029: import java.io.IOException;
0030: import java.io.InputStream;
0031: import java.util.Enumeration;
0032: import java.util.Vector;
0033:
0034: /**
0035: * This class is used to parse Java statements and expressions.
0036: * The result is a parse tree.<p>
0037: *
0038: * This class implements an operator precedence parser. Errors are
0039: * reported to the Environment object, if the error can't be
0040: * resolved immediately, a SyntaxError exception is thrown.<p>
0041: *
0042: * Error recovery is implemented by catching SyntaxError exceptions
0043: * and discarding input tokens until an input token is reached that
0044: * is possibly a legal continuation.<p>
0045: *
0046: * The parse tree that is constructed represents the input
0047: * exactly (no rewrites to simpler forms). This is important
0048: * if the resulting tree is to be used for code formatting in
0049: * a programming environment. Currently only documentation comments
0050: * are retained.<p>
0051: *
0052: * The parsing algorithm does NOT use any type information. Changes
0053: * in the type system do not affect the structure of the parse tree.
0054: * This restriction does introduce an ambiguity an expression of the
0055: * form: (e1) e2 is assumed to be a cast if e2 does not start with
0056: * an operator. That means that (a) - b is interpreted as subtract
0057: * b from a and not cast negative b to type a. However, if a is a
0058: * simple type (byte, int, ...) then it is assumed to be a cast.<p>
0059: *
0060: * WARNING: The contents of this source file are not part of any
0061: * supported API. Code that depends on them does so at its own risk:
0062: * they are subject to change or removal without notice.
0063: *
0064: * @author Arthur van Hoff
0065: * @version 1.97, 05/05/07
0066: */
0067:
0068: public class Parser extends Scanner implements ParserActions, Constants {
0069: /**
0070: * Create a parser
0071: */
0072: protected Parser(Environment env, InputStream in)
0073: throws IOException {
0074: super (env, in);
0075: this .scanner = this ;
0076: this .actions = this ;
0077: }
0078:
0079: /**
0080: * Create a parser, given a scanner.
0081: */
0082: protected Parser(Scanner scanner) throws IOException {
0083: super (scanner.env);
0084: this .scanner = scanner;
0085: ((Scanner) this ).env = scanner.env;
0086: ((Scanner) this ).token = scanner.token;
0087: ((Scanner) this ).pos = scanner.pos;
0088: this .actions = this ;
0089: }
0090:
0091: /**
0092: * Create a parser, given a scanner and the semantic callback.
0093: */
0094: public Parser(Scanner scanner, ParserActions actions)
0095: throws IOException {
0096: this (scanner);
0097: this .actions = actions;
0098: }
0099:
0100: /**
0101: * Usually <code>this.actions == (ParserActions)this</code>.
0102: * However, a delegate scanner can produce tokens for this parser,
0103: * in which case <code>(Scanner)this</code> is unused,
0104: * except for <code>this.token</code> and <code>this.pos</code>
0105: * instance variables which are filled from the real scanner
0106: * by <code>this.scan()</code> and the constructor.
0107: */
0108: ParserActions actions;
0109:
0110: // Note: The duplication of methods allows pre-1.1 classes to
0111: // be binary compatible with the new version of the parser,
0112: // which now passes IdentifierTokens to the semantics phase,
0113: // rather than just Identifiers. This change is necessary,
0114: // since the parser is no longer responsible for managing the
0115: // resolution of type names. (That caused the "Vector" bug.)
0116: //
0117: // In a future release, the old "plain-Identifier" methods will
0118: // go away, and the corresponding "IdentifierToken" methods
0119: // may become abstract.
0120:
0121: /**
0122: * package declaration
0123: * @deprecated
0124: */
0125: @Deprecated
0126: public void packageDeclaration(long off, IdentifierToken nm) {
0127: // By default, call the deprecated version.
0128: // Any application must override one of the packageDeclaration methods.
0129: packageDeclaration(off, nm.id);
0130: }
0131:
0132: /**
0133: * @deprecated
0134: */
0135: @Deprecated
0136: protected void packageDeclaration(long off, Identifier nm) {
0137: throw new RuntimeException("beginClass method is abstract");
0138: }
0139:
0140: /**
0141: * import class
0142: * @deprecated
0143: */
0144: @Deprecated
0145: public void importClass(long off, IdentifierToken nm) {
0146: // By default, call the deprecated version.
0147: // Any application must override one of the packageDeclaration methods.
0148: importClass(off, nm.id);
0149: }
0150:
0151: /**
0152: * @deprecated Use the version with the IdentifierToken arguments.
0153: */
0154: @Deprecated
0155: protected void importClass(long off, Identifier nm) {
0156: throw new RuntimeException("importClass method is abstract");
0157: }
0158:
0159: /**
0160: * import package
0161: * @deprecated
0162: */
0163: @Deprecated
0164: public void importPackage(long off, IdentifierToken nm) {
0165: // By default, call the deprecated version.
0166: // Any application must override one of the importPackage methods.
0167: importPackage(off, nm.id);
0168: }
0169:
0170: /**
0171: * @deprecated Use the version with the IdentifierToken arguments.
0172: */
0173: @Deprecated
0174: protected void importPackage(long off, Identifier nm) {
0175: throw new RuntimeException("importPackage method is abstract");
0176: }
0177:
0178: /**
0179: * Define class
0180: * @deprecated
0181: */
0182: @Deprecated
0183: public ClassDefinition beginClass(long off, String doc, int mod,
0184: IdentifierToken nm, IdentifierToken sup,
0185: IdentifierToken impl[]) {
0186: // By default, call the deprecated version.
0187: // Any application must override one of the beginClass methods.
0188: Identifier supId = (sup == null) ? null : sup.id;
0189: Identifier implIds[] = null;
0190: if (impl != null) {
0191: implIds = new Identifier[impl.length];
0192: for (int i = 0; i < impl.length; i++) {
0193: implIds[i] = impl[i].id;
0194: }
0195: }
0196: beginClass(off, doc, mod, nm.id, supId, implIds);
0197: return getCurrentClass();
0198: }
0199:
0200: /**
0201: * @deprecated Use the version with the IdentifierToken arguments.
0202: */
0203: @Deprecated
0204: protected void beginClass(long off, String doc, int mod,
0205: Identifier nm, Identifier sup, Identifier impl[]) {
0206: throw new RuntimeException("beginClass method is abstract");
0207: }
0208:
0209: /**
0210: * Report the current class under construction.
0211: * By default, it's a no-op which returns null.
0212: * It may only be called before the corresponding endClass().
0213: */
0214: protected ClassDefinition getCurrentClass() {
0215: return null;
0216: }
0217:
0218: /**
0219: * End class
0220: * @deprecated
0221: */
0222: @Deprecated
0223: public void endClass(long off, ClassDefinition c) {
0224: // By default, call the deprecated version.
0225: // Any application must override one of the beginClass methods.
0226: endClass(off, c.getName().getFlatName().getName());
0227: }
0228:
0229: /**
0230: * @deprecated Use the version with the IdentifierToken arguments.
0231: */
0232: @Deprecated
0233: protected void endClass(long off, Identifier nm) {
0234: throw new RuntimeException("endClass method is abstract");
0235: }
0236:
0237: /**
0238: * Define a field
0239: * @deprecated
0240: */
0241: @Deprecated
0242: public void defineField(long where, ClassDefinition c, String doc,
0243: int mod, Type t, IdentifierToken nm,
0244: IdentifierToken args[], IdentifierToken exp[], Node val) {
0245: // By default, call the deprecated version.
0246: // Any application must override one of the defineField methods.
0247: Identifier argIds[] = null;
0248: Identifier expIds[] = null;
0249: if (args != null) {
0250: argIds = new Identifier[args.length];
0251: for (int i = 0; i < args.length; i++) {
0252: argIds[i] = args[i].id;
0253: }
0254: }
0255: if (exp != null) {
0256: expIds = new Identifier[exp.length];
0257: for (int i = 0; i < exp.length; i++) {
0258: expIds[i] = exp[i].id;
0259: }
0260: }
0261: defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
0262: }
0263:
0264: /**
0265: * @deprecated Use the version with the IdentifierToken arguments.
0266: */
0267: @Deprecated
0268: protected void defineField(long where, String doc, int mod, Type t,
0269: Identifier nm, Identifier args[], Identifier exp[], Node val) {
0270: throw new RuntimeException("defineField method is abstract");
0271: }
0272:
0273: /*
0274: * A growable array of nodes. It is used as a growable
0275: * buffer to hold argument lists and expression lists.
0276: * I'm not using Vector to make it more efficient.
0277: */
0278: private Node args[] = new Node[32];
0279: protected int argIndex = 0;
0280:
0281: protected final void addArgument(Node n) {
0282: if (argIndex == args.length) {
0283: Node newArgs[] = new Node[args.length * 2];
0284: System.arraycopy(args, 0, newArgs, 0, args.length);
0285: args = newArgs;
0286: }
0287: args[argIndex++] = n;
0288: }
0289:
0290: protected final Expression exprArgs(int index)[] {
0291: Expression e[] = new Expression[argIndex - index];
0292: System.arraycopy(args, index, e, 0, argIndex - index);
0293: argIndex = index;
0294: return e;
0295: }
0296:
0297: protected final Statement statArgs(int index)[] {
0298: Statement s[] = new Statement[argIndex - index];
0299: System.arraycopy(args, index, s, 0, argIndex - index);
0300: argIndex = index;
0301: return s;
0302: }
0303:
0304: /**
0305: * Expect a token, return its value, scan the next token or
0306: * throw an exception.
0307: */
0308: protected void expect(int t) throws SyntaxError, IOException {
0309: if (token != t) {
0310: switch (t) {
0311: case IDENT:
0312: env.error(scanner.prevPos, "identifier.expected");
0313: break;
0314: default:
0315: env
0316: .error(scanner.prevPos, "token.expected",
0317: opNames[t]);
0318: break;
0319: }
0320: throw new SyntaxError();
0321: }
0322: scan();
0323: }
0324:
0325: /**
0326: * Parse a type expression. Does not parse the []'s.
0327: */
0328: protected Expression parseTypeExpression() throws SyntaxError,
0329: IOException {
0330: switch (token) {
0331: case VOID:
0332: return new TypeExpression(scan(), Type.tVoid);
0333: case BOOLEAN:
0334: return new TypeExpression(scan(), Type.tBoolean);
0335: case BYTE:
0336: return new TypeExpression(scan(), Type.tByte);
0337: case CHAR:
0338: return new TypeExpression(scan(), Type.tChar);
0339: case SHORT:
0340: return new TypeExpression(scan(), Type.tShort);
0341: case INT:
0342: return new TypeExpression(scan(), Type.tInt);
0343: case LONG:
0344: return new TypeExpression(scan(), Type.tLong);
0345: case FLOAT:
0346: return new TypeExpression(scan(), Type.tFloat);
0347: case DOUBLE:
0348: return new TypeExpression(scan(), Type.tDouble);
0349: case IDENT:
0350: Expression e = new IdentifierExpression(pos,
0351: scanner.idValue);
0352: scan();
0353: while (token == FIELD) {
0354: e = new FieldExpression(scan(), e, scanner.idValue);
0355: expect(IDENT);
0356: }
0357: return e;
0358: }
0359:
0360: env.error(pos, "type.expected");
0361: throw new SyntaxError();
0362: }
0363:
0364: /**
0365: * Parse a method invocation. Should be called when the current
0366: * then is the '(' of the argument list.
0367: */
0368: protected Expression parseMethodExpression(Expression e,
0369: Identifier id) throws SyntaxError, IOException {
0370: long p = scan();
0371: int i = argIndex;
0372: if (token != RPAREN) {
0373: addArgument(parseExpression());
0374: while (token == COMMA) {
0375: scan();
0376: addArgument(parseExpression());
0377: }
0378: }
0379: expect(RPAREN);
0380: return new MethodExpression(p, e, id, exprArgs(i));
0381: }
0382:
0383: /**
0384: * Parse a new instance expression. Should be called when the current
0385: * token is the '(' of the argument list.
0386: */
0387: protected Expression parseNewInstanceExpression(long p,
0388: Expression outerArg, Expression type) throws SyntaxError,
0389: IOException {
0390: int i = argIndex;
0391: expect(LPAREN);
0392: if (token != RPAREN) {
0393: addArgument(parseExpression());
0394: while (token == COMMA) {
0395: scan();
0396: addArgument(parseExpression());
0397: }
0398: }
0399: expect(RPAREN);
0400: ClassDefinition body = null;
0401: if (token == LBRACE && !(type instanceof TypeExpression)) {
0402: long tp = pos;
0403: // x = new Type(arg) { subclass body ... }
0404: Identifier super Name = FieldExpression.toIdentifier(type);
0405: if (super Name == null) {
0406: env.error(type.getWhere(), "type.expected");
0407: }
0408: Vector ext = new Vector(1);
0409: Vector impl = new Vector(0);
0410: ext.addElement(new IdentifierToken(idNull));
0411: if (token == IMPLEMENTS || token == EXTENDS) {
0412: env.error(pos, "anonymous.extends");
0413: parseInheritance(ext, impl); // error recovery
0414: }
0415: body = parseClassBody(new IdentifierToken(tp, idNull),
0416: M_ANONYMOUS | M_LOCAL, EXPR, null, ext, impl, type
0417: .getWhere());
0418: }
0419: if (outerArg == null && body == null) {
0420: return new NewInstanceExpression(p, type, exprArgs(i));
0421: }
0422: return new NewInstanceExpression(p, type, exprArgs(i),
0423: outerArg, body);
0424: }
0425:
0426: /**
0427: * Parse a primary expression.
0428: */
0429: protected Expression parseTerm() throws SyntaxError, IOException {
0430: switch (token) {
0431: case CHARVAL: {
0432: char v = scanner.charValue;
0433: return new CharExpression(scan(), v);
0434: }
0435: case INTVAL: {
0436: int v = scanner.intValue;
0437: long q = scan();
0438: if (v < 0 && radix == 10)
0439: env.error(q, "overflow.int.dec");
0440: return new IntExpression(q, v);
0441: }
0442: case LONGVAL: {
0443: long v = scanner.longValue;
0444: long q = scan();
0445: if (v < 0 && radix == 10)
0446: env.error(q, "overflow.long.dec");
0447: return new LongExpression(q, v);
0448: }
0449: case FLOATVAL: {
0450: float v = scanner.floatValue;
0451: return new FloatExpression(scan(), v);
0452: }
0453: case DOUBLEVAL: {
0454: double v = scanner.doubleValue;
0455: return new DoubleExpression(scan(), v);
0456: }
0457: case STRINGVAL: {
0458: String v = scanner.stringValue;
0459: return new StringExpression(scan(), v);
0460: }
0461: case IDENT: {
0462: Identifier v = scanner.idValue;
0463: long p = scan();
0464: return (token == LPAREN) ? parseMethodExpression(null, v)
0465: : new IdentifierExpression(p, v);
0466: }
0467:
0468: case TRUE:
0469: return new BooleanExpression(scan(), true);
0470: case FALSE:
0471: return new BooleanExpression(scan(), false);
0472: case NULL:
0473: return new NullExpression(scan());
0474:
0475: case THIS: {
0476: Expression e = new ThisExpression(scan());
0477: return (token == LPAREN) ? parseMethodExpression(e, idInit)
0478: : e;
0479: }
0480: case SUPER: {
0481: Expression e = new SuperExpression(scan());
0482: return (token == LPAREN) ? parseMethodExpression(e, idInit)
0483: : e;
0484: }
0485:
0486: case VOID:
0487: case BOOLEAN:
0488: case BYTE:
0489: case CHAR:
0490: case SHORT:
0491: case INT:
0492: case LONG:
0493: case FLOAT:
0494: case DOUBLE:
0495: return parseTypeExpression();
0496:
0497: case ADD: {
0498: long p = scan();
0499: switch (token) {
0500: case INTVAL: {
0501: int v = scanner.intValue;
0502: long q = scan();
0503: if (v < 0 && radix == 10)
0504: env.error(q, "overflow.int.dec");
0505: return new IntExpression(q, v);
0506: }
0507: case LONGVAL: {
0508: long v = scanner.longValue;
0509: long q = scan();
0510: if (v < 0 && radix == 10)
0511: env.error(q, "overflow.long.dec");
0512: return new LongExpression(q, v);
0513: }
0514: case FLOATVAL: {
0515: float v = scanner.floatValue;
0516: return new FloatExpression(scan(), v);
0517: }
0518: case DOUBLEVAL: {
0519: double v = scanner.doubleValue;
0520: return new DoubleExpression(scan(), v);
0521: }
0522: }
0523: return new PositiveExpression(p, parseTerm());
0524: }
0525: case SUB: {
0526: long p = scan();
0527: switch (token) {
0528: case INTVAL: {
0529: int v = -scanner.intValue;
0530: return new IntExpression(scan(), v);
0531: }
0532: case LONGVAL: {
0533: long v = -scanner.longValue;
0534: return new LongExpression(scan(), v);
0535: }
0536: case FLOATVAL: {
0537: float v = -scanner.floatValue;
0538: return new FloatExpression(scan(), v);
0539: }
0540: case DOUBLEVAL: {
0541: double v = -scanner.doubleValue;
0542: return new DoubleExpression(scan(), v);
0543: }
0544: }
0545: return new NegativeExpression(p, parseTerm());
0546: }
0547: case NOT:
0548: return new NotExpression(scan(), parseTerm());
0549: case BITNOT:
0550: return new BitNotExpression(scan(), parseTerm());
0551: case INC:
0552: return new PreIncExpression(scan(), parseTerm());
0553: case DEC:
0554: return new PreDecExpression(scan(), parseTerm());
0555:
0556: case LPAREN: {
0557: // bracketed-expr: (expr)
0558: long p = scan();
0559: Expression e = parseExpression();
0560: expect(RPAREN);
0561:
0562: if (e.getOp() == TYPE) {
0563: // cast-expr: (simple-type) expr
0564: return new CastExpression(p, e, parseTerm());
0565: }
0566:
0567: switch (token) {
0568:
0569: // We handle INC and DEC specially.
0570: // See the discussion in JLS section 15.14.1.
0571: // (Part of fix for 4044502.)
0572:
0573: case INC:
0574: // We know this must be a postfix increment.
0575: return new PostIncExpression(scan(), e);
0576:
0577: case DEC:
0578: // We know this must be a postfix decrement.
0579: return new PostDecExpression(scan(), e);
0580:
0581: case LPAREN:
0582: case CHARVAL:
0583: case INTVAL:
0584: case LONGVAL:
0585: case FLOATVAL:
0586: case DOUBLEVAL:
0587: case STRINGVAL:
0588: case IDENT:
0589: case TRUE:
0590: case FALSE:
0591: case NOT:
0592: case BITNOT:
0593: case THIS:
0594: case SUPER:
0595: case NULL:
0596: case NEW:
0597: // cast-expr: (expr) expr
0598: return new CastExpression(p, e, parseTerm());
0599: }
0600: return new ExprExpression(p, e);
0601: }
0602:
0603: case LBRACE: {
0604: // array initializer: {expr1, expr2, ... exprn}
0605: long p = scan();
0606: int i = argIndex;
0607: if (token != RBRACE) {
0608: addArgument(parseExpression());
0609: while (token == COMMA) {
0610: scan();
0611: if (token == RBRACE) {
0612: break;
0613: }
0614: addArgument(parseExpression());
0615: }
0616: }
0617: expect(RBRACE);
0618: return new ArrayExpression(p, exprArgs(i));
0619: }
0620:
0621: case NEW: {
0622: long p = scan();
0623: int i = argIndex;
0624:
0625: if (token == LPAREN) {
0626: scan();
0627: Expression e = parseExpression();
0628: expect(RPAREN);
0629: env.error(p, "not.supported", "new(...)");
0630: return new NullExpression(p);
0631: }
0632:
0633: Expression e = parseTypeExpression();
0634:
0635: if (token == LSQBRACKET) {
0636: while (token == LSQBRACKET) {
0637: scan();
0638: addArgument((token != RSQBRACKET) ? parseExpression()
0639: : null);
0640: expect(RSQBRACKET);
0641: }
0642: Expression[] dims = exprArgs(i);
0643: if (token == LBRACE) {
0644: return new NewArrayExpression(p, e, dims,
0645: parseTerm());
0646: }
0647: return new NewArrayExpression(p, e, dims);
0648: } else {
0649: return parseNewInstanceExpression(p, null, e);
0650: }
0651: }
0652: }
0653:
0654: // System.err.println("NEAR: " + opNames[token]);
0655: env.error(scanner.prevPos, "missing.term");
0656: return new IntExpression(pos, 0);
0657: }
0658:
0659: /**
0660: * Parse an expression.
0661: */
0662: protected Expression parseExpression() throws SyntaxError,
0663: IOException {
0664: for (Expression e = parseTerm(); e != null; e = e.order()) {
0665: Expression more = parseBinaryExpression(e);
0666: if (more == null)
0667: return e;
0668: e = more;
0669: }
0670: // this return is bogus
0671: return null;
0672: }
0673:
0674: /**
0675: * Given a left-hand term, parse an operator and right-hand term.
0676: */
0677: protected Expression parseBinaryExpression(Expression e)
0678: throws SyntaxError, IOException {
0679: if (e != null) {
0680: switch (token) {
0681: case LSQBRACKET: {
0682: // index: expr1[expr2]
0683: long p = scan();
0684: Expression index = (token != RSQBRACKET) ? parseExpression()
0685: : null;
0686: expect(RSQBRACKET);
0687: e = new ArrayAccessExpression(p, e, index);
0688: break;
0689: }
0690:
0691: case INC:
0692: e = new PostIncExpression(scan(), e);
0693: break;
0694: case DEC:
0695: e = new PostDecExpression(scan(), e);
0696: break;
0697: case FIELD: {
0698: long p = scan();
0699: if (token == THIS) {
0700: // class C { class N { ... C.this ... } }
0701: // class C { class N { N(C c){ ... c.this() ... } } }
0702: long q = scan();
0703: if (token == LPAREN) {
0704: e = new ThisExpression(q, e);
0705: e = parseMethodExpression(e, idInit);
0706: } else {
0707: e = new FieldExpression(p, e, idThis);
0708: }
0709: break;
0710: }
0711: if (token == SUPER) {
0712: // class D extends C.N { D(C.N n) { n.super(); } }
0713: // Also, 'C.super', as in:
0714: // class C extends CS { class N { ... C.super.foo ... } }
0715: // class C extends CS { class N { ... C.super.foo() ... } }
0716: long q = scan();
0717: if (token == LPAREN) {
0718: e = new SuperExpression(q, e);
0719: e = parseMethodExpression(e, idInit);
0720: } else {
0721: // We must check elsewhere that this expression
0722: // does not stand alone, but qualifies a member name.
0723: e = new FieldExpression(p, e, idSuper);
0724: }
0725: break;
0726: }
0727: if (token == NEW) {
0728: // new C().new N()
0729: scan();
0730: if (token != IDENT)
0731: expect(IDENT);
0732: e = parseNewInstanceExpression(p, e,
0733: parseTypeExpression());
0734: break;
0735: }
0736: if (token == CLASS) {
0737: // just class literals, really
0738: // Class c = C.class;
0739: scan();
0740: e = new FieldExpression(p, e, idClass);
0741: break;
0742: }
0743: Identifier id = scanner.idValue;
0744: expect(IDENT);
0745: if (token == LPAREN) {
0746: e = parseMethodExpression(e, id);
0747: } else {
0748: e = new FieldExpression(p, e, id);
0749: }
0750: break;
0751: }
0752: case INSTANCEOF:
0753: e = new InstanceOfExpression(scan(), e, parseTerm());
0754: break;
0755: case ADD:
0756: e = new AddExpression(scan(), e, parseTerm());
0757: break;
0758: case SUB:
0759: e = new SubtractExpression(scan(), e, parseTerm());
0760: break;
0761: case MUL:
0762: e = new MultiplyExpression(scan(), e, parseTerm());
0763: break;
0764: case DIV:
0765: e = new DivideExpression(scan(), e, parseTerm());
0766: break;
0767: case REM:
0768: e = new RemainderExpression(scan(), e, parseTerm());
0769: break;
0770: case LSHIFT:
0771: e = new ShiftLeftExpression(scan(), e, parseTerm());
0772: break;
0773: case RSHIFT:
0774: e = new ShiftRightExpression(scan(), e, parseTerm());
0775: break;
0776: case URSHIFT:
0777: e = new UnsignedShiftRightExpression(scan(), e,
0778: parseTerm());
0779: break;
0780: case LT:
0781: e = new LessExpression(scan(), e, parseTerm());
0782: break;
0783: case LE:
0784: e = new LessOrEqualExpression(scan(), e, parseTerm());
0785: break;
0786: case GT:
0787: e = new GreaterExpression(scan(), e, parseTerm());
0788: break;
0789: case GE:
0790: e = new GreaterOrEqualExpression(scan(), e, parseTerm());
0791: break;
0792: case EQ:
0793: e = new EqualExpression(scan(), e, parseTerm());
0794: break;
0795: case NE:
0796: e = new NotEqualExpression(scan(), e, parseTerm());
0797: break;
0798: case BITAND:
0799: e = new BitAndExpression(scan(), e, parseTerm());
0800: break;
0801: case BITXOR:
0802: e = new BitXorExpression(scan(), e, parseTerm());
0803: break;
0804: case BITOR:
0805: e = new BitOrExpression(scan(), e, parseTerm());
0806: break;
0807: case AND:
0808: e = new AndExpression(scan(), e, parseTerm());
0809: break;
0810: case OR:
0811: e = new OrExpression(scan(), e, parseTerm());
0812: break;
0813: case ASSIGN:
0814: e = new AssignExpression(scan(), e, parseTerm());
0815: break;
0816: case ASGMUL:
0817: e = new AssignMultiplyExpression(scan(), e, parseTerm());
0818: break;
0819: case ASGDIV:
0820: e = new AssignDivideExpression(scan(), e, parseTerm());
0821: break;
0822: case ASGREM:
0823: e = new AssignRemainderExpression(scan(), e,
0824: parseTerm());
0825: break;
0826: case ASGADD:
0827: e = new AssignAddExpression(scan(), e, parseTerm());
0828: break;
0829: case ASGSUB:
0830: e = new AssignSubtractExpression(scan(), e, parseTerm());
0831: break;
0832: case ASGLSHIFT:
0833: e = new AssignShiftLeftExpression(scan(), e,
0834: parseTerm());
0835: break;
0836: case ASGRSHIFT:
0837: e = new AssignShiftRightExpression(scan(), e,
0838: parseTerm());
0839: break;
0840: case ASGURSHIFT:
0841: e = new AssignUnsignedShiftRightExpression(scan(), e,
0842: parseTerm());
0843: break;
0844: case ASGBITAND:
0845: e = new AssignBitAndExpression(scan(), e, parseTerm());
0846: break;
0847: case ASGBITOR:
0848: e = new AssignBitOrExpression(scan(), e, parseTerm());
0849: break;
0850: case ASGBITXOR:
0851: e = new AssignBitXorExpression(scan(), e, parseTerm());
0852: break;
0853: case QUESTIONMARK: {
0854: long p = scan();
0855: Expression second = parseExpression();
0856: expect(COLON);
0857: Expression third = parseExpression();
0858:
0859: // The grammar in the JLS does not allow assignment
0860: // expressions as the third part of a ?: expression.
0861: // Even though javac has no trouble parsing this,
0862: // check for this case and signal an error.
0863: // (fix for bug 4092958)
0864: if (third instanceof AssignExpression
0865: || third instanceof AssignOpExpression) {
0866: env.error(third.getWhere(),
0867: "assign.in.conditionalexpr");
0868: }
0869:
0870: e = new ConditionalExpression(p, e, second, third);
0871: break;
0872: }
0873:
0874: default:
0875: return null; // mark end of binary expressions
0876: }
0877: }
0878: return e; // return more binary expression stuff
0879: }
0880:
0881: /**
0882: * Recover after a syntax error in a statement. This involves
0883: * discarding tokens until EOF or a possible continuation is
0884: * encountered.
0885: */
0886: protected boolean recoverStatement() throws SyntaxError,
0887: IOException {
0888: while (true) {
0889: switch (token) {
0890: case EOF:
0891: case RBRACE:
0892: case LBRACE:
0893: case IF:
0894: case FOR:
0895: case WHILE:
0896: case DO:
0897: case TRY:
0898: case CATCH:
0899: case FINALLY:
0900: case BREAK:
0901: case CONTINUE:
0902: case RETURN:
0903: // begin of a statement, return
0904: return true;
0905:
0906: case VOID:
0907: case STATIC:
0908: case PUBLIC:
0909: case PRIVATE:
0910: case SYNCHRONIZED:
0911: case INTERFACE:
0912: case CLASS:
0913: case TRANSIENT:
0914: // begin of something outside a statement, panic some more
0915: expect(RBRACE);
0916: return false;
0917:
0918: case LPAREN:
0919: match(LPAREN, RPAREN);
0920: scan();
0921: break;
0922:
0923: case LSQBRACKET:
0924: match(LSQBRACKET, RSQBRACKET);
0925: scan();
0926: break;
0927:
0928: default:
0929: // don't know what to do, skip
0930: scan();
0931: break;
0932: }
0933: }
0934: }
0935:
0936: /**
0937: * Parse declaration, called after the type expression
0938: * has been parsed and the current token is IDENT.
0939: */
0940: protected Statement parseDeclaration(long p, int mod,
0941: Expression type) throws SyntaxError, IOException {
0942: int i = argIndex;
0943: if (token == IDENT) {
0944: addArgument(new VarDeclarationStatement(pos,
0945: parseExpression()));
0946: while (token == COMMA) {
0947: scan();
0948: addArgument(new VarDeclarationStatement(pos,
0949: parseExpression()));
0950: }
0951: }
0952: return new DeclarationStatement(p, mod, type, statArgs(i));
0953: }
0954:
0955: /**
0956: * Check if an expression is a legal toplevel expression.
0957: * Only method, inc, dec, and new expression are allowed.
0958: */
0959: protected void topLevelExpression(Expression e) {
0960: switch (e.getOp()) {
0961: case ASSIGN:
0962: case ASGMUL:
0963: case ASGDIV:
0964: case ASGREM:
0965: case ASGADD:
0966: case ASGSUB:
0967: case ASGLSHIFT:
0968: case ASGRSHIFT:
0969: case ASGURSHIFT:
0970: case ASGBITAND:
0971: case ASGBITOR:
0972: case ASGBITXOR:
0973: case PREINC:
0974: case PREDEC:
0975: case POSTINC:
0976: case POSTDEC:
0977: case METHOD:
0978: case NEWINSTANCE:
0979: return;
0980: }
0981: env.error(e.getWhere(), "invalid.expr");
0982: }
0983:
0984: /**
0985: * Parse a statement.
0986: */
0987: protected Statement parseStatement() throws SyntaxError,
0988: IOException {
0989: switch (token) {
0990: case SEMICOLON:
0991: return new CompoundStatement(scan(), new Statement[0]);
0992:
0993: case LBRACE:
0994: return parseBlockStatement();
0995:
0996: case IF: {
0997: // if-statement: if (expr) stat
0998: // if-statement: if (expr) stat else stat
0999: long p = scan();
1000:
1001: expect(LPAREN);
1002: Expression c = parseExpression();
1003: expect(RPAREN);
1004: Statement t = parseStatement();
1005: if (token == ELSE) {
1006: scan();
1007: return new IfStatement(p, c, t, parseStatement());
1008: } else {
1009: return new IfStatement(p, c, t, null);
1010: }
1011: }
1012:
1013: case ELSE: {
1014: // else-statement: else stat
1015: env.error(scan(), "else.without.if");
1016: return parseStatement();
1017: }
1018:
1019: case FOR: {
1020: // for-statement: for (decl-expr? ; expr? ; expr?) stat
1021: long p = scan();
1022: Statement init = null;
1023: Expression cond = null, inc = null;
1024:
1025: expect(LPAREN);
1026: if (token != SEMICOLON) {
1027: long p2 = pos;
1028: int mod = parseModifiers(M_FINAL);
1029: Expression e = parseExpression();
1030:
1031: if (token == IDENT) {
1032: init = parseDeclaration(p2, mod, e);
1033: } else {
1034: if (mod != 0) {
1035: expect(IDENT); // should have been a declaration
1036: }
1037: topLevelExpression(e);
1038: while (token == COMMA) {
1039: long p3 = scan();
1040: Expression e2 = parseExpression();
1041: topLevelExpression(e2);
1042: e = new CommaExpression(p3, e, e2);
1043: }
1044: init = new ExpressionStatement(p2, e);
1045: }
1046: }
1047: expect(SEMICOLON);
1048: if (token != SEMICOLON) {
1049: cond = parseExpression();
1050: }
1051: expect(SEMICOLON);
1052: if (token != RPAREN) {
1053: inc = parseExpression();
1054: topLevelExpression(inc);
1055: while (token == COMMA) {
1056: long p2 = scan();
1057: Expression e2 = parseExpression();
1058: topLevelExpression(e2);
1059: inc = new CommaExpression(p2, inc, e2);
1060: }
1061: }
1062: expect(RPAREN);
1063: return new ForStatement(p, init, cond, inc,
1064: parseStatement());
1065: }
1066:
1067: case WHILE: {
1068: // while-statement: while (expr) stat
1069: long p = scan();
1070:
1071: expect(LPAREN);
1072: Expression cond = parseExpression();
1073: expect(RPAREN);
1074: return new WhileStatement(p, cond, parseStatement());
1075: }
1076:
1077: case DO: {
1078: // do-statement: do stat while (expr)
1079: long p = scan();
1080:
1081: Statement body = parseStatement();
1082: expect(WHILE);
1083: expect(LPAREN);
1084: Expression cond = parseExpression();
1085: expect(RPAREN);
1086: expect(SEMICOLON);
1087: return new DoStatement(p, body, cond);
1088: }
1089:
1090: case BREAK: {
1091: // break-statement: break ;
1092: long p = scan();
1093: Identifier label = null;
1094:
1095: if (token == IDENT) {
1096: label = scanner.idValue;
1097: scan();
1098: }
1099: expect(SEMICOLON);
1100: return new BreakStatement(p, label);
1101: }
1102:
1103: case CONTINUE: {
1104: // continue-statement: continue ;
1105: long p = scan();
1106: Identifier label = null;
1107:
1108: if (token == IDENT) {
1109: label = scanner.idValue;
1110: scan();
1111: }
1112: expect(SEMICOLON);
1113: return new ContinueStatement(p, label);
1114: }
1115:
1116: case RETURN: {
1117: // return-statement: return ;
1118: // return-statement: return expr ;
1119: long p = scan();
1120: Expression e = null;
1121:
1122: if (token != SEMICOLON) {
1123: e = parseExpression();
1124: }
1125: expect(SEMICOLON);
1126: return new ReturnStatement(p, e);
1127: }
1128:
1129: case SWITCH: {
1130: // switch statement: switch ( expr ) stat
1131: long p = scan();
1132: int i = argIndex;
1133:
1134: expect(LPAREN);
1135: Expression e = parseExpression();
1136: expect(RPAREN);
1137: expect(LBRACE);
1138:
1139: while ((token != EOF) && (token != RBRACE)) {
1140: int j = argIndex;
1141: try {
1142: switch (token) {
1143: case CASE:
1144: // case-statement: case expr:
1145: addArgument(new CaseStatement(scan(),
1146: parseExpression()));
1147: expect(COLON);
1148: break;
1149:
1150: case DEFAULT:
1151: // default-statement: default:
1152: addArgument(new CaseStatement(scan(), null));
1153: expect(COLON);
1154: break;
1155:
1156: default:
1157: addArgument(parseStatement());
1158: break;
1159: }
1160: } catch (SyntaxError ee) {
1161: argIndex = j;
1162: if (!recoverStatement()) {
1163: throw ee;
1164: }
1165: }
1166: }
1167: expect(RBRACE);
1168: return new SwitchStatement(p, e, statArgs(i));
1169: }
1170:
1171: case CASE: {
1172: // case-statement: case expr : stat
1173: env.error(pos, "case.without.switch");
1174: while (token == CASE) {
1175: scan();
1176: parseExpression();
1177: expect(COLON);
1178: }
1179: return parseStatement();
1180: }
1181:
1182: case DEFAULT: {
1183: // default-statement: default : stat
1184: env.error(pos, "default.without.switch");
1185: scan();
1186: expect(COLON);
1187: return parseStatement();
1188: }
1189:
1190: case TRY: {
1191: // try-statement: try stat catch (type-expr ident) stat finally stat
1192: long p = scan();
1193: Statement init = null; // try-object specification
1194: int i = argIndex;
1195: boolean catches = false;
1196:
1197: if (false && token == LPAREN) {
1198: expect(LPAREN);
1199: long p2 = pos;
1200: int mod = parseModifiers(M_FINAL);
1201: Expression e = parseExpression();
1202:
1203: if (token == IDENT) {
1204: init = parseDeclaration(p2, mod, e);
1205: // leave check for try (T x, y) for semantic phase
1206: } else {
1207: if (mod != 0) {
1208: expect(IDENT); // should have been a declaration
1209: }
1210: init = new ExpressionStatement(p2, e);
1211: }
1212: expect(RPAREN);
1213: }
1214:
1215: Statement s = parseBlockStatement();
1216:
1217: if (init != null) {
1218: // s = new FinallyStatement(p, init, s, 0);
1219: }
1220:
1221: while (token == CATCH) {
1222: long pp = pos;
1223: expect(CATCH);
1224: expect(LPAREN);
1225: int mod = parseModifiers(M_FINAL);
1226: Expression t = parseExpression();
1227: IdentifierToken id = scanner.getIdToken();
1228: expect(IDENT);
1229: id.modifiers = mod;
1230: // We only catch Throwable's, so this is no longer required
1231: // while (token == LSQBRACKET) {
1232: // t = new ArrayAccessExpression(scan(), t, null);
1233: // expect(RSQBRACKET);
1234: // }
1235: expect(RPAREN);
1236: addArgument(new CatchStatement(pp, t, id,
1237: parseBlockStatement()));
1238: catches = true;
1239: }
1240:
1241: if (catches)
1242: s = new TryStatement(p, s, statArgs(i));
1243:
1244: if (token == FINALLY) {
1245: scan();
1246: return new FinallyStatement(p, s, parseBlockStatement());
1247: } else if (catches || init != null) {
1248: return s;
1249: } else {
1250: env.error(pos, "try.without.catch.finally");
1251: return new TryStatement(p, s, null);
1252: }
1253: }
1254:
1255: case CATCH: {
1256: // catch-statement: catch (expr ident) stat finally stat
1257: env.error(pos, "catch.without.try");
1258:
1259: Statement s;
1260: do {
1261: scan();
1262: expect(LPAREN);
1263: parseModifiers(M_FINAL);
1264: parseExpression();
1265: expect(IDENT);
1266: expect(RPAREN);
1267: s = parseBlockStatement();
1268: } while (token == CATCH);
1269:
1270: if (token == FINALLY) {
1271: scan();
1272: s = parseBlockStatement();
1273: }
1274: return s;
1275: }
1276:
1277: case FINALLY: {
1278: // finally-statement: finally stat
1279: env.error(pos, "finally.without.try");
1280: scan();
1281: return parseBlockStatement();
1282: }
1283:
1284: case THROW: {
1285: // throw-statement: throw expr;
1286: long p = scan();
1287: Expression e = parseExpression();
1288: expect(SEMICOLON);
1289: return new ThrowStatement(p, e);
1290: }
1291:
1292: case GOTO: {
1293: long p = scan();
1294: expect(IDENT);
1295: expect(SEMICOLON);
1296: env.error(p, "not.supported", "goto");
1297: return new CompoundStatement(p, new Statement[0]);
1298: }
1299:
1300: case SYNCHRONIZED: {
1301: // synchronized-statement: synchronized (expr) stat
1302: long p = scan();
1303: expect(LPAREN);
1304: Expression e = parseExpression();
1305: expect(RPAREN);
1306: return new SynchronizedStatement(p, e,
1307: parseBlockStatement());
1308: }
1309:
1310: case INTERFACE:
1311: case CLASS:
1312: // Inner class.
1313: return parseLocalClass(0);
1314:
1315: case CONST:
1316: case ABSTRACT:
1317: case FINAL:
1318: case STRICTFP: {
1319: // a declaration of some sort
1320: long p = pos;
1321:
1322: // A class which is local to a block is not a member, and so
1323: // cannot be public, private, protected, or static. It is in
1324: // effect private to the block, since it cannot be used outside
1325: // its scope.
1326: //
1327: // However, any class (if it has a name) can be declared final,
1328: // abstract, or strictfp.
1329: int mod = parseModifiers(M_FINAL | M_ABSTRACT | M_STRICTFP);
1330:
1331: switch (token) {
1332: case INTERFACE:
1333: case CLASS:
1334: return parseLocalClass(mod);
1335:
1336: case BOOLEAN:
1337: case BYTE:
1338: case CHAR:
1339: case SHORT:
1340: case INT:
1341: case LONG:
1342: case FLOAT:
1343: case DOUBLE:
1344: case IDENT: {
1345: if ((mod & (M_ABSTRACT | M_STRICTFP)) != 0) {
1346: mod &= ~(M_ABSTRACT | M_STRICTFP);
1347: expect(CLASS);
1348: }
1349: Expression e = parseExpression();
1350: if (token != IDENT) {
1351: expect(IDENT);
1352: }
1353: // declaration: final expr expr
1354: Statement s = parseDeclaration(p, mod, e);
1355: expect(SEMICOLON);
1356: return s;
1357: }
1358:
1359: default:
1360: env.error(pos, "type.expected");
1361: throw new SyntaxError();
1362: }
1363: }
1364:
1365: case VOID:
1366: case STATIC:
1367: case PUBLIC:
1368: case PRIVATE:
1369: case TRANSIENT:
1370: // This is the start of something outside a statement
1371: env.error(pos, "statement.expected");
1372: throw new SyntaxError();
1373: }
1374:
1375: long p = pos;
1376: Expression e = parseExpression();
1377:
1378: if (token == IDENT) {
1379: // declaration: expr expr
1380: Statement s = parseDeclaration(p, 0, e);
1381: expect(SEMICOLON);
1382: return s;
1383: }
1384: if (token == COLON) {
1385: // label: id: stat
1386: scan();
1387: Statement s = parseStatement();
1388: s.setLabel(env, e);
1389: return s;
1390: }
1391:
1392: // it was just an expression...
1393: topLevelExpression(e);
1394: expect(SEMICOLON);
1395: return new ExpressionStatement(p, e);
1396: }
1397:
1398: protected Statement parseBlockStatement() throws SyntaxError,
1399: IOException {
1400: // compound statement: { stat1 stat2 ... statn }
1401: if (token != LBRACE) {
1402: // We're expecting a block statement. But we'll probably do the
1403: // least damage if we try to parse a normal statement instead.
1404: env.error(scanner.prevPos, "token.expected",
1405: opNames[LBRACE]);
1406: return parseStatement();
1407: }
1408: long p = scan();
1409: int i = argIndex;
1410: while ((token != EOF) && (token != RBRACE)) {
1411: int j = argIndex;
1412: try {
1413: addArgument(parseStatement());
1414: } catch (SyntaxError e) {
1415: argIndex = j;
1416: if (!recoverStatement()) {
1417: throw e;
1418: }
1419: }
1420: }
1421:
1422: expect(RBRACE);
1423: return new CompoundStatement(p, statArgs(i));
1424: }
1425:
1426: /**
1427: * Parse an identifier. ie: a.b.c returns "a.b.c"
1428: * If star is true then "a.b.*" is allowed.
1429: * The return value encodes both the identifier and its location.
1430: */
1431: protected IdentifierToken parseName(boolean star)
1432: throws SyntaxError, IOException {
1433: IdentifierToken res = scanner.getIdToken();
1434: expect(IDENT);
1435:
1436: if (token != FIELD) {
1437: return res;
1438: }
1439:
1440: StringBuffer buf = new StringBuffer(res.id.toString());
1441:
1442: while (token == FIELD) {
1443: scan();
1444: if ((token == MUL) && star) {
1445: scan();
1446: buf.append(".*");
1447: break;
1448: }
1449:
1450: buf.append('.');
1451: if (token == IDENT) {
1452: buf.append(scanner.idValue);
1453: }
1454: expect(IDENT);
1455: }
1456:
1457: res.id = Identifier.lookup(buf.toString());
1458: return res;
1459: }
1460:
1461: /**
1462: * @deprecated
1463: * @see #parseName
1464: */
1465: @Deprecated
1466: protected Identifier parseIdentifier(boolean star)
1467: throws SyntaxError, IOException {
1468: return parseName(star).id;
1469: }
1470:
1471: /**
1472: * Parse a type expression, this results in a Type.
1473: * The parse includes trailing array brackets.
1474: */
1475: protected Type parseType() throws SyntaxError, IOException {
1476: Type t;
1477:
1478: switch (token) {
1479: case IDENT:
1480: t = Type.tClass(parseName(false).id);
1481: break;
1482: case VOID:
1483: scan();
1484: t = Type.tVoid;
1485: break;
1486: case BOOLEAN:
1487: scan();
1488: t = Type.tBoolean;
1489: break;
1490: case BYTE:
1491: scan();
1492: t = Type.tByte;
1493: break;
1494: case CHAR:
1495: scan();
1496: t = Type.tChar;
1497: break;
1498: case SHORT:
1499: scan();
1500: t = Type.tShort;
1501: break;
1502: case INT:
1503: scan();
1504: t = Type.tInt;
1505: break;
1506: case FLOAT:
1507: scan();
1508: t = Type.tFloat;
1509: break;
1510: case LONG:
1511: scan();
1512: t = Type.tLong;
1513: break;
1514: case DOUBLE:
1515: scan();
1516: t = Type.tDouble;
1517: break;
1518: default:
1519: env.error(pos, "type.expected");
1520: throw new SyntaxError();
1521: }
1522: return parseArrayBrackets(t);
1523: }
1524:
1525: /**
1526: * Parse the tail of a type expression, which might be array brackets.
1527: * Return the given type, as possibly modified by the suffix.
1528: */
1529: protected Type parseArrayBrackets(Type t) throws SyntaxError,
1530: IOException {
1531:
1532: // Parse []'s
1533: while (token == LSQBRACKET) {
1534: scan();
1535: if (token != RSQBRACKET) {
1536: env.error(pos, "array.dim.in.decl");
1537: parseExpression();
1538: }
1539: expect(RSQBRACKET);
1540: t = Type.tArray(t);
1541: }
1542: return t;
1543: }
1544:
1545: /*
1546: * Dealing with argument lists, I'm not using
1547: * Vector for efficiency.
1548: */
1549:
1550: private int aCount = 0;
1551: private Type aTypes[] = new Type[8];
1552: private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];
1553:
1554: private void addArgument(int mod, Type t, IdentifierToken nm) {
1555: nm.modifiers = mod;
1556: if (aCount >= aTypes.length) {
1557: Type newATypes[] = new Type[aCount * 2];
1558: System.arraycopy(aTypes, 0, newATypes, 0, aCount);
1559: aTypes = newATypes;
1560: IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
1561: System.arraycopy(aNames, 0, newANames, 0, aCount);
1562: aNames = newANames;
1563: }
1564: aTypes[aCount] = t;
1565: aNames[aCount++] = nm;
1566: }
1567:
1568: /**
1569: * Parse a possibly-empty sequence of modifier keywords.
1570: * Return the resulting bitmask.
1571: * Diagnose repeated modifiers, but make no other checks.
1572: * Only modifiers mentioned in the given bitmask are scanned;
1573: * an unmatched modifier must be handled by the caller.
1574: */
1575: protected int parseModifiers(int mask) throws IOException {
1576: int mod = 0;
1577: while (true) {
1578: if (token == CONST) {
1579: // const isn't in java, but handle a common C++ usage gently
1580: env.error(pos, "not.supported", "const");
1581: scan();
1582: }
1583: int nextmod = 0;
1584: switch (token) {
1585: case PRIVATE:
1586: nextmod = M_PRIVATE;
1587: break;
1588: case PUBLIC:
1589: nextmod = M_PUBLIC;
1590: break;
1591: case PROTECTED:
1592: nextmod = M_PROTECTED;
1593: break;
1594: case STATIC:
1595: nextmod = M_STATIC;
1596: break;
1597: case TRANSIENT:
1598: nextmod = M_TRANSIENT;
1599: break;
1600: case FINAL:
1601: nextmod = M_FINAL;
1602: break;
1603: case ABSTRACT:
1604: nextmod = M_ABSTRACT;
1605: break;
1606: case NATIVE:
1607: nextmod = M_NATIVE;
1608: break;
1609: case VOLATILE:
1610: nextmod = M_VOLATILE;
1611: break;
1612: case SYNCHRONIZED:
1613: nextmod = M_SYNCHRONIZED;
1614: break;
1615: case STRICTFP:
1616: nextmod = M_STRICTFP;
1617: break;
1618: }
1619: if ((nextmod & mask) == 0) {
1620: break;
1621: }
1622: if ((nextmod & mod) != 0) {
1623: env.error(pos, "repeated.modifier");
1624: }
1625: mod |= nextmod;
1626: scan();
1627: }
1628: return mod;
1629: }
1630:
1631: private ClassDefinition curClass;
1632:
1633: /**
1634: * Parse a field.
1635: */
1636: protected void parseField() throws SyntaxError, IOException {
1637:
1638: // Empty fields are not allowed by the JLS but are accepted by
1639: // the compiler, and much code has come to rely on this. It has
1640: // been decided that the language will be extended to legitimize them.
1641: if (token == SEMICOLON) {
1642: // empty field
1643: scan();
1644: return;
1645: }
1646:
1647: // Optional doc comment
1648: String doc = scanner.docComment;
1649:
1650: // The start of the field
1651: long p = pos;
1652:
1653: // Parse the modifiers
1654: int mod = parseModifiers(MM_FIELD | MM_METHOD);
1655:
1656: // Check for static initializer
1657: // ie: static { ... }
1658: // or an instance initializer (w/o the static).
1659: if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
1660: // static initializer
1661: actions.defineField(p, curClass, doc, mod, Type
1662: .tMethod(Type.tVoid), new IdentifierToken(
1663: idClassInit), null, null, parseStatement());
1664: return;
1665: }
1666:
1667: // Check for inner class
1668: if (token == CLASS || token == INTERFACE) {
1669: parseNamedClass(mod, CLASS, doc);
1670: return;
1671: }
1672:
1673: // Parse the type
1674: p = pos;
1675: Type t = parseType();
1676: IdentifierToken id = null;
1677:
1678: // Check that the type is followed by an Identifier
1679: // (the name of the method or the first variable),
1680: // otherwise it is a constructor.
1681: switch (token) {
1682: case IDENT:
1683: id = scanner.getIdToken();
1684: p = scan();
1685: break;
1686:
1687: case LPAREN:
1688: // It is a constructor
1689: id = new IdentifierToken(idInit);
1690: if ((mod & M_STRICTFP) != 0)
1691: env.error(pos, "bad.constructor.modifier");
1692: break;
1693:
1694: default:
1695: expect(IDENT);
1696: }
1697:
1698: // If the next token is a left-bracket then we
1699: // are dealing with a method or constructor, otherwise it is
1700: // a list of variables
1701: if (token == LPAREN) {
1702: // It is a method or constructor declaration
1703: scan();
1704: aCount = 0;
1705:
1706: if (token != RPAREN) {
1707: // Parse argument type and identifier
1708: // (arguments (like locals) are allowed to be final)
1709: int am = parseModifiers(M_FINAL);
1710: Type at = parseType();
1711: IdentifierToken an = scanner.getIdToken();
1712: expect(IDENT);
1713:
1714: // Parse optional array specifier, ie: a[][]
1715: at = parseArrayBrackets(at);
1716: addArgument(am, at, an);
1717:
1718: // If the next token is a comma then there are
1719: // more arguments
1720: while (token == COMMA) {
1721: // Parse argument type and identifier
1722: scan();
1723: am = parseModifiers(M_FINAL);
1724: at = parseType();
1725: an = scanner.getIdToken();
1726: expect(IDENT);
1727:
1728: // Parse optional array specifier, ie: a[][]
1729: at = parseArrayBrackets(at);
1730: addArgument(am, at, an);
1731: }
1732: }
1733: expect(RPAREN);
1734:
1735: // Parse optional array sepecifier, ie: foo()[][]
1736: t = parseArrayBrackets(t);
1737:
1738: // copy arguments
1739: Type atypes[] = new Type[aCount];
1740: System.arraycopy(aTypes, 0, atypes, 0, aCount);
1741:
1742: IdentifierToken anames[] = new IdentifierToken[aCount];
1743: System.arraycopy(aNames, 0, anames, 0, aCount);
1744:
1745: // Construct the type signature
1746: t = Type.tMethod(t, atypes);
1747:
1748: // Parse and ignore throws clause
1749: IdentifierToken exp[] = null;
1750: if (token == THROWS) {
1751: Vector v = new Vector();
1752: scan();
1753: v.addElement(parseName(false));
1754: while (token == COMMA) {
1755: scan();
1756: v.addElement(parseName(false));
1757: }
1758:
1759: exp = new IdentifierToken[v.size()];
1760: v.copyInto(exp);
1761: }
1762:
1763: // Check if it is a method definition or a method declaration
1764: // ie: foo() {...} or foo();
1765: switch (token) {
1766: case LBRACE: // It's a method definition
1767:
1768: // Set the state of FP strictness for the body of the method
1769: int oldFPstate = FPstate;
1770: if ((mod & M_STRICTFP) != 0) {
1771: FPstate = M_STRICTFP;
1772: } else {
1773: mod |= FPstate & M_STRICTFP;
1774: }
1775:
1776: actions.defineField(p, curClass, doc, mod, t, id,
1777: anames, exp, parseStatement());
1778:
1779: FPstate = oldFPstate;
1780:
1781: break;
1782:
1783: case SEMICOLON:
1784: scan();
1785: actions.defineField(p, curClass, doc, mod, t, id,
1786: anames, exp, null);
1787: break;
1788:
1789: default:
1790: // really expected a statement body here
1791: if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
1792: expect(LBRACE);
1793: } else {
1794: expect(SEMICOLON);
1795: }
1796: }
1797: return;
1798: }
1799:
1800: // It is a list of instance variables
1801: while (true) {
1802: p = pos; // get the current position
1803: // parse the array brackets (if any)
1804: // ie: var[][][]
1805: Type vt = parseArrayBrackets(t);
1806:
1807: // Parse the optional initializer
1808: Node init = null;
1809: if (token == ASSIGN) {
1810: scan();
1811: init = parseExpression();
1812: }
1813:
1814: // Define the variable
1815: actions.defineField(p, curClass, doc, mod, vt, id, null,
1816: null, init);
1817:
1818: // If the next token is a comma, then there is more
1819: if (token != COMMA) {
1820: expect(SEMICOLON);
1821: return;
1822: }
1823: scan();
1824:
1825: // The next token must be an identifier
1826: id = scanner.getIdToken();
1827: expect(IDENT);
1828: }
1829: }
1830:
1831: /**
1832: * Recover after a syntax error in a field. This involves
1833: * discarding tokens until an EOF or a possible legal
1834: * continuation is encountered.
1835: */
1836: protected void recoverField(ClassDefinition newClass)
1837: throws SyntaxError, IOException {
1838: while (true) {
1839: switch (token) {
1840: case EOF:
1841: case STATIC:
1842: case FINAL:
1843: case PUBLIC:
1844: case PRIVATE:
1845: case SYNCHRONIZED:
1846: case TRANSIENT:
1847:
1848: case VOID:
1849: case BOOLEAN:
1850: case BYTE:
1851: case CHAR:
1852: case SHORT:
1853: case INT:
1854: case FLOAT:
1855: case LONG:
1856: case DOUBLE:
1857: // possible begin of a field, continue
1858: return;
1859:
1860: case LBRACE:
1861: match(LBRACE, RBRACE);
1862: scan();
1863: break;
1864:
1865: case LPAREN:
1866: match(LPAREN, RPAREN);
1867: scan();
1868: break;
1869:
1870: case LSQBRACKET:
1871: match(LSQBRACKET, RSQBRACKET);
1872: scan();
1873: break;
1874:
1875: case RBRACE:
1876: case INTERFACE:
1877: case CLASS:
1878: case IMPORT:
1879: case PACKAGE:
1880: // begin of something outside a class, panic more
1881: actions.endClass(pos, newClass);
1882: throw new SyntaxError();
1883:
1884: default:
1885: // don't know what to do, skip
1886: scan();
1887: break;
1888: }
1889: }
1890: }
1891:
1892: /**
1893: * Parse a top-level class or interface declaration.
1894: */
1895: protected void parseClass() throws SyntaxError, IOException {
1896: String doc = scanner.docComment;
1897:
1898: // Parse the modifiers.
1899: int mod = parseModifiers(MM_CLASS | MM_MEMBER);
1900:
1901: parseNamedClass(mod, PACKAGE, doc);
1902: }
1903:
1904: // Current strict/default state of floating point. This is
1905: // set and reset with a stack discipline around methods and named
1906: // classes. Only M_STRICTFP may be set in this word. try...
1907: // finally is not needed to protect setting and resetting because
1908: // there are no error messages based on FPstate.
1909: private int FPstate = 0;
1910:
1911: /**
1912: * Parse a block-local class or interface declaration.
1913: */
1914: protected Statement parseLocalClass(int mod) throws SyntaxError,
1915: IOException {
1916: long p = pos;
1917: ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT,
1918: null);
1919: Statement ds[] = { new VarDeclarationStatement(p,
1920: new LocalMember(body), null) };
1921: Expression type = new TypeExpression(p, body.getType());
1922: return new DeclarationStatement(p, 0, type, ds);
1923: }
1924:
1925: /**
1926: * Parse a named class or interface declaration,
1927: * starting at "class" or "interface".
1928: * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
1929: */
1930: protected ClassDefinition parseNamedClass(int mod, int ctx,
1931: String doc) throws SyntaxError, IOException {
1932: // Parse class/interface
1933: switch (token) {
1934: case INTERFACE:
1935: scan();
1936: mod |= M_INTERFACE;
1937: break;
1938:
1939: case CLASS:
1940: scan();
1941: break;
1942:
1943: default:
1944: env.error(pos, "class.expected");
1945: break;
1946: }
1947:
1948: int oldFPstate = FPstate;
1949: if ((mod & M_STRICTFP) != 0) {
1950: FPstate = M_STRICTFP;
1951: } else {
1952: // The & (...) isn't really necessary here because we do maintain
1953: // the invariant that FPstate has no extra bits set.
1954: mod |= FPstate & M_STRICTFP;
1955: }
1956:
1957: // Parse the class name
1958: IdentifierToken nm = scanner.getIdToken();
1959: long p = pos;
1960: expect(IDENT);
1961:
1962: Vector ext = new Vector();
1963: Vector impl = new Vector();
1964: parseInheritance(ext, impl);
1965:
1966: ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext,
1967: impl, p);
1968:
1969: FPstate = oldFPstate;
1970:
1971: return tmp;
1972: }
1973:
1974: protected void parseInheritance(Vector ext, Vector impl)
1975: throws SyntaxError, IOException {
1976: // Parse extends clause
1977: if (token == EXTENDS) {
1978: scan();
1979: ext.addElement(parseName(false));
1980: while (token == COMMA) {
1981: scan();
1982: ext.addElement(parseName(false));
1983: }
1984: }
1985:
1986: // Parse implements clause
1987: if (token == IMPLEMENTS) {
1988: scan();
1989: impl.addElement(parseName(false));
1990: while (token == COMMA) {
1991: scan();
1992: impl.addElement(parseName(false));
1993: }
1994: }
1995: }
1996:
1997: /**
1998: * Parse the body of a class or interface declaration,
1999: * starting at the left brace.
2000: */
2001: protected ClassDefinition parseClassBody(IdentifierToken nm,
2002: int mod, int ctx, String doc, Vector ext, Vector impl,
2003: long p) throws SyntaxError, IOException {
2004: // Decide which is the super class
2005: IdentifierToken sup = null;
2006: if ((mod & M_INTERFACE) != 0) {
2007: if (impl.size() > 0) {
2008: env.error(((IdentifierToken) impl.elementAt(0))
2009: .getWhere(), "intf.impl.intf");
2010: }
2011: impl = ext;
2012: } else {
2013: if (ext.size() > 0) {
2014: if (ext.size() > 1) {
2015: env.error(((IdentifierToken) ext.elementAt(1))
2016: .getWhere(), "multiple.inherit");
2017: }
2018: sup = (IdentifierToken) ext.elementAt(0);
2019: }
2020: }
2021:
2022: ClassDefinition oldClass = curClass;
2023:
2024: // Begin a new class
2025: IdentifierToken implids[] = new IdentifierToken[impl.size()];
2026: impl.copyInto(implids);
2027: ClassDefinition newClass = actions.beginClass(p, doc, mod, nm,
2028: sup, implids);
2029:
2030: // Parse fields
2031: expect(LBRACE);
2032: while ((token != EOF) && (token != RBRACE)) {
2033: try {
2034: curClass = newClass;
2035: parseField();
2036: } catch (SyntaxError e) {
2037: recoverField(newClass);
2038: } finally {
2039: curClass = oldClass;
2040: }
2041: }
2042: expect(RBRACE);
2043:
2044: // End the class
2045: actions.endClass(scanner.prevPos, newClass);
2046: return newClass;
2047: }
2048:
2049: /**
2050: * Recover after a syntax error in the file.
2051: * This involves discarding tokens until an EOF
2052: * or a possible legal continuation is encountered.
2053: */
2054: protected void recoverFile() throws IOException {
2055: while (true) {
2056: switch (token) {
2057: case CLASS:
2058: case INTERFACE:
2059: // Start of a new source file statement, continue
2060: return;
2061:
2062: case LBRACE:
2063: match(LBRACE, RBRACE);
2064: scan();
2065: break;
2066:
2067: case LPAREN:
2068: match(LPAREN, RPAREN);
2069: scan();
2070: break;
2071:
2072: case LSQBRACKET:
2073: match(LSQBRACKET, RSQBRACKET);
2074: scan();
2075: break;
2076:
2077: case EOF:
2078: return;
2079:
2080: default:
2081: // Don't know what to do, skip
2082: scan();
2083: break;
2084: }
2085: }
2086: }
2087:
2088: /**
2089: * Parse an Java file.
2090: */
2091: public void parseFile() {
2092: try {
2093: try {
2094: if (token == PACKAGE) {
2095: // Package statement
2096: long p = scan();
2097: IdentifierToken id = parseName(false);
2098: expect(SEMICOLON);
2099: actions.packageDeclaration(p, id);
2100: }
2101: } catch (SyntaxError e) {
2102: recoverFile();
2103: }
2104: while (token == IMPORT) {
2105: try {
2106: // Import statement
2107: long p = scan();
2108: IdentifierToken id = parseName(true);
2109: expect(SEMICOLON);
2110: if (id.id.getName().equals(idStar)) {
2111: id.id = id.id.getQualifier();
2112: actions.importPackage(p, id);
2113: } else {
2114: actions.importClass(p, id);
2115: }
2116: } catch (SyntaxError e) {
2117: recoverFile();
2118: }
2119: }
2120:
2121: while (token != EOF) {
2122: try {
2123: switch (token) {
2124: case FINAL:
2125: case PUBLIC:
2126: case PRIVATE:
2127: case ABSTRACT:
2128: case CLASS:
2129: case INTERFACE:
2130: case STRICTFP:
2131: // Start of a class
2132: parseClass();
2133: break;
2134:
2135: case SEMICOLON:
2136: // Bogus semicolon.
2137: // According to the JLS (7.6,19.6), a TypeDeclaration
2138: // may consist of a single semicolon, however, this
2139: // usage is discouraged (JLS 7.6). In contrast,
2140: // a FieldDeclaration may not be empty, and is flagged
2141: // as an error. See parseField above.
2142: scan();
2143: break;
2144:
2145: case EOF:
2146: // The end
2147: return;
2148:
2149: default:
2150: // Oops
2151: env.error(pos, "toplevel.expected");
2152: throw new SyntaxError();
2153: }
2154: } catch (SyntaxError e) {
2155: recoverFile();
2156: }
2157: }
2158: } catch (IOException e) {
2159: env.error(pos, "io.exception", env.getSource());
2160: return;
2161: }
2162: }
2163:
2164: /**
2165: * Usually <code>this.scanner == (Scanner)this</code>.
2166: * However, a delegate scanner can produce tokens for this parser,
2167: * in which case <code>(Scanner)this</code> is unused,
2168: * except for <code>this.token</code> and <code>this.pos</code>
2169: * instance variables which are filled from the real scanner
2170: * by <code>this.scan()</code> and the constructor.
2171: */
2172: protected Scanner scanner;
2173:
2174: // Design Note: We ought to disinherit Parser from Scanner.
2175: // We also should split out the interface ParserActions from
2176: // Parser, and make BatchParser implement ParserActions,
2177: // not extend Parser. This would split scanning, parsing,
2178: // and class building into distinct responsibility areas.
2179: // (Perhaps tree building could be virtualized too.)
2180:
2181: public long scan() throws IOException {
2182: if (scanner != this && scanner != null) {
2183: long result = scanner.scan();
2184: ((Scanner) this ).token = scanner.token;
2185: ((Scanner) this ).pos = scanner.pos;
2186: return result;
2187: }
2188: return super .scan();
2189: }
2190:
2191: public void match(int open, int close) throws IOException {
2192: if (scanner != this ) {
2193: scanner.match(open, close);
2194: ((Scanner) this ).token = scanner.token;
2195: ((Scanner) this).pos = scanner.pos;
2196: return;
2197: }
2198: super.match(open, close);
2199: }
2200: }
|