📄 parser.java
字号:
Either "(int.class)" or "(String[].class)" is a not cast expression. */ private ASTree parseCast(SymbolTable tbl) throws CompileError { int t = lex.lookAhead(1); if (isBuiltinType(t) && nextIsBuiltinCast()) { lex.get(); // '(' lex.get(); // primitive type int dim = parseArrayDimension(); if (lex.get() != ')') throw new CompileError(") is missing", lex); return new CastExpr(t, dim, parseUnaryExpr(tbl)); } else if (t == Identifier && nextIsClassCast()) { lex.get(); // '(' ASTList name = parseClassType(tbl); int dim = parseArrayDimension(); if (lex.get() != ')') throw new CompileError(") is missing", lex); return new CastExpr(name, dim, parseUnaryExpr(tbl)); } else return parsePostfix(tbl); } private boolean nextIsBuiltinCast() { int t; int i = 2; while ((t = lex.lookAhead(i++)) == '[') if (lex.lookAhead(i++) != ']') return false; return lex.lookAhead(i - 1) == ')'; } private boolean nextIsClassCast() { int i = nextIsClassType(1); if (i < 0) return false; int t = lex.lookAhead(i); if (t != ')') return false; t = lex.lookAhead(i + 1); return t == '(' || t == NULL || t == StringL || t == Identifier || t == THIS || t == SUPER || t == NEW || t == TRUE || t == FALSE || t == LongConstant || t == IntConstant || t == CharConstant || t == DoubleConstant || t == FloatConstant; } private int nextIsClassType(int i) { int t; while (lex.lookAhead(++i) == '.') if (lex.lookAhead(++i) != Identifier) return -1; while ((t = lex.lookAhead(i++)) == '[') if (lex.lookAhead(i++) != ']') return -1; return i - 1; } /* array.dimension : [ "[" "]" ]* */ private int parseArrayDimension() throws CompileError { int arrayDim = 0; while (lex.lookAhead() == '[') { ++arrayDim; lex.get(); if (lex.get() != ']') throw new CompileError("] is missing", lex); } return arrayDim; } /* class.type : Identifier ( "." Identifier )* */ private ASTList parseClassType(SymbolTable tbl) throws CompileError { ASTList list = null; for (;;) { if (lex.get() != Identifier) throw new SyntaxError(lex); list = ASTList.append(list, new Symbol(lex.getString())); if (lex.lookAhead() == '.') lex.get(); else break; } return list; } /* postfix.expr : number.literal * | primary.expr * | method.expr * | postfix.expr "++" | "--" * | postfix.expr "[" array.size "]" * | postfix.expr "." Identifier * | postfix.expr ( "[" "]" )* "." CLASS * | postfix.expr "#" Identifier * * "#" is not an operator of regular Java. It separates * a class name and a member name in an expression for static member * access. For example, * java.lang.Integer.toString(3) in regular Java * can be written like this: * java.lang.Integer#toString(3) for this compiler. */ private ASTree parsePostfix(SymbolTable tbl) throws CompileError { int token = lex.lookAhead(); switch (token) { // see also parseUnaryExpr() case LongConstant : case IntConstant : case CharConstant : lex.get(); return new IntConst(lex.getLong(), token); case DoubleConstant : case FloatConstant : lex.get(); return new DoubleConst(lex.getDouble(), token); default : break; } String str; ASTree index; ASTree expr = parsePrimaryExpr(tbl); int t; while (true) { switch (lex.lookAhead()) { case '(' : expr = parseMethodCall(tbl, expr); break; case '[' : if (lex.lookAhead(1) == ']') { int dim = parseArrayDimension(); if (lex.get() != '.' || lex.get() != CLASS) throw new SyntaxError(lex); expr = parseDotClass(expr, dim); } else { index = parseArrayIndex(tbl); if (index == null) throw new SyntaxError(lex); expr = Expr.make(ARRAY, expr, index); } break; case PLUSPLUS : case MINUSMINUS : t = lex.get(); expr = Expr.make(t, null, expr); break; case '.' : lex.get(); t = lex.get(); if (t == CLASS) { expr = parseDotClass(expr, 0); } else if (t == Identifier) { str = lex.getString(); expr = Expr.make('.', expr, new Member(str)); } else throw new CompileError("missing member name", lex); break; case '#' : lex.get(); t = lex.get(); if (t != Identifier) throw new CompileError("missing static member name", lex); str = lex.getString(); expr = Expr.make(MEMBER, new Symbol(toClassName(expr)), new Member(str)); break; default : return expr; } } } /* Parse a .class expression on a class type. For example, * String.class => ('.' "String" "class") * String[].class => ('.' "[LString;" "class") */ private ASTree parseDotClass(ASTree className, int dim) throws CompileError { String cname = toClassName(className); if (dim > 0) { StringBuffer sbuf = new StringBuffer(); while (dim-- > 0) sbuf.append('['); sbuf.append('L').append(cname.replace('.', '/')).append(';'); cname = sbuf.toString(); } return Expr.make('.', new Symbol(cname), new Member("class")); } /* Parses a .class expression on a built-in type. For example, * int.class => ('#' "java.lang.Integer" "TYPE") * int[].class => ('.' "[I", "class") */ private ASTree parseDotClass(int builtinType, int dim) throws CompileError { if (dim > 0) { String cname = CodeGen.toJvmTypeName(builtinType, dim); return Expr.make('.', new Symbol(cname), new Member("class")); } else { String cname; switch(builtinType) { case BOOLEAN : cname = "java.lang.Boolean"; break; case BYTE : cname = "java.lang.Byte"; break; case CHAR : cname = "java.lang.Character"; break; case SHORT : cname = "java.lang.Short"; break; case INT : cname = "java.lang.Integer"; break; case LONG : cname = "java.lang.Long"; break; case FLOAT : cname = "java.lang.Float"; break; case DOUBLE : cname = "java.lang.Double"; break; case VOID : cname = "java.lang.Void"; break; default : throw new CompileError("invalid builtin type: " + builtinType); } return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE")); } } /* method.call : method.expr "(" argument.list ")" * method.expr : THIS | SUPER | Identifier * | postfix.expr "." Identifier * | postfix.expr "#" Identifier */ private ASTree parseMethodCall(SymbolTable tbl, ASTree expr) throws CompileError { if (expr instanceof Keyword) { int token = ((Keyword)expr).get(); if (token != THIS && token != SUPER) throw new SyntaxError(lex); } else if (expr instanceof Symbol) // Identifier ; else if (expr instanceof Expr) { int op = ((Expr)expr).getOperator(); if (op != '.' && op != MEMBER) throw new SyntaxError(lex); } return CallExpr.makeCall(expr, parseArgumentList(tbl)); } private String toClassName(ASTree name) throws CompileError { StringBuffer sbuf = new StringBuffer(); toClassName(name, sbuf); return sbuf.toString(); } private void toClassName(ASTree name, StringBuffer sbuf) throws CompileError { if (name instanceof Symbol) { sbuf.append(((Symbol)name).get()); return; } else if (name instanceof Expr) { Expr expr = (Expr)name; if (expr.getOperator() == '.') { toClassName(expr.oprand1(), sbuf); sbuf.append('.'); toClassName(expr.oprand2(), sbuf); return; } } throw new CompileError("bad static member access", lex); } /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL * | StringL * | Identifier * | NEW new.expr * | "(" expression ")" * | builtin.type ( "[" "]" )* "." CLASS * * Identifier represents either a local variable name, a member name, * or a class name. */ private ASTree parsePrimaryExpr(SymbolTable tbl) throws CompileError { int t; String name; Declarator decl; ASTree expr; switch (t = lex.get()) { case THIS : case SUPER : case TRUE : case FALSE : case NULL : return new Keyword(t); case Identifier : name = lex.getString(); decl = tbl.lookup(name); if (decl == null) return new Member(name); // this or static member else return new Variable(name, decl); // local variable case StringL : return new StringL(lex.getString()); case NEW : return parseNew(tbl); case '(' : expr = parseExpression(tbl); if (lex.get() == ')') return expr; else throw new CompileError(") is missing", lex); default : if (isBuiltinType(t) || t == VOID) { int dim = parseArrayDimension(); if (lex.get() == '.' && lex.get() == CLASS) return parseDotClass(t, dim); } throw new SyntaxError(lex); } } /* new.expr : class.type "(" argument.list ")" * | class.type array.size [ array.initializer ] * | primitive.type array.size [ array.initializer ] */ private NewExpr parseNew(SymbolTable tbl) throws CompileError { ArrayInit init = null; int t = lex.lookAhead(); if (isBuiltinType(t)) { lex.get(); ASTList size = parseArraySize(tbl); if (lex.lookAhead() == '{') init = parseArrayInitializer(tbl); return new NewExpr(t, size, init); } else if (t == Identifier) { ASTList name = parseClassType(tbl); t = lex.lookAhead(); if (t == '(') { ASTList args = parseArgumentList(tbl); return new NewExpr(name, args); } else if (t == '[') { ASTList size = parseArraySize(tbl); if (lex.lookAhead() == '{') init = parseArrayInitializer(tbl); return NewExpr.makeObjectArray(name, size, init); } } throw new SyntaxError(lex); } /* array.size : [ array.index ]* */ private ASTList parseArraySize(SymbolTable tbl) throws CompileError { ASTList list = null; while (lex.lookAhead() == '[') list = ASTList.append(list, parseArrayIndex(tbl)); return list; } /* array.index : "[" [ expression ] "]" */ private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError { lex.get(); // '[' if (lex.lookAhead() == ']') { lex.get(); return null; } else { ASTree index = parseExpression(tbl); if (lex.get() != ']') throw new CompileError("] is missing", lex); return index; } } /* argument.list : "(" [ expression [ "," expression ]* ] ")" */ private ASTList parseArgumentList(SymbolTable tbl) throws CompileError { if (lex.get() != '(') throw new CompileError("( is missing", lex); ASTList list = null; if (lex.lookAhead() != ')') for (;;) { list = ASTList.append(list, parseExpression(tbl)); if (lex.lookAhead() == ',') lex.get(); else break; } if (lex.get() != ')') throw new CompileError(") is missing", lex); return list; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -