package frontend.ast; import frontend.ast.decl.Decl; import frontend.ast.func.MainFuncDef; import frontend.lexer.Token; import frontend.lexer.TokenStream; import frontend.ast.block.BlockItem; import frontend.ast.block.ForStmt; import frontend.ast.block.Block; import frontend.ast.decl.ConstDecl; import frontend.ast.decl.ConstDef; import frontend.ast.decl.VarDef; import frontend.ast.exp.UnaryExp; import frontend.ast.func.FuncDef; import frontend.ast.token.TokenNode; import frontend.lexer.TokenType; import frontend.ast.exp.LVal; import frontend.ast.block.Stmt; import frontend.ast.exp.Exp; import error.Errors; import error.Error; import error.ErrorType; import midend.symbol.FuncSymbol; import midend.symbol.SymbolManager; import midend.symbol.SymbolType; import midend.symbol.Symbol; import java.util.ArrayList; import java.util.HashMap; public class Node { private SyntaxType type; private ArrayList children; protected TokenStream ts; public Node(SyntaxType type, TokenStream ts) { this.type = type; this.ts = ts; this.children = new ArrayList<>(); } public void addChild(Node child) { this.children.add(child); } public String toString() { return "<" + type.toString() + ">\n"; } public Token getCurrToken() { return ts.peek(0); } // not change index in ts public Token read() { return ts.read(); } // change index in ts public String getInfo() { String info = ""; for (Node child : children) { info += child.getInfo(); } if (!(this instanceof Decl || this instanceof BlockItem)) { info += this.toString(); } return info; } public ArrayList getChildren() { return children; } public Node getChild(int index) { return children.get(index); } public void fillSymbolTable(boolean isInFunc, boolean isInFor, Errors errors) { if (this instanceof CompUnit || (this instanceof Block && !isInFunc)) { SymbolManager.addSymbolTable(); } if (this instanceof Decl) { handleDecl(errors); } if (this instanceof FuncDef) { handleFuncDef(errors); return; } if (this instanceof UnaryExp && children.get(0) instanceof TokenNode) { handleFuncCall(errors); return; } if (this instanceof Stmt && getChild(0) instanceof TokenNode && ((TokenNode) getChild(0)).getType() == TokenType.FORTK) { for (Node child: children) { child.fillSymbolTable(false, true, errors); } return; } if (this instanceof Stmt && getChild(0) instanceof TokenNode && (((TokenNode) getChild(0)).getType() == TokenType.BREAKTK || ((TokenNode) getChild(0)).getType() == TokenType.CONTINUETK)) { if (!isInFor) { errors.addError(new Error(((TokenNode) getChild(0)).getLine(), ErrorType.m)); } } if (this instanceof TokenNode) { handleTokenNode(errors); } if (this instanceof Stmt && getChild(0) instanceof LVal) { // error handle handleErrorhInStmt(errors); } if (this instanceof ForStmt) { handleErrorhInStmt(errors); } if (this instanceof Stmt && getChild(0) instanceof TokenNode && ((TokenNode) getChild(0)).getType() == TokenType.PRINTFTK) { handleMatchFormat(errors); } if (this instanceof MainFuncDef) { ((MainFuncDef) this).checkReturnNode(errors); } for (Node child : children) { child.fillSymbolTable(false, isInFor, errors); } if (this instanceof CompUnit || this instanceof Block) { SymbolManager.releaseSymbolTable(); // System.out.println("release a symbol table"); } // !注意哪些是直接return的,这些直接return的是否处理完整,因为他们直接省略了后续的递归,要么在子方法里重新递归了,要么没有递归的必要,仔细检查!!! } public void handleDecl(Errors errors) { if (this.children.get(0) instanceof ConstDecl) { Node constdecl = this.children.get(0); for (int i = 2; i < constdecl.children.size(); i = i + 2) { SymbolManager.addSymbol(((ConstDef) constdecl.children.get(i)).getSymbol(), errors); } } else { Node vardecl = this.children.get(0); if (((TokenNode) vardecl.children.get(0)).getType() == TokenType.STATICTK) { for (int i = 2; i < vardecl.children.size(); i = i + 2) { SymbolManager.addSymbol( ((VarDef) vardecl.children.get(i)).getSymbol(1), errors); // System.out.println(((VarDef) // vardecl.children.get(i)).getSymbol(1).toString()); } } else { for (int i = 1; i < vardecl.children.size(); i = i + 2) { SymbolManager.addSymbol( ((VarDef) vardecl.children.get(i)).getSymbol(0), errors); // System.out.println(((VarDef) // vardecl.children.get(i)).getSymbol(0).toString()); } } } } public void handleFuncDef(Errors errors) { FuncDef funcdef = (FuncDef) this; Symbol funcSymbol = funcdef.getSymbol(); // System.out.println(funcSymbol.toString()); // System.out.println(SymbolManager.getSymbolTableSize()); SymbolManager.addSymbol(funcSymbol, errors); SymbolManager.addSymbolTable(); funcdef.addParamSymbol(funcSymbol, errors); if (funcSymbol.getType() == SymbolType.VOID_FUNC) { // int returnStatus = funcdef.getReturnStatus(); // TokenNode returnNode = funcdef.getReturnNode(); HashMap returnNodes = new HashMap<>(); funcdef.getReturnNodes(returnNodes); for (TokenNode returnNode : returnNodes.keySet()) { if (returnNodes.get(returnNode) == 2) { errors.addError(new Error(returnNode.getLine(), ErrorType.f)); } } } else if (funcSymbol.getType() == SymbolType.INT_FUNC) { funcdef.checkReturnNode(errors); } // 填参数和块里定义的参数,一个问题是这时的释放是该如何判断 for (Node child : children) { if (child instanceof Block) { ((Block) child).fillSymbolTable(true, false, errors); } } } public void handleTokenNode(Errors errors) { TokenNode tokenNode = (TokenNode) this; if (tokenNode.getType() == TokenType.IDENFR && !tokenNode.getName().equals("getint")) { Symbol symbol = SymbolManager.getSymbol(tokenNode.getName()); if (symbol == null) { errors.addError(new Error(tokenNode.getLine(), ErrorType.c)); } } } public void handleFuncCall(Errors errors) { UnaryExp ue = (UnaryExp) this; ue.handleFuncCall(errors); } public void getReturnNodes(HashMap returnNodess) { // 0: no return, 1: return void, 2: return int for (int i = 0; i < children.size(); i++) { if (getChild(i) instanceof TokenNode && ((TokenNode) getChild(i)).getType() == TokenType.RETURNTK) { if (i == children.size() - 1) { returnNodess.put((TokenNode) getChild(i), 1); }else if (getChild(i+1) instanceof TokenNode) { returnNodess.put((TokenNode) getChild(i), 1); }else { returnNodess.put((TokenNode) getChild(i), 2); } } else if (!(getChild(i) instanceof TokenNode)) { getChild(i).getReturnNodes(returnNodess); } } } public void handleErrorhInStmt(Errors errors) { for (int i = 0; 4 * i < children.size(); i++){ TokenNode idenfr = (TokenNode) getChild(4 * i).getChild(0); Symbol symbol = SymbolManager.getSymbol(idenfr.getName()); if (symbol != null) { if (symbol.getType() == SymbolType.CONST_INT || symbol.getType() == SymbolType.CONST_INT_ARRAY) { errors.addError(new Error(idenfr.getLine(), ErrorType.h)); } } } } public void handleMatchFormat(Errors errors) { TokenNode strCons = (TokenNode) getChild(2); int formatNum = strCons.getFormatNum(); int expNum = 0; for (Node child : children) { if (child instanceof Exp) { expNum++; } } if (formatNum != expNum) { errors.addError(new Error(((TokenNode) getChild(0)).getLine(), ErrorType.l)); } } }