0001: /*
0002: * Javassist, a Java-bytecode translator toolkit.
0003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
0004: *
0005: * The contents of this file are subject to the Mozilla Public License Version
0006: * 1.1 (the "License"); you may not use this file except in compliance with
0007: * the License. Alternatively, the contents of this file may be used under
0008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
0009: *
0010: * Software distributed under the License is distributed on an "AS IS" basis,
0011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0012: * for the specific language governing rights and limitations under the
0013: * License.
0014: */
0015:
0016: package javassist.compiler;
0017:
0018: import javassist.compiler.ast.*;
0019:
0020: public final class Parser implements TokenId {
0021: private Lex lex;
0022:
0023: public Parser(Lex lex) {
0024: this .lex = lex;
0025: }
0026:
0027: public boolean hasMore() {
0028: return lex.lookAhead() >= 0;
0029: }
0030:
0031: /* member.declaration
0032: * : method.declaration | field.declaration
0033: */
0034: public ASTList parseMember(SymbolTable tbl) throws CompileError {
0035: ASTList mem = parseMember1(tbl);
0036: if (mem instanceof MethodDecl)
0037: return parseMethod2(tbl, (MethodDecl) mem);
0038: else
0039: return mem;
0040: }
0041:
0042: /* A method body is not parsed.
0043: */
0044: public ASTList parseMember1(SymbolTable tbl) throws CompileError {
0045: ASTList mods = parseMemberMods();
0046: Declarator d;
0047: boolean isConstructor = false;
0048: if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') {
0049: d = new Declarator(VOID, 0);
0050: isConstructor = true;
0051: } else
0052: d = parseFormalType(tbl);
0053:
0054: if (lex.get() != Identifier)
0055: throw new SyntaxError(lex);
0056:
0057: String name;
0058: if (isConstructor)
0059: name = MethodDecl.initName;
0060: else
0061: name = lex.getString();
0062:
0063: d.setVariable(new Symbol(name));
0064: if (isConstructor || lex.lookAhead() == '(')
0065: return parseMethod1(tbl, isConstructor, mods, d);
0066: else
0067: return parseField(tbl, mods, d);
0068: }
0069:
0070: /* field.declaration
0071: * : member.modifiers
0072: * formal.type Identifier
0073: * [ "=" expression ] ";"
0074: */
0075: private FieldDecl parseField(SymbolTable tbl, ASTList mods,
0076: Declarator d) throws CompileError {
0077: ASTree expr = null;
0078: if (lex.lookAhead() == '=') {
0079: lex.get();
0080: expr = parseExpression(tbl);
0081: }
0082:
0083: int c = lex.get();
0084: if (c == ';')
0085: return new FieldDecl(mods,
0086: new ASTList(d, new ASTList(expr)));
0087: else if (c == ',')
0088: throw new CompileError(
0089: "only one field can be declared in one declaration",
0090: lex);
0091: else
0092: throw new SyntaxError(lex);
0093: }
0094:
0095: /* method.declaration
0096: * : member.modifiers
0097: * [ formal.type ]
0098: * Identifier "(" [ formal.parameter ( "," formal.parameter )* ] ")"
0099: * array.dimension
0100: * [ THROWS class.type ( "," class.type ) ]
0101: * ( block.statement | ";" )
0102: *
0103: * Note that a method body is not parsed.
0104: */
0105: private MethodDecl parseMethod1(SymbolTable tbl,
0106: boolean isConstructor, ASTList mods, Declarator d)
0107: throws CompileError {
0108: if (lex.get() != '(')
0109: throw new SyntaxError(lex);
0110:
0111: ASTList parms = null;
0112: if (lex.lookAhead() != ')')
0113: while (true) {
0114: parms = ASTList.append(parms, parseFormalParam(tbl));
0115: int t = lex.lookAhead();
0116: if (t == ',')
0117: lex.get();
0118: else if (t == ')')
0119: break;
0120: }
0121:
0122: lex.get(); // ')'
0123: d.addArrayDim(parseArrayDimension());
0124: if (isConstructor && d.getArrayDim() > 0)
0125: throw new SyntaxError(lex);
0126:
0127: ASTList throwsList = null;
0128: if (lex.lookAhead() == THROWS) {
0129: lex.get();
0130: while (true) {
0131: throwsList = ASTList.append(throwsList,
0132: parseClassType(tbl));
0133: if (lex.lookAhead() == ',')
0134: lex.get();
0135: else
0136: break;
0137: }
0138: }
0139:
0140: return new MethodDecl(mods, new ASTList(d, ASTList.make(parms,
0141: throwsList, null)));
0142: }
0143:
0144: /* Parses a method body.
0145: */
0146: public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md)
0147: throws CompileError {
0148: Stmnt body = null;
0149: if (lex.lookAhead() == ';')
0150: lex.get();
0151: else {
0152: body = parseBlock(tbl);
0153: if (body == null)
0154: body = new Stmnt(BLOCK);
0155: }
0156:
0157: md.sublist(4).setHead(body);
0158: return md;
0159: }
0160:
0161: /* member.modifiers
0162: * : ( FINAL | SYNCHRONIZED | ABSTRACT
0163: * | PUBLIC | PROTECTED | PRIVATE | STATIC
0164: * | VOLATILE | TRANSIENT | STRICT )*
0165: */
0166: private ASTList parseMemberMods() {
0167: int t;
0168: ASTList list = null;
0169: while (true) {
0170: t = lex.lookAhead();
0171: if (t == ABSTRACT || t == FINAL || t == PUBLIC
0172: || t == PROTECTED || t == PRIVATE
0173: || t == SYNCHRONIZED || t == STATIC
0174: || t == VOLATILE || t == TRANSIENT || t == STRICT)
0175: list = new ASTList(new Keyword(lex.get()), list);
0176: else
0177: break;
0178: }
0179:
0180: return list;
0181: }
0182:
0183: /* formal.type : ( build-in-type | class.type ) array.dimension
0184: */
0185: private Declarator parseFormalType(SymbolTable tbl)
0186: throws CompileError {
0187: int t = lex.lookAhead();
0188: if (isBuiltinType(t) || t == VOID) {
0189: lex.get(); // primitive type
0190: int dim = parseArrayDimension();
0191: return new Declarator(t, dim);
0192: } else {
0193: ASTList name = parseClassType(tbl);
0194: int dim = parseArrayDimension();
0195: return new Declarator(name, dim);
0196: }
0197: }
0198:
0199: private static boolean isBuiltinType(int t) {
0200: return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT
0201: || t == INT || t == LONG || t == FLOAT || t == DOUBLE);
0202: }
0203:
0204: /* formal.parameter : formal.type Identifier array.dimension
0205: */
0206: private Declarator parseFormalParam(SymbolTable tbl)
0207: throws CompileError {
0208: Declarator d = parseFormalType(tbl);
0209: if (lex.get() != Identifier)
0210: throw new SyntaxError(lex);
0211:
0212: String name = lex.getString();
0213: d.setVariable(new Symbol(name));
0214: d.addArrayDim(parseArrayDimension());
0215: tbl.append(name, d);
0216: return d;
0217: }
0218:
0219: /* statement : [ label ":" ]* labeled.statement
0220: *
0221: * labeled.statement
0222: * : block.statement
0223: * | if.statement
0224: * | while.statement
0225: * | do.statement
0226: * | for.statement
0227: * | switch.statement
0228: * | try.statement
0229: * | return.statement
0230: * | thorw.statement
0231: * | break.statement
0232: * | continue.statement
0233: * | declaration.or.expression
0234: * | ";"
0235: *
0236: * This method may return null (empty statement).
0237: */
0238: public Stmnt parseStatement(SymbolTable tbl) throws CompileError {
0239: int t = lex.lookAhead();
0240: if (t == '{')
0241: return parseBlock(tbl);
0242: else if (t == ';') {
0243: lex.get();
0244: return new Stmnt(BLOCK); // empty statement
0245: } else if (t == Identifier && lex.lookAhead(1) == ':') {
0246: lex.get(); // Identifier
0247: String label = lex.getString();
0248: lex.get(); // ':'
0249: return Stmnt.make(LABEL, new Symbol(label),
0250: parseStatement(tbl));
0251: } else if (t == IF)
0252: return parseIf(tbl);
0253: else if (t == WHILE)
0254: return parseWhile(tbl);
0255: else if (t == DO)
0256: return parseDo(tbl);
0257: else if (t == FOR)
0258: return parseFor(tbl);
0259: else if (t == TRY)
0260: return parseTry(tbl);
0261: else if (t == SWITCH)
0262: return parseSwitch(tbl);
0263: else if (t == SYNCHRONIZED)
0264: return parseSynchronized(tbl);
0265: else if (t == RETURN)
0266: return parseReturn(tbl);
0267: else if (t == THROW)
0268: return parseThrow(tbl);
0269: else if (t == BREAK)
0270: return parseBreak(tbl);
0271: else if (t == CONTINUE)
0272: return parseContinue(tbl);
0273: else
0274: return parseDeclarationOrExpression(tbl, false);
0275: }
0276:
0277: /* block.statement : "{" statement* "}"
0278: */
0279: private Stmnt parseBlock(SymbolTable tbl) throws CompileError {
0280: if (lex.get() != '{')
0281: throw new SyntaxError(lex);
0282:
0283: Stmnt body = null;
0284: SymbolTable tbl2 = new SymbolTable(tbl);
0285: while (lex.lookAhead() != '}') {
0286: Stmnt s = parseStatement(tbl2);
0287: if (s != null)
0288: body = (Stmnt) ASTList
0289: .concat(body, new Stmnt(BLOCK, s));
0290: }
0291:
0292: lex.get(); // '}'
0293: if (body == null)
0294: return new Stmnt(BLOCK); // empty block
0295: else
0296: return body;
0297: }
0298:
0299: /* if.statement : IF "(" expression ")" statement
0300: * [ ELSE statement ]
0301: */
0302: private Stmnt parseIf(SymbolTable tbl) throws CompileError {
0303: int t = lex.get(); // IF
0304: ASTree expr = parseParExpression(tbl);
0305: Stmnt thenp = parseStatement(tbl);
0306: Stmnt elsep;
0307: if (lex.lookAhead() == ELSE) {
0308: lex.get();
0309: elsep = parseStatement(tbl);
0310: } else
0311: elsep = null;
0312:
0313: return new Stmnt(t, expr,
0314: new ASTList(thenp, new ASTList(elsep)));
0315: }
0316:
0317: /* while.statement : WHILE "(" expression ")" statement
0318: */
0319: private Stmnt parseWhile(SymbolTable tbl) throws CompileError {
0320: int t = lex.get(); // WHILE
0321: ASTree expr = parseParExpression(tbl);
0322: Stmnt body = parseStatement(tbl);
0323: return new Stmnt(t, expr, body);
0324: }
0325:
0326: /* do.statement : DO statement WHILE "(" expression ")" ";"
0327: */
0328: private Stmnt parseDo(SymbolTable tbl) throws CompileError {
0329: int t = lex.get(); // DO
0330: Stmnt body = parseStatement(tbl);
0331: if (lex.get() != WHILE || lex.get() != '(')
0332: throw new SyntaxError(lex);
0333:
0334: ASTree expr = parseExpression(tbl);
0335: if (lex.get() != ')' || lex.get() != ';')
0336: throw new SyntaxError(lex);
0337:
0338: return new Stmnt(t, expr, body);
0339: }
0340:
0341: /* for.statement : FOR "(" decl.or.expr expression ";" expression ")"
0342: * statement
0343: */
0344: private Stmnt parseFor(SymbolTable tbl) throws CompileError {
0345: Stmnt expr1, expr3;
0346: ASTree expr2;
0347: int t = lex.get(); // FOR
0348:
0349: SymbolTable tbl2 = new SymbolTable(tbl);
0350:
0351: if (lex.get() != '(')
0352: throw new SyntaxError(lex);
0353:
0354: if (lex.lookAhead() == ';') {
0355: lex.get();
0356: expr1 = null;
0357: } else
0358: expr1 = parseDeclarationOrExpression(tbl2, true);
0359:
0360: if (lex.lookAhead() == ';')
0361: expr2 = null;
0362: else
0363: expr2 = parseExpression(tbl2);
0364:
0365: if (lex.get() != ';')
0366: throw new CompileError("; is missing", lex);
0367:
0368: if (lex.lookAhead() == ')')
0369: expr3 = null;
0370: else
0371: expr3 = parseExprList(tbl2);
0372:
0373: if (lex.get() != ')')
0374: throw new CompileError(") is missing", lex);
0375:
0376: Stmnt body = parseStatement(tbl2);
0377: return new Stmnt(t, expr1, new ASTList(expr2, new ASTList(
0378: expr3, body)));
0379: }
0380:
0381: /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
0382: *
0383: * swtich.block : ( switch.label statement* )*
0384: *
0385: * swtich.label : DEFAULT ":"
0386: * | CASE const.expression ":"
0387: */
0388: private Stmnt parseSwitch(SymbolTable tbl) throws CompileError {
0389: int t = lex.get(); // SWITCH
0390: ASTree expr = parseParExpression(tbl);
0391: Stmnt body = parseSwitchBlock(tbl);
0392: return new Stmnt(t, expr, body);
0393: }
0394:
0395: private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError {
0396: if (lex.get() != '{')
0397: throw new SyntaxError(lex);
0398:
0399: SymbolTable tbl2 = new SymbolTable(tbl);
0400: Stmnt s = parseStmntOrCase(tbl2);
0401: if (s == null)
0402: throw new CompileError("empty switch block", lex);
0403:
0404: int op = s.getOperator();
0405: if (op != CASE && op != DEFAULT)
0406: throw new CompileError(
0407: "no case or default in a switch block", lex);
0408:
0409: Stmnt body = new Stmnt(BLOCK, s);
0410: while (lex.lookAhead() != '}') {
0411: Stmnt s2 = parseStmntOrCase(tbl2);
0412: if (s2 != null) {
0413: int op2 = s2.getOperator();
0414: if (op2 == CASE || op2 == DEFAULT) {
0415: body = (Stmnt) ASTList.concat(body, new Stmnt(
0416: BLOCK, s2));
0417: s = s2;
0418: } else
0419: s = (Stmnt) ASTList.concat(s, new Stmnt(BLOCK, s2));
0420: }
0421: }
0422:
0423: lex.get(); // '}'
0424: return body;
0425: }
0426:
0427: private Stmnt parseStmntOrCase(SymbolTable tbl) throws CompileError {
0428: int t = lex.lookAhead();
0429: if (t != CASE && t != DEFAULT)
0430: return parseStatement(tbl);
0431:
0432: lex.get();
0433: Stmnt s;
0434: if (t == CASE)
0435: s = new Stmnt(t, parseExpression(tbl));
0436: else
0437: s = new Stmnt(DEFAULT);
0438:
0439: if (lex.get() != ':')
0440: throw new CompileError(": is missing", lex);
0441:
0442: return s;
0443: }
0444:
0445: /* synchronized.statement :
0446: * SYNCHRONIZED "(" expression ")" block.statement
0447: */
0448: private Stmnt parseSynchronized(SymbolTable tbl)
0449: throws CompileError {
0450: int t = lex.get(); // SYNCHRONIZED
0451: if (lex.get() != '(')
0452: throw new SyntaxError(lex);
0453:
0454: ASTree expr = parseExpression(tbl);
0455: if (lex.get() != ')')
0456: throw new SyntaxError(lex);
0457:
0458: Stmnt body = parseBlock(tbl);
0459: return new Stmnt(t, expr, body);
0460: }
0461:
0462: /* try.statement
0463: * : TRY block.statement
0464: * [ CATCH "(" class.type Identifier ")" block.statement ]*
0465: * [ FINALLY block.statement ]*
0466: */
0467: private Stmnt parseTry(SymbolTable tbl) throws CompileError {
0468: lex.get(); // TRY
0469: Stmnt block = parseBlock(tbl);
0470: ASTList catchList = null;
0471: while (lex.lookAhead() == CATCH) {
0472: lex.get(); // CATCH
0473: if (lex.get() != '(')
0474: throw new SyntaxError(lex);
0475:
0476: SymbolTable tbl2 = new SymbolTable(tbl);
0477: Declarator d = parseFormalParam(tbl2);
0478: if (d.getArrayDim() > 0 || d.getType() != CLASS)
0479: throw new SyntaxError(lex);
0480:
0481: if (lex.get() != ')')
0482: throw new SyntaxError(lex);
0483:
0484: Stmnt b = parseBlock(tbl2);
0485: catchList = ASTList.append(catchList, new Pair(d, b));
0486: }
0487:
0488: Stmnt finallyBlock = null;
0489: if (lex.lookAhead() == FINALLY) {
0490: lex.get(); // FINALLY
0491: finallyBlock = parseBlock(tbl);
0492: }
0493:
0494: return Stmnt.make(TRY, block, catchList, finallyBlock);
0495: }
0496:
0497: /* return.statement : RETURN [ expression ] ";"
0498: */
0499: private Stmnt parseReturn(SymbolTable tbl) throws CompileError {
0500: int t = lex.get(); // RETURN
0501: Stmnt s = new Stmnt(t);
0502: if (lex.lookAhead() != ';')
0503: s.setLeft(parseExpression(tbl));
0504:
0505: if (lex.get() != ';')
0506: throw new CompileError("; is missing", lex);
0507:
0508: return s;
0509: }
0510:
0511: /* throw.statement : THROW expression ";"
0512: */
0513: private Stmnt parseThrow(SymbolTable tbl) throws CompileError {
0514: int t = lex.get(); // THROW
0515: ASTree expr = parseExpression(tbl);
0516: if (lex.get() != ';')
0517: throw new CompileError("; is missing", lex);
0518:
0519: return new Stmnt(t, expr);
0520: }
0521:
0522: /* break.statement : BREAK [ Identifier ] ";"
0523: */
0524: private Stmnt parseBreak(SymbolTable tbl) throws CompileError {
0525: return parseContinue(tbl);
0526: }
0527:
0528: /* continue.statement : CONTINUE [ Identifier ] ";"
0529: */
0530: private Stmnt parseContinue(SymbolTable tbl) throws CompileError {
0531: int t = lex.get(); // CONTINUE
0532: Stmnt s = new Stmnt(t);
0533: int t2 = lex.get();
0534: if (t2 == Identifier) {
0535: s.setLeft(new Symbol(lex.getString()));
0536: t2 = lex.get();
0537: }
0538:
0539: if (t2 != ';')
0540: throw new CompileError("; is missing", lex);
0541:
0542: return s;
0543: }
0544:
0545: /* declaration.or.expression
0546: * : [ FINAL ] built-in-type array.dimension declarators
0547: * | [ FINAL ] class.type array.dimension declarators
0548: * | expression ';'
0549: * | expr.list ';' if exprList is true
0550: *
0551: * Note: FINAL is currently ignored. This must be fixed
0552: * in future.
0553: */
0554: private Stmnt parseDeclarationOrExpression(SymbolTable tbl,
0555: boolean exprList) throws CompileError {
0556: int t = lex.lookAhead();
0557: while (t == FINAL) {
0558: lex.get();
0559: t = lex.lookAhead();
0560: }
0561:
0562: if (isBuiltinType(t)) {
0563: t = lex.get();
0564: int dim = parseArrayDimension();
0565: return parseDeclarators(tbl, new Declarator(t, dim));
0566: } else if (t == Identifier) {
0567: int i = nextIsClassType(0);
0568: if (i >= 0)
0569: if (lex.lookAhead(i) == Identifier) {
0570: ASTList name = parseClassType(tbl);
0571: int dim = parseArrayDimension();
0572: return parseDeclarators(tbl, new Declarator(name,
0573: dim));
0574: }
0575: }
0576:
0577: Stmnt expr;
0578: if (exprList)
0579: expr = parseExprList(tbl);
0580: else
0581: expr = new Stmnt(EXPR, parseExpression(tbl));
0582:
0583: if (lex.get() != ';')
0584: throw new CompileError("; is missing", lex);
0585:
0586: return expr;
0587: }
0588:
0589: /* expr.list : ( expression ',')* expression
0590: */
0591: private Stmnt parseExprList(SymbolTable tbl) throws CompileError {
0592: Stmnt expr = null;
0593: for (;;) {
0594: Stmnt e = new Stmnt(EXPR, parseExpression(tbl));
0595: expr = (Stmnt) ASTList.concat(expr, new Stmnt(BLOCK, e));
0596: if (lex.lookAhead() == ',')
0597: lex.get();
0598: else
0599: return expr;
0600: }
0601: }
0602:
0603: /* declarators : declarator [ ',' declarator ]* ';'
0604: */
0605: private Stmnt parseDeclarators(SymbolTable tbl, Declarator d)
0606: throws CompileError {
0607: Stmnt decl = null;
0608: for (;;) {
0609: decl = (Stmnt) ASTList.concat(decl, new Stmnt(DECL,
0610: parseDeclarator(tbl, d)));
0611: int t = lex.get();
0612: if (t == ';')
0613: return decl;
0614: else if (t != ',')
0615: throw new CompileError("; is missing", lex);
0616: }
0617: }
0618:
0619: /* declarator : Identifier array.dimension [ '=' initializer ]
0620: */
0621: private Declarator parseDeclarator(SymbolTable tbl, Declarator d)
0622: throws CompileError {
0623: if (lex.get() != Identifier || d.getType() == VOID)
0624: throw new SyntaxError(lex);
0625:
0626: String name = lex.getString();
0627: Symbol symbol = new Symbol(name);
0628: int dim = parseArrayDimension();
0629: ASTree init = null;
0630: if (lex.lookAhead() == '=') {
0631: lex.get();
0632: init = parseInitializer(tbl);
0633: }
0634:
0635: Declarator decl = d.make(symbol, dim, init);
0636: tbl.append(name, decl);
0637: return decl;
0638: }
0639:
0640: /* initializer : expression | array.initializer
0641: */
0642: private ASTree parseInitializer(SymbolTable tbl)
0643: throws CompileError {
0644: if (lex.lookAhead() == '{')
0645: return parseArrayInitializer(tbl);
0646: else
0647: return parseExpression(tbl);
0648: }
0649:
0650: /* array.initializer :
0651: * '{' (( array.initializer | expression ) ',')* '}'
0652: */
0653: private ArrayInit parseArrayInitializer(SymbolTable tbl)
0654: throws CompileError {
0655: lex.get(); // '{'
0656: ASTree expr = parseExpression(tbl);
0657: ArrayInit init = new ArrayInit(expr);
0658: while (lex.lookAhead() == ',') {
0659: lex.get();
0660: expr = parseExpression(tbl);
0661: ASTList.append(init, expr);
0662: }
0663:
0664: if (lex.get() != '}')
0665: throw new SyntaxError(lex);
0666:
0667: return init;
0668: }
0669:
0670: /* par.expression : '(' expression ')'
0671: */
0672: private ASTree parseParExpression(SymbolTable tbl)
0673: throws CompileError {
0674: if (lex.get() != '(')
0675: throw new SyntaxError(lex);
0676:
0677: ASTree expr = parseExpression(tbl);
0678: if (lex.get() != ')')
0679: throw new SyntaxError(lex);
0680:
0681: return expr;
0682: }
0683:
0684: /* expression : conditional.expr
0685: * | conditional.expr assign.op expression (right-to-left)
0686: */
0687: public ASTree parseExpression(SymbolTable tbl) throws CompileError {
0688: ASTree left = parseConditionalExpr(tbl);
0689: if (!isAssignOp(lex.lookAhead()))
0690: return left;
0691:
0692: int t = lex.get();
0693: ASTree right = parseExpression(tbl);
0694: return AssignExpr.makeAssign(t, left, right);
0695: }
0696:
0697: private static boolean isAssignOp(int t) {
0698: return t == '=' || t == MOD_E || t == AND_E || t == MUL_E
0699: || t == PLUS_E || t == MINUS_E || t == DIV_E
0700: || t == EXOR_E || t == OR_E || t == LSHIFT_E
0701: || t == RSHIFT_E || t == ARSHIFT_E;
0702: }
0703:
0704: /* conditional.expr (right-to-left)
0705: * : logical.or.expr [ '?' expression ':' conditional.expr ]
0706: */
0707: private ASTree parseConditionalExpr(SymbolTable tbl)
0708: throws CompileError {
0709: ASTree cond = parseBinaryExpr(tbl);
0710: if (lex.lookAhead() == '?') {
0711: lex.get();
0712: ASTree thenExpr = parseExpression(tbl);
0713: if (lex.get() != ':')
0714: throw new CompileError(": is missing", lex);
0715:
0716: ASTree elseExpr = parseExpression(tbl);
0717: return new CondExpr(cond, thenExpr, elseExpr);
0718: } else
0719: return cond;
0720: }
0721:
0722: /* logical.or.expr 10 (operator precedence)
0723: * : logical.and.expr
0724: * | logical.or.expr OROR logical.and.expr left-to-right
0725: *
0726: * logical.and.expr 9
0727: * : inclusive.or.expr
0728: * | logical.and.expr ANDAND inclusive.or.expr
0729: *
0730: * inclusive.or.expr 8
0731: * : exclusive.or.expr
0732: * | inclusive.or.expr "|" exclusive.or.expr
0733: *
0734: * exclusive.or.expr 7
0735: * : and.expr
0736: * | exclusive.or.expr "^" and.expr
0737: *
0738: * and.expr 6
0739: * : equality.expr
0740: * | and.expr "&" equality.expr
0741: *
0742: * equality.expr 5
0743: * : relational.expr
0744: * | equality.expr (EQ | NEQ) relational.expr
0745: *
0746: * relational.expr 4
0747: * : shift.expr
0748: * | relational.expr (LE | GE | "<" | ">") shift.expr
0749: * | relational.expr INSTANCEOF class.type ("[" "]")*
0750: *
0751: * shift.expr 3
0752: * : additive.expr
0753: * | shift.expr (LSHIFT | RSHIFT | ARSHIFT) additive.expr
0754: *
0755: * additive.expr 2
0756: * : multiply.expr
0757: * | additive.expr ("+" | "-") multiply.expr
0758: *
0759: * multiply.expr 1
0760: * : unary.expr
0761: * | multiply.expr ("*" | "/" | "%") unary.expr
0762: */
0763: private ASTree parseBinaryExpr(SymbolTable tbl) throws CompileError {
0764: ASTree expr = parseUnaryExpr(tbl);
0765: for (;;) {
0766: int t = lex.lookAhead();
0767: int p = getOpPrecedence(t);
0768: if (p == 0)
0769: return expr;
0770: else
0771: expr = binaryExpr2(tbl, expr, p);
0772: }
0773: }
0774:
0775: private ASTree parseInstanceOf(SymbolTable tbl, ASTree expr)
0776: throws CompileError {
0777: int t = lex.lookAhead();
0778: if (isBuiltinType(t)) {
0779: lex.get(); // primitive type
0780: int dim = parseArrayDimension();
0781: return new InstanceOfExpr(t, dim, expr);
0782: } else {
0783: ASTList name = parseClassType(tbl);
0784: int dim = parseArrayDimension();
0785: return new InstanceOfExpr(name, dim, expr);
0786: }
0787: }
0788:
0789: private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec)
0790: throws CompileError {
0791: int t = lex.get();
0792: if (t == INSTANCEOF)
0793: return parseInstanceOf(tbl, expr);
0794:
0795: ASTree expr2 = parseUnaryExpr(tbl);
0796: for (;;) {
0797: int t2 = lex.lookAhead();
0798: int p2 = getOpPrecedence(t2);
0799: if (p2 != 0 && prec > p2)
0800: expr2 = binaryExpr2(tbl, expr2, p2);
0801: else
0802: return BinExpr.makeBin(t, expr, expr2);
0803: }
0804: }
0805:
0806: // !"#$%&'( )*+,-./0 12345678 9:;<=>?
0807: private static final int[] binaryOpPrecedence = { 0, 0, 0, 0, 1, 6,
0808: 0, 0, 0, 1, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0809: 0, 4, 0, 4, 0 };
0810:
0811: private int getOpPrecedence(int c) {
0812: if ('!' <= c && c <= '?')
0813: return binaryOpPrecedence[c - '!'];
0814: else if (c == '^')
0815: return 7;
0816: else if (c == '|')
0817: return 8;
0818: else if (c == ANDAND)
0819: return 9;
0820: else if (c == OROR)
0821: return 10;
0822: else if (c == EQ || c == NEQ)
0823: return 5;
0824: else if (c == LE || c == GE || c == INSTANCEOF)
0825: return 4;
0826: else if (c == LSHIFT || c == RSHIFT || c == ARSHIFT)
0827: return 3;
0828: else
0829: return 0; // not a binary operator
0830: }
0831:
0832: /* unary.expr : "++"|"--" unary.expr
0833: | "+"|"-" unary.expr
0834: | "!"|"~" unary.expr
0835: | cast.expr
0836: | postfix.expr
0837:
0838: unary.expr.not.plus.minus is a unary expression starting without
0839: "+", "-", "++", or "--".
0840: */
0841: private ASTree parseUnaryExpr(SymbolTable tbl) throws CompileError {
0842: int t;
0843: switch (lex.lookAhead()) {
0844: case '+':
0845: case '-':
0846: case PLUSPLUS:
0847: case MINUSMINUS:
0848: case '!':
0849: case '~':
0850: t = lex.get();
0851: if (t == '-') {
0852: int t2 = lex.lookAhead();
0853: switch (t2) {
0854: case LongConstant:
0855: case IntConstant:
0856: case CharConstant:
0857: lex.get();
0858: return new IntConst(-lex.getLong(), t2);
0859: case DoubleConstant:
0860: case FloatConstant:
0861: lex.get();
0862: return new DoubleConst(-lex.getDouble(), t2);
0863: default:
0864: break;
0865: }
0866: }
0867:
0868: return Expr.make(t, parseUnaryExpr(tbl));
0869: case '(':
0870: return parseCast(tbl);
0871: default:
0872: return parsePostfix(tbl);
0873: }
0874: }
0875:
0876: /* cast.expr : "(" builtin.type ("[" "]")* ")" unary.expr
0877: | "(" class.type ("[" "]")* ")" unary.expr2
0878:
0879: unary.expr2 is a unary.expr begining with "(", NULL, StringL,
0880: Identifier, THIS, SUPER, or NEW.
0881:
0882: Either "(int.class)" or "(String[].class)" is a not cast expression.
0883: */
0884: private ASTree parseCast(SymbolTable tbl) throws CompileError {
0885: int t = lex.lookAhead(1);
0886: if (isBuiltinType(t) && nextIsBuiltinCast()) {
0887: lex.get(); // '('
0888: lex.get(); // primitive type
0889: int dim = parseArrayDimension();
0890: if (lex.get() != ')')
0891: throw new CompileError(") is missing", lex);
0892:
0893: return new CastExpr(t, dim, parseUnaryExpr(tbl));
0894: } else if (t == Identifier && nextIsClassCast()) {
0895: lex.get(); // '('
0896: ASTList name = parseClassType(tbl);
0897: int dim = parseArrayDimension();
0898: if (lex.get() != ')')
0899: throw new CompileError(") is missing", lex);
0900:
0901: return new CastExpr(name, dim, parseUnaryExpr(tbl));
0902: } else
0903: return parsePostfix(tbl);
0904: }
0905:
0906: private boolean nextIsBuiltinCast() {
0907: int t;
0908: int i = 2;
0909: while ((t = lex.lookAhead(i++)) == '[')
0910: if (lex.lookAhead(i++) != ']')
0911: return false;
0912:
0913: return lex.lookAhead(i - 1) == ')';
0914: }
0915:
0916: private boolean nextIsClassCast() {
0917: int i = nextIsClassType(1);
0918: if (i < 0)
0919: return false;
0920:
0921: int t = lex.lookAhead(i);
0922: if (t != ')')
0923: return false;
0924:
0925: t = lex.lookAhead(i + 1);
0926: return t == '(' || t == NULL || t == StringL || t == Identifier
0927: || t == THIS || t == SUPER || t == NEW || t == TRUE
0928: || t == FALSE || t == LongConstant || t == IntConstant
0929: || t == CharConstant || t == DoubleConstant
0930: || t == FloatConstant;
0931: }
0932:
0933: private int nextIsClassType(int i) {
0934: int t;
0935: while (lex.lookAhead(++i) == '.')
0936: if (lex.lookAhead(++i) != Identifier)
0937: return -1;
0938:
0939: while ((t = lex.lookAhead(i++)) == '[')
0940: if (lex.lookAhead(i++) != ']')
0941: return -1;
0942:
0943: return i - 1;
0944: }
0945:
0946: /* array.dimension : [ "[" "]" ]*
0947: */
0948: private int parseArrayDimension() throws CompileError {
0949: int arrayDim = 0;
0950: while (lex.lookAhead() == '[') {
0951: ++arrayDim;
0952: lex.get();
0953: if (lex.get() != ']')
0954: throw new CompileError("] is missing", lex);
0955: }
0956:
0957: return arrayDim;
0958: }
0959:
0960: /* class.type : Identifier ( "." Identifier )*
0961: */
0962: private ASTList parseClassType(SymbolTable tbl) throws CompileError {
0963: ASTList list = null;
0964: for (;;) {
0965: if (lex.get() != Identifier)
0966: throw new SyntaxError(lex);
0967:
0968: list = ASTList.append(list, new Symbol(lex.getString()));
0969: if (lex.lookAhead() == '.')
0970: lex.get();
0971: else
0972: break;
0973: }
0974:
0975: return list;
0976: }
0977:
0978: /* postfix.expr : number.literal
0979: * | primary.expr
0980: * | method.expr
0981: * | postfix.expr "++" | "--"
0982: * | postfix.expr "[" array.size "]"
0983: * | postfix.expr "." Identifier
0984: * | postfix.expr ( "[" "]" )* "." CLASS
0985: * | postfix.expr "#" Identifier
0986: *
0987: * "#" is not an operator of regular Java. It separates
0988: * a class name and a member name in an expression for static member
0989: * access. For example,
0990: * java.lang.Integer.toString(3) in regular Java
0991: * can be written like this:
0992: * java.lang.Integer#toString(3) for this compiler.
0993: */
0994: private ASTree parsePostfix(SymbolTable tbl) throws CompileError {
0995: int token = lex.lookAhead();
0996: switch (token) { // see also parseUnaryExpr()
0997: case LongConstant:
0998: case IntConstant:
0999: case CharConstant:
1000: lex.get();
1001: return new IntConst(lex.getLong(), token);
1002: case DoubleConstant:
1003: case FloatConstant:
1004: lex.get();
1005: return new DoubleConst(lex.getDouble(), token);
1006: default:
1007: break;
1008: }
1009:
1010: String str;
1011: ASTree index;
1012: ASTree expr = parsePrimaryExpr(tbl);
1013: int t;
1014: while (true) {
1015: switch (lex.lookAhead()) {
1016: case '(':
1017: expr = parseMethodCall(tbl, expr);
1018: break;
1019: case '[':
1020: if (lex.lookAhead(1) == ']') {
1021: int dim = parseArrayDimension();
1022: if (lex.get() != '.' || lex.get() != CLASS)
1023: throw new SyntaxError(lex);
1024:
1025: expr = parseDotClass(expr, dim);
1026: } else {
1027: index = parseArrayIndex(tbl);
1028: if (index == null)
1029: throw new SyntaxError(lex);
1030:
1031: expr = Expr.make(ARRAY, expr, index);
1032: }
1033: break;
1034: case PLUSPLUS:
1035: case MINUSMINUS:
1036: t = lex.get();
1037: expr = Expr.make(t, null, expr);
1038: break;
1039: case '.':
1040: lex.get();
1041: t = lex.get();
1042: if (t == CLASS) {
1043: expr = parseDotClass(expr, 0);
1044: } else if (t == Identifier) {
1045: str = lex.getString();
1046: expr = Expr.make('.', expr, new Member(str));
1047: } else
1048: throw new CompileError("missing member name", lex);
1049: break;
1050: case '#':
1051: lex.get();
1052: t = lex.get();
1053: if (t != Identifier)
1054: throw new CompileError(
1055: "missing static member name", lex);
1056:
1057: str = lex.getString();
1058: expr = Expr.make(MEMBER, new Symbol(toClassName(expr)),
1059: new Member(str));
1060: break;
1061: default:
1062: return expr;
1063: }
1064: }
1065: }
1066:
1067: /* Parse a .class expression on a class type. For example,
1068: * String.class => ('.' "String" "class")
1069: * String[].class => ('.' "[LString;" "class")
1070: */
1071: private ASTree parseDotClass(ASTree className, int dim)
1072: throws CompileError {
1073: String cname = toClassName(className);
1074: if (dim > 0) {
1075: StringBuffer sbuf = new StringBuffer();
1076: while (dim-- > 0)
1077: sbuf.append('[');
1078:
1079: sbuf.append('L').append(cname.replace('.', '/'))
1080: .append(';');
1081: cname = sbuf.toString();
1082: }
1083:
1084: return Expr.make('.', new Symbol(cname), new Member("class"));
1085: }
1086:
1087: /* Parses a .class expression on a built-in type. For example,
1088: * int.class => ('#' "java.lang.Integer" "TYPE")
1089: * int[].class => ('.' "[I", "class")
1090: */
1091: private ASTree parseDotClass(int builtinType, int dim)
1092: throws CompileError {
1093: if (dim > 0) {
1094: String cname = CodeGen.toJvmTypeName(builtinType, dim);
1095: return Expr.make('.', new Symbol(cname),
1096: new Member("class"));
1097: } else {
1098: String cname;
1099: switch (builtinType) {
1100: case BOOLEAN:
1101: cname = "java.lang.Boolean";
1102: break;
1103: case BYTE:
1104: cname = "java.lang.Byte";
1105: break;
1106: case CHAR:
1107: cname = "java.lang.Character";
1108: break;
1109: case SHORT:
1110: cname = "java.lang.Short";
1111: break;
1112: case INT:
1113: cname = "java.lang.Integer";
1114: break;
1115: case LONG:
1116: cname = "java.lang.Long";
1117: break;
1118: case FLOAT:
1119: cname = "java.lang.Float";
1120: break;
1121: case DOUBLE:
1122: cname = "java.lang.Double";
1123: break;
1124: case VOID:
1125: cname = "java.lang.Void";
1126: break;
1127: default:
1128: throw new CompileError("invalid builtin type: "
1129: + builtinType);
1130: }
1131:
1132: return Expr.make(MEMBER, new Symbol(cname), new Member(
1133: "TYPE"));
1134: }
1135: }
1136:
1137: /* method.call : method.expr "(" argument.list ")"
1138: * method.expr : THIS | SUPER | Identifier
1139: * | postfix.expr "." Identifier
1140: * | postfix.expr "#" Identifier
1141: */
1142: private ASTree parseMethodCall(SymbolTable tbl, ASTree expr)
1143: throws CompileError {
1144: if (expr instanceof Keyword) {
1145: int token = ((Keyword) expr).get();
1146: if (token != THIS && token != SUPER)
1147: throw new SyntaxError(lex);
1148: } else if (expr instanceof Symbol) // Identifier
1149: ;
1150: else if (expr instanceof Expr) {
1151: int op = ((Expr) expr).getOperator();
1152: if (op != '.' && op != MEMBER)
1153: throw new SyntaxError(lex);
1154: }
1155:
1156: return CallExpr.makeCall(expr, parseArgumentList(tbl));
1157: }
1158:
1159: private String toClassName(ASTree name) throws CompileError {
1160: StringBuffer sbuf = new StringBuffer();
1161: toClassName(name, sbuf);
1162: return sbuf.toString();
1163: }
1164:
1165: private void toClassName(ASTree name, StringBuffer sbuf)
1166: throws CompileError {
1167: if (name instanceof Symbol) {
1168: sbuf.append(((Symbol) name).get());
1169: return;
1170: } else if (name instanceof Expr) {
1171: Expr expr = (Expr) name;
1172: if (expr.getOperator() == '.') {
1173: toClassName(expr.oprand1(), sbuf);
1174: sbuf.append('.');
1175: toClassName(expr.oprand2(), sbuf);
1176: return;
1177: }
1178: }
1179:
1180: throw new CompileError("bad static member access", lex);
1181: }
1182:
1183: /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL
1184: * | StringL
1185: * | Identifier
1186: * | NEW new.expr
1187: * | "(" expression ")"
1188: * | builtin.type ( "[" "]" )* "." CLASS
1189: *
1190: * Identifier represents either a local variable name, a member name,
1191: * or a class name.
1192: */
1193: private ASTree parsePrimaryExpr(SymbolTable tbl)
1194: throws CompileError {
1195: int t;
1196: String name;
1197: Declarator decl;
1198: ASTree expr;
1199:
1200: switch (t = lex.get()) {
1201: case THIS:
1202: case SUPER:
1203: case TRUE:
1204: case FALSE:
1205: case NULL:
1206: return new Keyword(t);
1207: case Identifier:
1208: name = lex.getString();
1209: decl = tbl.lookup(name);
1210: if (decl == null)
1211: return new Member(name); // this or static member
1212: else
1213: return new Variable(name, decl); // local variable
1214: case StringL:
1215: return new StringL(lex.getString());
1216: case NEW:
1217: return parseNew(tbl);
1218: case '(':
1219: expr = parseExpression(tbl);
1220: if (lex.get() == ')')
1221: return expr;
1222: else
1223: throw new CompileError(") is missing", lex);
1224: default:
1225: if (isBuiltinType(t) || t == VOID) {
1226: int dim = parseArrayDimension();
1227: if (lex.get() == '.' && lex.get() == CLASS)
1228: return parseDotClass(t, dim);
1229: }
1230:
1231: throw new SyntaxError(lex);
1232: }
1233: }
1234:
1235: /* new.expr : class.type "(" argument.list ")"
1236: * | class.type array.size [ array.initializer ]
1237: * | primitive.type array.size [ array.initializer ]
1238: */
1239: private NewExpr parseNew(SymbolTable tbl) throws CompileError {
1240: ArrayInit init = null;
1241: int t = lex.lookAhead();
1242: if (isBuiltinType(t)) {
1243: lex.get();
1244: ASTList size = parseArraySize(tbl);
1245: if (lex.lookAhead() == '{')
1246: init = parseArrayInitializer(tbl);
1247:
1248: return new NewExpr(t, size, init);
1249: } else if (t == Identifier) {
1250: ASTList name = parseClassType(tbl);
1251: t = lex.lookAhead();
1252: if (t == '(') {
1253: ASTList args = parseArgumentList(tbl);
1254: return new NewExpr(name, args);
1255: } else if (t == '[') {
1256: ASTList size = parseArraySize(tbl);
1257: if (lex.lookAhead() == '{')
1258: init = parseArrayInitializer(tbl);
1259:
1260: return NewExpr.makeObjectArray(name, size, init);
1261: }
1262: }
1263:
1264: throw new SyntaxError(lex);
1265: }
1266:
1267: /* array.size : [ array.index ]*
1268: */
1269: private ASTList parseArraySize(SymbolTable tbl) throws CompileError {
1270: ASTList list = null;
1271: while (lex.lookAhead() == '[')
1272: list = ASTList.append(list, parseArrayIndex(tbl));
1273:
1274: return list;
1275: }
1276:
1277: /* array.index : "[" [ expression ] "]"
1278: */
1279: private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError {
1280: lex.get(); // '['
1281: if (lex.lookAhead() == ']') {
1282: lex.get();
1283: return null;
1284: } else {
1285: ASTree index = parseExpression(tbl);
1286: if (lex.get() != ']')
1287: throw new CompileError("] is missing", lex);
1288:
1289: return index;
1290: }
1291: }
1292:
1293: /* argument.list : "(" [ expression [ "," expression ]* ] ")"
1294: */
1295: private ASTList parseArgumentList(SymbolTable tbl)
1296: throws CompileError {
1297: if (lex.get() != '(')
1298: throw new CompileError("( is missing", lex);
1299:
1300: ASTList list = null;
1301: if (lex.lookAhead() != ')')
1302: for (;;) {
1303: list = ASTList.append(list, parseExpression(tbl));
1304: if (lex.lookAhead() == ',')
1305: lex.get();
1306: else
1307: break;
1308: }
1309:
1310: if (lex.get() != ')')
1311: throw new CompileError(") is missing", lex);
1312:
1313: return list;
1314: }
1315: }
|