Files
MY_COMPILER/frontend/ast/Node.java
2025-12-10 17:58:17 +08:00

249 lines
9.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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));
}
}
}