249 lines
9.0 KiB
Java
249 lines
9.0 KiB
Java
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<Node> 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<Node> 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<TokenNode, Integer> 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<TokenNode, Integer> 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));
|
||
}
|
||
}
|
||
}
|