📄 parser.java
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.compiler;import javassist.compiler.ast.*;public final class Parser implements TokenId { private Lex lex; public Parser(Lex lex) { this.lex = lex; } public boolean hasMore() { return lex.lookAhead() >= 0; } /* member.declaration * : method.declaration | field.declaration */ public ASTList parseMember(SymbolTable tbl) throws CompileError { ASTList mem = parseMember1(tbl); if (mem instanceof MethodDecl) return parseMethod2(tbl, (MethodDecl)mem); else return mem; } /* A method body is not parsed. */ public ASTList parseMember1(SymbolTable tbl) throws CompileError { ASTList mods = parseMemberMods(); Declarator d; boolean isConstructor = false; if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') { d = new Declarator(VOID, 0); isConstructor = true; } else d = parseFormalType(tbl); if (lex.get() != Identifier) throw new SyntaxError(lex); String name; if (isConstructor) name = MethodDecl.initName; else name = lex.getString(); d.setVariable(new Symbol(name)); if (isConstructor || lex.lookAhead() == '(') return parseMethod1(tbl, isConstructor, mods, d); else return parseField(tbl, mods, d); } /* field.declaration * : member.modifiers * formal.type Identifier * [ "=" expression ] ";" */ private FieldDecl parseField(SymbolTable tbl, ASTList mods, Declarator d) throws CompileError { ASTree expr = null; if (lex.lookAhead() == '=') { lex.get(); expr = parseExpression(tbl); } int c = lex.get(); if (c == ';') return new FieldDecl(mods, new ASTList(d, new ASTList(expr))); else if (c == ',') throw new CompileError( "only one field can be declared in one declaration", lex); else throw new SyntaxError(lex); } /* method.declaration * : member.modifiers * [ formal.type ] * Identifier "(" [ formal.parameter ( "," formal.parameter )* ] ")" * array.dimension * [ THROWS class.type ( "," class.type ) ] * ( block.statement | ";" ) * * Note that a method body is not parsed. */ private MethodDecl parseMethod1(SymbolTable tbl, boolean isConstructor, ASTList mods, Declarator d) throws CompileError { if (lex.get() != '(') throw new SyntaxError(lex); ASTList parms = null; if (lex.lookAhead() != ')') while (true) { parms = ASTList.append(parms, parseFormalParam(tbl)); int t = lex.lookAhead(); if (t == ',') lex.get(); else if (t == ')') break; } lex.get(); // ')' d.addArrayDim(parseArrayDimension()); if (isConstructor && d.getArrayDim() > 0) throw new SyntaxError(lex); ASTList throwsList = null; if (lex.lookAhead() == THROWS) { lex.get(); while (true) { throwsList = ASTList.append(throwsList, parseClassType(tbl)); if (lex.lookAhead() == ',') lex.get(); else break; } } return new MethodDecl(mods, new ASTList(d, ASTList.make(parms, throwsList, null))); } /* Parses a method body. */ public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md) throws CompileError { Stmnt body = null; if (lex.lookAhead() == ';') lex.get(); else { body = parseBlock(tbl); if (body == null) body = new Stmnt(BLOCK); } md.sublist(4).setHead(body); return md; } /* member.modifiers * : ( FINAL | SYNCHRONIZED | ABSTRACT * | PUBLIC | PROTECTED | PRIVATE | STATIC * | VOLATILE | TRANSIENT | STRICT )* */ private ASTList parseMemberMods() { int t; ASTList list = null; while (true) { t = lex.lookAhead(); if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED || t == PRIVATE || t == SYNCHRONIZED || t == STATIC || t == VOLATILE || t == TRANSIENT || t == STRICT) list = new ASTList(new Keyword(lex.get()), list); else break; } return list; } /* formal.type : ( build-in-type | class.type ) array.dimension */ private Declarator parseFormalType(SymbolTable tbl) throws CompileError { int t = lex.lookAhead(); if (isBuiltinType(t) || t == VOID) { lex.get(); // primitive type int dim = parseArrayDimension(); return new Declarator(t, dim); } else { ASTList name = parseClassType(tbl); int dim = parseArrayDimension(); return new Declarator(name, dim); } } private static boolean isBuiltinType(int t) { return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT || t == INT || t == LONG || t == FLOAT || t == DOUBLE); } /* formal.parameter : formal.type Identifier array.dimension */ private Declarator parseFormalParam(SymbolTable tbl) throws CompileError { Declarator d = parseFormalType(tbl); if (lex.get() != Identifier) throw new SyntaxError(lex); String name = lex.getString(); d.setVariable(new Symbol(name)); d.addArrayDim(parseArrayDimension()); tbl.append(name, d); return d; } /* statement : [ label ":" ]* labeled.statement * * labeled.statement * : block.statement * | if.statement * | while.statement * | do.statement * | for.statement * | switch.statement * | try.statement * | return.statement * | thorw.statement * | break.statement * | continue.statement * | declaration.or.expression * | ";" * * This method may return null (empty statement). */ public Stmnt parseStatement(SymbolTable tbl) throws CompileError { int t = lex.lookAhead(); if (t == '{') return parseBlock(tbl); else if (t == ';') { lex.get(); return new Stmnt(BLOCK); // empty statement } else if (t == Identifier && lex.lookAhead(1) == ':') { lex.get(); // Identifier String label = lex.getString(); lex.get(); // ':' return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl)); } else if (t == IF) return parseIf(tbl); else if (t == WHILE) return parseWhile(tbl); else if (t == DO) return parseDo(tbl); else if (t == FOR) return parseFor(tbl); else if (t == TRY) return parseTry(tbl); else if (t == SWITCH) return parseSwitch(tbl); else if (t == SYNCHRONIZED) return parseSynchronized(tbl); else if (t == RETURN) return parseReturn(tbl); else if (t == THROW) return parseThrow(tbl); else if (t == BREAK) return parseBreak(tbl); else if (t == CONTINUE) return parseContinue(tbl); else return parseDeclarationOrExpression(tbl, false); } /* block.statement : "{" statement* "}" */ private Stmnt parseBlock(SymbolTable tbl) throws CompileError { if (lex.get() != '{') throw new SyntaxError(lex); Stmnt body = null; SymbolTable tbl2 = new SymbolTable(tbl); while (lex.lookAhead() != '}') { Stmnt s = parseStatement(tbl2); if (s != null) body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s)); } lex.get(); // '}' if (body == null) return new Stmnt(BLOCK); // empty block else return body; } /* if.statement : IF "(" expression ")" statement * [ ELSE statement ] */ private Stmnt parseIf(SymbolTable tbl) throws CompileError { int t = lex.get(); // IF ASTree expr = parseParExpression(tbl); Stmnt thenp = parseStatement(tbl); Stmnt elsep; if (lex.lookAhead() == ELSE) { lex.get(); elsep = parseStatement(tbl); } else elsep = null; return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep))); } /* while.statement : WHILE "(" expression ")" statement */ private Stmnt parseWhile(SymbolTable tbl) throws CompileError { int t = lex.get(); // WHILE ASTree expr = parseParExpression(tbl); Stmnt body = parseStatement(tbl); return new Stmnt(t, expr, body); } /* do.statement : DO statement WHILE "(" expression ")" ";" */ private Stmnt parseDo(SymbolTable tbl) throws CompileError { int t = lex.get(); // DO Stmnt body = parseStatement(tbl); if (lex.get() != WHILE || lex.get() != '(') throw new SyntaxError(lex); ASTree expr = parseExpression(tbl); if (lex.get() != ')' || lex.get() != ';') throw new SyntaxError(lex); return new Stmnt(t, expr, body); } /* for.statement : FOR "(" decl.or.expr expression ";" expression ")" * statement */ private Stmnt parseFor(SymbolTable tbl) throws CompileError { Stmnt expr1, expr3; ASTree expr2; int t = lex.get(); // FOR SymbolTable tbl2 = new SymbolTable(tbl); if (lex.get() != '(') throw new SyntaxError(lex); if (lex.lookAhead() == ';') { lex.get(); expr1 = null; } else expr1 = parseDeclarationOrExpression(tbl2, true); if (lex.lookAhead() == ';') expr2 = null; else expr2 = parseExpression(tbl2); if (lex.get() != ';') throw new CompileError("; is missing", lex); if (lex.lookAhead() == ')') expr3 = null; else expr3 = parseExprList(tbl2); if (lex.get() != ')') throw new CompileError(") is missing", lex); Stmnt body = parseStatement(tbl2); return new Stmnt(t, expr1, new ASTList(expr2, new ASTList(expr3, body))); } /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}" * * swtich.block : ( switch.label statement* )* * * swtich.label : DEFAULT ":" * | CASE const.expression ":" */ private Stmnt parseSwitch(SymbolTable tbl) throws CompileError { int t = lex.get(); // SWITCH ASTree expr = parseParExpression(tbl); Stmnt body = parseSwitchBlock(tbl); return new Stmnt(t, expr, body); } private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError { if (lex.get() != '{') throw new SyntaxError(lex); SymbolTable tbl2 = new SymbolTable(tbl); Stmnt s = parseStmntOrCase(tbl2); if (s == null) throw new CompileError("empty switch block", lex); int op = s.getOperator(); if (op != CASE && op != DEFAULT) throw new CompileError("no case or default in a switch block", lex); Stmnt body = new Stmnt(BLOCK, s); while (lex.lookAhead() != '}') { Stmnt s2 = parseStmntOrCase(tbl2); if (s2 != null) { int op2 = s2.getOperator(); if (op2 == CASE || op2 == DEFAULT) { body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2)); s = s2; } else s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2)); } } lex.get(); // '}' return body; } private Stmnt parseStmntOrCase(SymbolTable tbl) throws CompileError { int t = lex.lookAhead(); if (t != CASE && t != DEFAULT) return parseStatement(tbl); lex.get(); Stmnt s; if (t == CASE) s = new Stmnt(t, parseExpression(tbl)); else s = new Stmnt(DEFAULT); if (lex.get() != ':') throw new CompileError(": is missing", lex); return s; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -