llvmir some opt
This commit is contained in:
BIN
2025编译技术实验文法定义及相关说明.pdf
Normal file
BIN
2025编译技术实验文法定义及相关说明.pdf
Normal file
Binary file not shown.
42
Compiler.java
Normal file
42
Compiler.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import frontend.lexer.Lexer;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.parser.Parser;
|
||||||
|
import midend.Midend;
|
||||||
|
import midend.errorhandle.ErrorHandler;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
public class Compiler {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Errors errors = new Errors();
|
||||||
|
try {
|
||||||
|
String content = new String(Files.readAllBytes(Paths.get("testfile.txt")));
|
||||||
|
String llvmFile = "llvm_ir.txt";
|
||||||
|
String errorFile = "error.txt";
|
||||||
|
Lexer lexer = new Lexer(content);
|
||||||
|
lexer.lex(errors);
|
||||||
|
TokenStream ts = new TokenStream(lexer.getTokens());
|
||||||
|
Parser parser = new Parser(ts);
|
||||||
|
parser.parse(errors);
|
||||||
|
ErrorHandler errorHandler = new ErrorHandler(parser.getCompUnit());
|
||||||
|
errorHandler.visit(errors);
|
||||||
|
// for (int i : SymbolManager.getSequence()) {
|
||||||
|
// System.out.print(i + " ");
|
||||||
|
// }
|
||||||
|
// System.out.println(); // TODO:debug
|
||||||
|
if (errors.size() > 0) {
|
||||||
|
StringBuilder sb = errors.toStringBuilder();
|
||||||
|
Files.write(Paths.get(errorFile), sb.toString().getBytes());
|
||||||
|
} else {
|
||||||
|
Midend midend = new Midend(parser.getCompUnit());
|
||||||
|
midend.generateLLvmIr();
|
||||||
|
midend.writeToFile(llvmFile);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
error/Error.java
Normal file
27
error/Error.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package error;
|
||||||
|
|
||||||
|
public class Error {
|
||||||
|
private int line;
|
||||||
|
private ErrorType type;
|
||||||
|
|
||||||
|
public Error(int line, ErrorType type) {
|
||||||
|
this.line = line;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printError() {
|
||||||
|
System.out.println(this.line + " " + this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return this.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorType getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.line + " " + this.type + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
17
error/ErrorType.java
Normal file
17
error/ErrorType.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package error;
|
||||||
|
|
||||||
|
public enum ErrorType {
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d,
|
||||||
|
e,
|
||||||
|
f,
|
||||||
|
g,
|
||||||
|
h,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
k,
|
||||||
|
l,
|
||||||
|
m
|
||||||
|
}
|
||||||
43
error/Errors.java
Normal file
43
error/Errors.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package error;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Errors {
|
||||||
|
private ArrayList<Error> errors;
|
||||||
|
|
||||||
|
public Errors() {
|
||||||
|
this.errors = new ArrayList<Error>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addError(Error error) {
|
||||||
|
int index = 0;
|
||||||
|
if (this.errors.size() == 0 ||
|
||||||
|
this.errors.get(this.errors.size() - 1).getLine() <= error.getLine()) {
|
||||||
|
this.errors.add(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.errors.get(0).getLine() > error.getLine()) {
|
||||||
|
this.errors.add(index, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = this.errors.size() - 1; i >= 0; i--) {
|
||||||
|
if (this.errors.get(i).getLine() <= error.getLine()) {
|
||||||
|
index = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.errors.add(index, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return this.errors.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilder toStringBuilder() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Error error : this.errors) {
|
||||||
|
sb.append(error.toString());
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
frontend/.DS_Store
vendored
Normal file
BIN
frontend/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
frontend/ast/.DS_Store
vendored
Normal file
BIN
frontend/ast/.DS_Store
vendored
Normal file
Binary file not shown.
63
frontend/ast/CompUnit.java
Normal file
63
frontend/ast/CompUnit.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package frontend.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import frontend.ast.func.FuncDef;
|
||||||
|
import frontend.ast.func.MainFuncDef;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class CompUnit extends Node {
|
||||||
|
public CompUnit(TokenStream ts) {
|
||||||
|
super(SyntaxType.COMP_UNIT, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
while (getCurrToken() != null) {
|
||||||
|
if (this.ts.peek(1).getType() == TokenType.MAINTK) {
|
||||||
|
MainFuncDef mainFuncDef = new MainFuncDef(this.ts);
|
||||||
|
mainFuncDef.parse(errors);
|
||||||
|
addChild(mainFuncDef);
|
||||||
|
} else if (this.ts.peek(2).getType() == TokenType.LPARENT) {
|
||||||
|
FuncDef funcdef = new FuncDef(this.ts);
|
||||||
|
funcdef.parse(errors);
|
||||||
|
addChild(funcdef);
|
||||||
|
} else {
|
||||||
|
Decl decl = new Decl(this.ts);
|
||||||
|
decl.parse(errors);
|
||||||
|
addChild(decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Decl> GetDecls() {
|
||||||
|
ArrayList<Decl> decls = new ArrayList<Decl>();
|
||||||
|
for (int i = 0; i < this.getChildren().size(); i++) {
|
||||||
|
if (this.getChild(i) instanceof Decl) {
|
||||||
|
decls.add((Decl) this.getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<FuncDef> GetFuncDefs() {
|
||||||
|
ArrayList<FuncDef> funcDefs = new ArrayList<FuncDef>();
|
||||||
|
for (int i = 0; i < this.getChildren().size(); i++) {
|
||||||
|
if (this.getChild(i) instanceof FuncDef) {
|
||||||
|
funcDefs.add((FuncDef) this.getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return funcDefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainFuncDef GetMainFuncDef() {
|
||||||
|
for (int i = 0; i < this.getChildren().size(); i++) {
|
||||||
|
if (this.getChild(i) instanceof MainFuncDef) {
|
||||||
|
return (MainFuncDef) this.getChild(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
248
frontend/ast/Node.java
Normal file
248
frontend/ast/Node.java
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
frontend/ast/NodeStack.java
Normal file
23
frontend/ast/NodeStack.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package frontend.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class NodeStack {
|
||||||
|
private ArrayList<Node> stack;
|
||||||
|
|
||||||
|
public NodeStack() {
|
||||||
|
stack = new ArrayList<Node>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void push(Node node) {
|
||||||
|
stack.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node pop() {
|
||||||
|
return stack.remove(stack.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return stack.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
66
frontend/ast/SyntaxType.java
Normal file
66
frontend/ast/SyntaxType.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package frontend.ast;
|
||||||
|
|
||||||
|
public enum SyntaxType {
|
||||||
|
COMP_UNIT("CompUnit"),
|
||||||
|
|
||||||
|
BTYPE("BType"),
|
||||||
|
|
||||||
|
DECL("Decl"),
|
||||||
|
CONST_DECL("ConstDecl"),
|
||||||
|
VAR_DECL("VarDecl"),
|
||||||
|
|
||||||
|
CONST_DEF("ConstDef"),
|
||||||
|
CONST_INIT_VAL("ConstInitVal"),
|
||||||
|
VAR_DEF("VarDef"),
|
||||||
|
INIT_VAL("InitVal"),
|
||||||
|
|
||||||
|
FUNC_DEF("FuncDef"),
|
||||||
|
MAIN_FUNC_DEF("MainFuncDef"),
|
||||||
|
FUNC_TYPE("FuncType"),
|
||||||
|
|
||||||
|
FUNC_FORMAL_PARAM("FuncFParam"),
|
||||||
|
FUNC_FORMAL_PARAM_S("FuncFParams"),
|
||||||
|
FUNC_REAL_PARAM_S("FuncRParams"),
|
||||||
|
|
||||||
|
BLOCK("Block"),
|
||||||
|
BLOCK_ITEM("BlockItem"),
|
||||||
|
|
||||||
|
STMT("Stmt"),
|
||||||
|
FOR_STMT("ForStmt"),
|
||||||
|
|
||||||
|
UNARY_OP("UnaryOp"),
|
||||||
|
IDENT("Ident"),
|
||||||
|
|
||||||
|
EXP("Exp"),
|
||||||
|
LVAL_EXP("LVal"),
|
||||||
|
PRIMARY_EXP("PrimaryExp"),
|
||||||
|
UNARY_EXP("UnaryExp"),
|
||||||
|
MUL_EXP("MulExp"),
|
||||||
|
ADD_EXP("AddExp"),
|
||||||
|
REL_EXP("RelExp"),
|
||||||
|
EQ_EXP("EqExp"),
|
||||||
|
LAND_EXP("LAndExp"),
|
||||||
|
LOR_EXP("LOrExp"),
|
||||||
|
CONST_EXP("ConstExp"),
|
||||||
|
COND_EXP("Cond"),
|
||||||
|
|
||||||
|
NUMBER("Number"),
|
||||||
|
CHARACTER("Character"),
|
||||||
|
|
||||||
|
INT_CONST("IntConst"),
|
||||||
|
STRING_CONST("StringConst"),
|
||||||
|
CHAR_CONST("CharConst"),
|
||||||
|
|
||||||
|
TOKEN("Token");
|
||||||
|
|
||||||
|
private final String Name;
|
||||||
|
|
||||||
|
SyntaxType(String Name) {
|
||||||
|
this.Name = Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
frontend/ast/block/Block.java
Normal file
49
frontend/ast/block/Block.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package frontend.ast.block;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
|
||||||
|
public class Block extends Node {
|
||||||
|
private boolean isFuncBlock;
|
||||||
|
|
||||||
|
public Block(TokenStream ts) {
|
||||||
|
super(SyntaxType.BLOCK, ts);
|
||||||
|
isFuncBlock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode lbrace = new TokenNode(this.ts);
|
||||||
|
addChild(lbrace);
|
||||||
|
while (getCurrToken().getType() != TokenType.RBRACE) {
|
||||||
|
BlockItem bit = new BlockItem(this.ts);
|
||||||
|
bit.parse(errors);
|
||||||
|
addChild(bit);
|
||||||
|
}
|
||||||
|
TokenNode rbrace = new TokenNode(this.ts);
|
||||||
|
addChild(rbrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<BlockItem> getBlockItems() {
|
||||||
|
ArrayList<BlockItem> blockItems = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i++) {
|
||||||
|
if (getChild(i) instanceof BlockItem) {
|
||||||
|
blockItems.add((BlockItem) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return blockItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFuncBlock() {
|
||||||
|
return isFuncBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsFuncBlock(boolean isFuncBlock) {
|
||||||
|
this.isFuncBlock = isFuncBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
frontend/ast/block/BlockItem.java
Normal file
28
frontend/ast/block/BlockItem.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package frontend.ast.block;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
|
||||||
|
public class BlockItem extends Node {
|
||||||
|
public BlockItem(TokenStream ts) {
|
||||||
|
super(SyntaxType.BLOCK_ITEM, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.CONSTTK
|
||||||
|
|| getCurrToken().getType() == TokenType.STATICTK
|
||||||
|
|| getCurrToken().getType() == TokenType.INTTK) {
|
||||||
|
Decl decl = new Decl(this.ts);
|
||||||
|
decl.parse(errors);
|
||||||
|
addChild(decl);
|
||||||
|
} else {
|
||||||
|
Stmt stmt = new Stmt(this.ts);
|
||||||
|
stmt.parse(errors);
|
||||||
|
addChild(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
frontend/ast/block/ForStmt.java
Normal file
57
frontend/ast/block/ForStmt.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package frontend.ast.block;
|
||||||
|
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.exp.Exp;
|
||||||
|
import frontend.ast.exp.LVal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class ForStmt extends Node {
|
||||||
|
public ForStmt(TokenStream ts) {
|
||||||
|
super(SyntaxType.FOR_STMT, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
handleAssign(errors);
|
||||||
|
while (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
addChild(new TokenNode(ts)); // comma
|
||||||
|
handleAssign(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleAssign(Errors errors) {
|
||||||
|
LVal lval = new LVal(this.ts);
|
||||||
|
lval.parse(errors);
|
||||||
|
addChild(lval);
|
||||||
|
addChild(new TokenNode(ts)); // assign
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<LVal> getLValList() {
|
||||||
|
ArrayList<LVal> lvalList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i++) {
|
||||||
|
if (getChild(i) instanceof LVal) {
|
||||||
|
lvalList.add((LVal) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lvalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Exp> getExpList() {
|
||||||
|
ArrayList<Exp> expList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i++) {
|
||||||
|
if (getChild(i) instanceof Exp) {
|
||||||
|
expList.add((Exp) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expList;
|
||||||
|
}
|
||||||
|
}
|
||||||
274
frontend/ast/block/Stmt.java
Normal file
274
frontend/ast/block/Stmt.java
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
package frontend.ast.block;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.exp.Exp;
|
||||||
|
import frontend.ast.exp.Cond;
|
||||||
|
import frontend.ast.exp.LVal;
|
||||||
|
|
||||||
|
public class Stmt extends Node {
|
||||||
|
private boolean getint;
|
||||||
|
|
||||||
|
public Stmt(TokenStream ts) {
|
||||||
|
super(SyntaxType.STMT, ts);
|
||||||
|
getint = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACE) {
|
||||||
|
Block block = new Block(this.ts);
|
||||||
|
block.parse(errors);
|
||||||
|
addChild(block);
|
||||||
|
} else if (getCurrToken().getType() == TokenType.IFTK) {
|
||||||
|
handleIf(errors);
|
||||||
|
} else if (getCurrToken().getType() == TokenType.FORTK) {
|
||||||
|
handleFor(errors);
|
||||||
|
} else if (getCurrToken().getType() == TokenType.BREAKTK) {
|
||||||
|
TokenNode breakkk = new TokenNode(this.ts);
|
||||||
|
addChild(breakkk);
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
} else if (getCurrToken().getType() == TokenType.CONTINUETK) {
|
||||||
|
TokenNode continuekk = new TokenNode(this.ts);
|
||||||
|
addChild(continuekk);
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
} else if (getCurrToken().getType() == TokenType.RETURNTK) {
|
||||||
|
handleReturn(errors);
|
||||||
|
} else if (getCurrToken().getType() == TokenType.PRINTFTK) {
|
||||||
|
handlePrintf(errors);
|
||||||
|
} else {
|
||||||
|
handleAssign(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleIf(Errors errors) {
|
||||||
|
TokenNode ifkk = new TokenNode(this.ts);
|
||||||
|
addChild(ifkk);
|
||||||
|
TokenNode lparent = new TokenNode(this.ts);
|
||||||
|
addChild(lparent);
|
||||||
|
Cond cond = new Cond(this.ts);
|
||||||
|
cond.parse(errors);
|
||||||
|
addChild(cond);
|
||||||
|
if (getCurrToken().getType() == TokenType.RPARENT) {
|
||||||
|
TokenNode rparent = new TokenNode(this.ts);
|
||||||
|
addChild(rparent);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
}
|
||||||
|
Stmt stmt = new Stmt(this.ts);
|
||||||
|
stmt.parse(errors);
|
||||||
|
addChild(stmt);
|
||||||
|
if (getCurrToken().getType() == TokenType.ELSETK) {
|
||||||
|
TokenNode elsekk = new TokenNode(this.ts);
|
||||||
|
addChild(elsekk);
|
||||||
|
Stmt elseStmt = new Stmt(this.ts);
|
||||||
|
elseStmt.parse(errors);
|
||||||
|
addChild(elseStmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleFor(Errors errors) {
|
||||||
|
TokenNode forkk = new TokenNode(this.ts);
|
||||||
|
addChild(forkk);
|
||||||
|
TokenNode lparent = new TokenNode(this.ts);
|
||||||
|
addChild(lparent);
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
} else {
|
||||||
|
ForStmt fst = new ForStmt(this.ts);
|
||||||
|
fst.parse(errors);
|
||||||
|
addChild(fst);
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
} else {
|
||||||
|
Cond cond = new Cond(this.ts);
|
||||||
|
cond.parse(errors);
|
||||||
|
addChild(cond);
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.RPARENT) {
|
||||||
|
TokenNode rparent = new TokenNode(this.ts);
|
||||||
|
addChild(rparent);
|
||||||
|
} else {
|
||||||
|
ForStmt fst = new ForStmt(this.ts);
|
||||||
|
fst.parse(errors);
|
||||||
|
addChild(fst);
|
||||||
|
TokenNode rparent = new TokenNode(this.ts);
|
||||||
|
addChild(rparent);
|
||||||
|
}
|
||||||
|
Stmt stmt = new Stmt(this.ts);
|
||||||
|
stmt.parse(errors);
|
||||||
|
addChild(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleReturn(Errors errors) {
|
||||||
|
TokenNode returnkk = new TokenNode(this.ts);
|
||||||
|
addChild(returnkk);
|
||||||
|
if (currentIsExp()) {
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicolon = new TokenNode(this.ts);
|
||||||
|
addChild(semicolon);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePrintf(Errors errors) {
|
||||||
|
TokenNode printfkk = new TokenNode(this.ts);
|
||||||
|
addChild(printfkk);
|
||||||
|
addChild(new TokenNode(this.ts)); // lparent
|
||||||
|
addChild(new TokenNode(this.ts)); // strconst
|
||||||
|
while (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
addChild(new TokenNode(this.ts)); // comma
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() != TokenType.RPARENT) {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
} else {
|
||||||
|
addChild(new TokenNode(this.ts)); // rparent
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() != TokenType.SEMICN) {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
} else {
|
||||||
|
addChild(new TokenNode(this.ts)); // semicolon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleAssign(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.IDENFR) {
|
||||||
|
if (this.ts.peek(1).getType() == TokenType.ASSIGN) {
|
||||||
|
LVal lval = new LVal(this.ts);
|
||||||
|
lval.parse(errors);
|
||||||
|
addChild(lval);
|
||||||
|
addChild(new TokenNode(this.ts)); // assign
|
||||||
|
if (getCurrToken().getValue().equals("getint")) {
|
||||||
|
getint = true;
|
||||||
|
}
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
addChild(new TokenNode(this.ts)); // semicolon
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
} else if (this.ts.peek(1).getType() == TokenType.LBRACK) {
|
||||||
|
int start = this.ts.getCurrentIndex();
|
||||||
|
LVal lval = new LVal(this.ts);
|
||||||
|
lval.parse(errors);
|
||||||
|
if (getCurrToken().getType() == TokenType.ASSIGN) {
|
||||||
|
addChild(lval);
|
||||||
|
addChild(new TokenNode(this.ts)); // assign
|
||||||
|
if (getCurrToken().getValue().equals("getint")) {
|
||||||
|
getint = true;
|
||||||
|
}
|
||||||
|
handleExpInAssign(errors);
|
||||||
|
} else {
|
||||||
|
this.ts.resetIndex(start);
|
||||||
|
// parse exp ;
|
||||||
|
handleExpInAssign(errors);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleExpInAssign(errors);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentIsExp()) {
|
||||||
|
handleExpInAssign(errors);
|
||||||
|
} else {
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
addChild(new TokenNode(this.ts)); // semicolon
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleExpInAssign(Errors errors) {
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
addChild(new TokenNode(this.ts)); // semicolon
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean currentIsExp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|
||||||
|
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGetint() {
|
||||||
|
return getint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Exp> getExpList() {
|
||||||
|
ArrayList<Exp> expList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i++) {
|
||||||
|
if (getChild(i) instanceof Exp) {
|
||||||
|
expList.add((Exp) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cond getCond() { //just for fortype stmt
|
||||||
|
for (int i = 0; i < getChildren().size(); i++) {
|
||||||
|
if (getChild(i) instanceof Cond) {
|
||||||
|
return (Cond) getChild(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForStmt getinitStmt() {
|
||||||
|
if (getChild(2) instanceof ForStmt) {
|
||||||
|
return (ForStmt) getChild(2);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForStmt getStepStmt() {
|
||||||
|
if (getChild(getChildren().size() - 3) instanceof ForStmt) {
|
||||||
|
return (ForStmt) getChild(getChildren().size() - 3);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stmt getBodyStmt() {
|
||||||
|
return (Stmt) getChild(getChildren().size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
frontend/ast/decl/ConstDecl.java
Normal file
51
frontend/ast/decl/ConstDecl.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package frontend.ast.decl;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import error.ErrorType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class ConstDecl extends Node {
|
||||||
|
public ConstDecl(TokenStream ts) {
|
||||||
|
super(SyntaxType.CONST_DECL, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode constkk = new TokenNode(this.ts);
|
||||||
|
addChild(constkk);
|
||||||
|
TokenNode intkk = new TokenNode(this.ts);
|
||||||
|
addChild(intkk);
|
||||||
|
while (true) {
|
||||||
|
ConstDef cdef = new ConstDef(this.ts);
|
||||||
|
cdef.parse(errors);
|
||||||
|
addChild(cdef);
|
||||||
|
if (getCurrToken().getType() != TokenType.COMMA) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
TokenNode comma = new TokenNode(this.ts);
|
||||||
|
addChild(comma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() != TokenType.SEMICN) {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
} else {
|
||||||
|
TokenNode semicoln = new TokenNode(this.ts);
|
||||||
|
addChild(semicoln);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ConstDef> GetConstDefs() {
|
||||||
|
ArrayList<ConstDef> constDefs = new ArrayList<>();
|
||||||
|
for (int i = 2; i < getChildren().size(); i += 2) {
|
||||||
|
constDefs.add((ConstDef) getChild(i));
|
||||||
|
}
|
||||||
|
return constDefs;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
frontend/ast/decl/ConstDef.java
Normal file
66
frontend/ast/decl/ConstDef.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package frontend.ast.decl;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.exp.ConstExp;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.val.ConstInitVal;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.SymbolType;
|
||||||
|
|
||||||
|
public class ConstDef extends Node {
|
||||||
|
private boolean isArray;
|
||||||
|
|
||||||
|
public ConstDef(TokenStream ts) {
|
||||||
|
super(SyntaxType.CONST_DEF, ts);
|
||||||
|
isArray = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode ident = new TokenNode(this.ts);
|
||||||
|
addChild(ident);
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACK) {
|
||||||
|
TokenNode lbrack = new TokenNode(this.ts);
|
||||||
|
addChild(lbrack);
|
||||||
|
isArray = true;
|
||||||
|
ConstExp cep = new ConstExp(this.ts);
|
||||||
|
cep.parse(errors);
|
||||||
|
addChild(cep);
|
||||||
|
if (getCurrToken().getType() == TokenType.RBRACK) {
|
||||||
|
TokenNode rbrack = new TokenNode(this.ts);
|
||||||
|
addChild(rbrack);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenNode assign = new TokenNode(this.ts);
|
||||||
|
addChild(assign);
|
||||||
|
ConstInitVal civ = new ConstInitVal(this.ts);
|
||||||
|
civ.parse(errors);
|
||||||
|
addChild(civ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
if (isArray) {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
|
||||||
|
SymbolType.CONST_INT_ARRAY, tn.getLine(),
|
||||||
|
((ConstExp) getChild(2)).getValue());
|
||||||
|
arraySymbol.addValue(((ConstInitVal) getChild(getChildren().size() - 1)).getValue());
|
||||||
|
arraySymbol.fullValue();
|
||||||
|
return arraySymbol;
|
||||||
|
} else {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
Symbol valueSymbol = new Symbol(tn.getName(),
|
||||||
|
SymbolType.CONST_INT, tn.getLine());
|
||||||
|
valueSymbol.addValue(((ConstInitVal) getChild(getChildren().size() - 1)).getValue());
|
||||||
|
return valueSymbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
frontend/ast/decl/Decl.java
Normal file
25
frontend/ast/decl/Decl.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package frontend.ast.decl;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class Decl extends Node {
|
||||||
|
public Decl(TokenStream ts) {
|
||||||
|
super(SyntaxType.DECL, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.CONSTTK) {
|
||||||
|
ConstDecl cd = new ConstDecl(this.ts);
|
||||||
|
cd.parse(errors);
|
||||||
|
addChild(cd);
|
||||||
|
} else {
|
||||||
|
VarDecl vd = new VarDecl(this.ts);
|
||||||
|
vd.parse(errors);
|
||||||
|
addChild(vd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
frontend/ast/decl/VarDecl.java
Normal file
59
frontend/ast/decl/VarDecl.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package frontend.ast.decl;
|
||||||
|
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class VarDecl extends Node {
|
||||||
|
public VarDecl(TokenStream ts) {
|
||||||
|
super(SyntaxType.VAR_DECL, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.STATICTK) {
|
||||||
|
TokenNode staitckk = new TokenNode(ts);
|
||||||
|
addChild(staitckk);
|
||||||
|
}
|
||||||
|
TokenNode intkk = new TokenNode(ts);
|
||||||
|
addChild(intkk);
|
||||||
|
while (true) {
|
||||||
|
VarDef vdf = new VarDef(ts);
|
||||||
|
vdf.parse(errors);
|
||||||
|
addChild(vdf);
|
||||||
|
if (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
TokenNode comma = new TokenNode(ts);
|
||||||
|
addChild(comma);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.SEMICN) {
|
||||||
|
TokenNode semicn = new TokenNode(ts);
|
||||||
|
addChild(semicn);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<VarDef> GetVarDefs() {
|
||||||
|
ArrayList<VarDef> varDefs = new ArrayList<VarDef>();
|
||||||
|
if (getChild(1) instanceof VarDef) {
|
||||||
|
for (int i = 1; i < getChildren().size(); i += 2) {
|
||||||
|
varDefs.add((VarDef) getChild(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 2; i < getChildren().size(); i += 2) {
|
||||||
|
varDefs.add((VarDef) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return varDefs;
|
||||||
|
}
|
||||||
|
}
|
||||||
117
frontend/ast/decl/VarDef.java
Normal file
117
frontend/ast/decl/VarDef.java
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
package frontend.ast.decl;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.exp.ConstExp;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.val.InitVal;
|
||||||
|
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import midend.symbol.SymbolType;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
|
||||||
|
public class VarDef extends Node {
|
||||||
|
private boolean isArray;
|
||||||
|
|
||||||
|
public VarDef(TokenStream ts) {
|
||||||
|
super(SyntaxType.VAR_DEF, ts);
|
||||||
|
isArray = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode ident = new TokenNode(this.ts);
|
||||||
|
addChild(ident);
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACK) {
|
||||||
|
TokenNode lbrack = new TokenNode(this.ts);
|
||||||
|
addChild(lbrack);
|
||||||
|
isArray = true;
|
||||||
|
ConstExp cep = new ConstExp(this.ts);
|
||||||
|
cep.parse(errors);
|
||||||
|
addChild(cep);
|
||||||
|
if (getCurrToken().getType() == TokenType.RBRACK) {
|
||||||
|
TokenNode rbrack = new TokenNode(this.ts);
|
||||||
|
addChild(rbrack);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.ASSIGN) {
|
||||||
|
TokenNode assign = new TokenNode(this.ts);
|
||||||
|
addChild(assign);
|
||||||
|
InitVal itv = new InitVal(this.ts);
|
||||||
|
itv.parse(errors);
|
||||||
|
addChild(itv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol(int isStatic) {
|
||||||
|
if (isStatic == 1) { //static修饰的变量有初值
|
||||||
|
if (isArray) {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
|
||||||
|
SymbolType.STATIC_INT_ARRAY, tn.getLine(),
|
||||||
|
((ConstExp) getChild(2)).getValue());
|
||||||
|
if (HaveInitVal()) {
|
||||||
|
arraySymbol.addValue(((InitVal) getChild(getChildren().size() - 1)).getValue());
|
||||||
|
}
|
||||||
|
arraySymbol.fullValue();
|
||||||
|
return arraySymbol;
|
||||||
|
} else {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
Symbol valueSymbol = new Symbol(tn.getName(),
|
||||||
|
SymbolType.STATIC_INT, tn.getLine());
|
||||||
|
if (HaveInitVal()) {
|
||||||
|
valueSymbol.addValue(((InitVal) getChild(getChildren().size() - 1)).getValue());
|
||||||
|
} else {
|
||||||
|
valueSymbol.addValue(0);
|
||||||
|
}
|
||||||
|
return valueSymbol;
|
||||||
|
}
|
||||||
|
} else { //要判断是否为全局变量,如果为全局变量,也应该赋初值
|
||||||
|
if (isArray) {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
|
||||||
|
SymbolType.INT_ARRAY, tn.getLine(),
|
||||||
|
((ConstExp) getChild(2)).getValue());
|
||||||
|
if (SymbolManager.IsGlobal()) {
|
||||||
|
if (HaveInitVal()) {
|
||||||
|
arraySymbol.addValue(((InitVal) getChild(
|
||||||
|
getChildren().size() - 1)).getValue());
|
||||||
|
}
|
||||||
|
arraySymbol.fullValue();
|
||||||
|
}
|
||||||
|
return arraySymbol;
|
||||||
|
} else {
|
||||||
|
TokenNode tn = (TokenNode) getChild(0);
|
||||||
|
Symbol symbol = new Symbol(tn.getName(),
|
||||||
|
SymbolType.INT, tn.getLine());
|
||||||
|
if (SymbolManager.IsGlobal()) {
|
||||||
|
if (HaveInitVal()) {
|
||||||
|
symbol.addValue(((InitVal) getChild(
|
||||||
|
getChildren().size() - 1)).getValue());
|
||||||
|
} else {
|
||||||
|
symbol.addValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean HaveInitVal() {
|
||||||
|
return getChild(getChildren().size() - 1) instanceof InitVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InitVal getInitVal() {
|
||||||
|
if (HaveInitVal()) {
|
||||||
|
return (InitVal) getChild(getChildren().size() - 1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
frontend/ast/exp/AddExp.java
Normal file
73
frontend/ast/exp/AddExp.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class AddExp extends Node {
|
||||||
|
public AddExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.ADD_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
MulExp mep = new MulExp(this.ts);
|
||||||
|
mep.parse(errors);
|
||||||
|
stack.push(mep);
|
||||||
|
if (isAddOp()) {
|
||||||
|
stack.push(new TokenNode(ts)); // addop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.size() == 1) {
|
||||||
|
this.addChild((MulExp) stack.pop());
|
||||||
|
} else {
|
||||||
|
AddExp temp = this;
|
||||||
|
while (stack.size() > 1) {
|
||||||
|
AddExp ae = new AddExp(this.ts);
|
||||||
|
MulExp mep = (MulExp) stack.pop();
|
||||||
|
TokenNode op = (TokenNode) stack.pop();
|
||||||
|
temp.addChild(ae);
|
||||||
|
temp.addChild(op);
|
||||||
|
temp.addChild(mep);
|
||||||
|
temp = ae;
|
||||||
|
}
|
||||||
|
temp.addChild((MulExp) stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAddOp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.PLUS || t == TokenType.MINU;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
if (getChildren().size() == 1) {
|
||||||
|
return ((MulExp) getChild(0)).getType();
|
||||||
|
} else {
|
||||||
|
return ((AddExp) getChild(0)).getType()
|
||||||
|
| ((MulExp) getChild(2)).getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
if (getChild(0) instanceof MulExp) {
|
||||||
|
return ((MulExp) getChild(0)).getValue();
|
||||||
|
} else {
|
||||||
|
int left = ((AddExp) getChild(0)).getValue();
|
||||||
|
int right = ((MulExp) getChild(2)).getValue();
|
||||||
|
if (((TokenNode) getChild(1)).getType() == TokenType.PLUS) {
|
||||||
|
return left + right;
|
||||||
|
} else {
|
||||||
|
return left - right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
frontend/ast/exp/Cond.java
Normal file
18
frontend/ast/exp/Cond.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
|
||||||
|
public class Cond extends Node {
|
||||||
|
public Cond(TokenStream ts) {
|
||||||
|
super(SyntaxType.COND_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
LOrExp lep = new LOrExp(this.ts);
|
||||||
|
lep.parse(errors);
|
||||||
|
addChild(lep);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
frontend/ast/exp/ConstExp.java
Normal file
22
frontend/ast/exp/ConstExp.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
|
||||||
|
public class ConstExp extends Node {
|
||||||
|
public ConstExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.CONST_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
AddExp ade = new AddExp(ts);
|
||||||
|
ade.parse(errors);
|
||||||
|
addChild(ade);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return ((AddExp) getChild(0)).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
frontend/ast/exp/EqExp.java
Normal file
49
frontend/ast/exp/EqExp.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class EqExp extends Node {
|
||||||
|
public EqExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.EQ_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
RelExp relexp = new RelExp(this.ts);
|
||||||
|
relexp.parse(errors);
|
||||||
|
stack.push(relexp);
|
||||||
|
if (isEqOp()) {
|
||||||
|
stack.push(new TokenNode(ts)); // eqop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(stack.size() == 1) {
|
||||||
|
this.addChild((RelExp)stack.pop());
|
||||||
|
} else {
|
||||||
|
EqExp temp = this;
|
||||||
|
while (stack.size() > 1) {
|
||||||
|
EqExp eep = new EqExp(this.ts);
|
||||||
|
RelExp relexp = (RelExp)stack.pop();
|
||||||
|
TokenNode eqop = (TokenNode)stack.pop();
|
||||||
|
temp.addChild(eep);
|
||||||
|
temp.addChild(eqop);
|
||||||
|
temp.addChild(relexp);
|
||||||
|
temp = eep;
|
||||||
|
}
|
||||||
|
temp.addChild((RelExp)stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEqOp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.EQL || t == TokenType.NEQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
frontend/ast/exp/Exp.java
Normal file
27
frontend/ast/exp/Exp.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class Exp extends Node {
|
||||||
|
public Exp(TokenStream ts) {
|
||||||
|
super(SyntaxType.EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
AddExp addexp = new AddExp(this.ts);
|
||||||
|
addexp.parse(errors);
|
||||||
|
addChild(addexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return ((AddExp) getChild(0)).getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return ((AddExp) getChild(0)).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
44
frontend/ast/exp/LAndExp.java
Normal file
44
frontend/ast/exp/LAndExp.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class LAndExp extends Node {
|
||||||
|
public LAndExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.LAND_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
EqExp eep = new EqExp(this.ts);
|
||||||
|
eep.parse(errors);
|
||||||
|
stack.push(eep);
|
||||||
|
if (getCurrToken().getType() == TokenType.AND) {
|
||||||
|
stack.push(new TokenNode(ts)); // landop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.size() == 1) {
|
||||||
|
this.addChild((EqExp)stack.pop());
|
||||||
|
} else {
|
||||||
|
LAndExp temp = this;
|
||||||
|
while(stack.size() > 1) {
|
||||||
|
LAndExp lae = new LAndExp(this.ts);
|
||||||
|
EqExp eep = (EqExp)stack.pop();
|
||||||
|
TokenNode landop = (TokenNode)stack.pop();
|
||||||
|
temp.addChild(lae);
|
||||||
|
temp.addChild(landop);
|
||||||
|
temp.addChild(eep);
|
||||||
|
temp = lae;
|
||||||
|
}
|
||||||
|
temp.addChild((EqExp)stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
frontend/ast/exp/LOrExp.java
Normal file
44
frontend/ast/exp/LOrExp.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class LOrExp extends Node {
|
||||||
|
public LOrExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.LOR_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
LAndExp andexp = new LAndExp(this.ts);
|
||||||
|
andexp.parse(errors);
|
||||||
|
stack.push(andexp);
|
||||||
|
if (getCurrToken().getType() == TokenType.OR) {
|
||||||
|
stack.push(new TokenNode(ts)); // lorop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.size() == 1) {
|
||||||
|
this.addChild((LAndExp)stack.pop());
|
||||||
|
} else {
|
||||||
|
LOrExp temp = this;
|
||||||
|
while(stack.size() > 1) {
|
||||||
|
LOrExp loe = new LOrExp(this.ts);
|
||||||
|
LAndExp lae = (LAndExp)stack.pop();
|
||||||
|
TokenNode lorop = (TokenNode)stack.pop();
|
||||||
|
temp.addChild(loe);
|
||||||
|
temp.addChild(lorop);
|
||||||
|
temp.addChild(lae);
|
||||||
|
temp = loe;
|
||||||
|
}
|
||||||
|
temp.addChild((LAndExp)stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
frontend/ast/exp/LVal.java
Normal file
59
frontend/ast/exp/LVal.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
import error.Errors;
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
|
||||||
|
public class LVal extends Node {
|
||||||
|
public LVal(TokenStream ts) {
|
||||||
|
super(SyntaxType.LVAL_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
addChild(new TokenNode(this.ts)); // idenfr
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACK) {
|
||||||
|
addChild(new TokenNode(this.ts)); // lbrack
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
if (getCurrToken().getType() == TokenType.RBRACK) {
|
||||||
|
addChild(new TokenNode(this.ts)); // rbrack
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
if (getChildren().size() == 1) {
|
||||||
|
TokenNode idenfr = (TokenNode) getChild(0);
|
||||||
|
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
|
||||||
|
if (symbol instanceof ArraySymbol) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
TokenNode idenfr = (TokenNode) getChild(0); //idenfr一定是个常量,可在符号表找到且有值
|
||||||
|
if (getChildren().size() == 1) {
|
||||||
|
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
|
||||||
|
return symbol.getValue(0);
|
||||||
|
} else {
|
||||||
|
int index = ((Exp) getChild(2)).getValue();
|
||||||
|
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
|
||||||
|
return symbol.getValue(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
frontend/ast/exp/MulExp.java
Normal file
75
frontend/ast/exp/MulExp.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class MulExp extends Node {
|
||||||
|
public MulExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.MUL_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
UnaryExp uep = new UnaryExp(this.ts);
|
||||||
|
uep.parse(errors);
|
||||||
|
stack.push(uep);
|
||||||
|
if (isMulOp()) {
|
||||||
|
stack.push(new TokenNode(ts)); // mulop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.size() == 1) {
|
||||||
|
addChild((UnaryExp)stack.pop());
|
||||||
|
} else {
|
||||||
|
MulExp temp = this;
|
||||||
|
while (stack.size() > 1) {
|
||||||
|
MulExp mep = new MulExp(this.ts);
|
||||||
|
UnaryExp uep = (UnaryExp) stack.pop();
|
||||||
|
TokenNode mulop = (TokenNode) stack.pop();
|
||||||
|
temp.addChild(mep);
|
||||||
|
temp.addChild(mulop);
|
||||||
|
temp.addChild(uep);
|
||||||
|
temp = mep;
|
||||||
|
}
|
||||||
|
temp.addChild((UnaryExp)stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMulOp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.MULT || t == TokenType.DIV || t == TokenType.MOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
if (getChildren().size() == 1) {
|
||||||
|
return ((UnaryExp) getChild(0)).getType();
|
||||||
|
} else {
|
||||||
|
return ((MulExp) getChild(0)).getType()
|
||||||
|
| ((UnaryExp) getChild(2)).getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
if (getChild(0) instanceof UnaryExp) {
|
||||||
|
return ((UnaryExp) getChild(0)).getValue();
|
||||||
|
} else {
|
||||||
|
int left = ((MulExp) getChild(0)).getValue();
|
||||||
|
int right = ((UnaryExp) getChild(2)).getValue();
|
||||||
|
if (((TokenNode) getChild(1)).getType() == TokenType.MULT) {
|
||||||
|
return left * right;
|
||||||
|
} else if (((TokenNode) getChild(1)).getType() == TokenType.DIV) {
|
||||||
|
return left / right;
|
||||||
|
} else {
|
||||||
|
return left % right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
frontend/ast/exp/NumberExp.java
Normal file
21
frontend/ast/exp/NumberExp.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
|
||||||
|
public class NumberExp extends Node {
|
||||||
|
public NumberExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.NUMBER, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
addChild(new TokenNode(ts)); //intconst
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return Integer.parseInt(((TokenNode) getChild(0)).getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
58
frontend/ast/exp/PrimaryExp.java
Normal file
58
frontend/ast/exp/PrimaryExp.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.Errors;
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
|
||||||
|
public class PrimaryExp extends Node {
|
||||||
|
public PrimaryExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.PRIMARY_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.LPARENT) {
|
||||||
|
addChild(new TokenNode(ts)); // lparent
|
||||||
|
Exp exp = new Exp(this.ts);
|
||||||
|
exp.parse(errors);
|
||||||
|
addChild(exp);
|
||||||
|
if (getCurrToken().getType() == TokenType.RPARENT) {
|
||||||
|
addChild(new TokenNode(ts)); // rparent
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
}
|
||||||
|
} else if (getCurrToken().getType() == TokenType.IDENFR) {
|
||||||
|
LVal lval = new LVal(this.ts);
|
||||||
|
lval.parse(errors);
|
||||||
|
addChild(lval);
|
||||||
|
} else {
|
||||||
|
NumberExp num = new NumberExp(this.ts);
|
||||||
|
num.parse(errors);
|
||||||
|
addChild(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
if (getChild(0) instanceof TokenNode) {
|
||||||
|
return ((Exp) getChild(1)).getType();
|
||||||
|
} else if (getChild(0) instanceof LVal) {
|
||||||
|
return ((LVal) getChild(0)).getType();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
if (getChild(0) instanceof TokenNode) {
|
||||||
|
return ((Exp) getChild(1)).getValue();
|
||||||
|
} else if (getChild(0) instanceof LVal) {
|
||||||
|
return ((LVal) getChild(0)).getValue();
|
||||||
|
} else {
|
||||||
|
return ((NumberExp) getChild(0)).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
frontend/ast/exp/RelExp.java
Normal file
50
frontend/ast/exp/RelExp.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.NodeStack;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class RelExp extends Node {
|
||||||
|
public RelExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.REL_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
NodeStack stack = new NodeStack();
|
||||||
|
while (true) {
|
||||||
|
AddExp addexp = new AddExp(this.ts);
|
||||||
|
addexp.parse(errors);
|
||||||
|
stack.push(addexp);
|
||||||
|
if (isRelOp()) {
|
||||||
|
stack.push(new TokenNode(ts)); // relop
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.size() == 1) {
|
||||||
|
this.addChild((AddExp)stack.pop());
|
||||||
|
} else {
|
||||||
|
RelExp temp = this;
|
||||||
|
while(stack.size() > 1) {
|
||||||
|
RelExp rexp = new RelExp(this.ts);
|
||||||
|
AddExp addexp = (AddExp)stack.pop();
|
||||||
|
TokenNode relop = (TokenNode)stack.pop();
|
||||||
|
temp.addChild(rexp);
|
||||||
|
temp.addChild(relop);
|
||||||
|
temp.addChild(addexp);
|
||||||
|
temp = rexp;
|
||||||
|
}
|
||||||
|
temp.addChild((AddExp)stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRelOp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.LSS || t == TokenType.GRE
|
||||||
|
|| t == TokenType.LEQ || t == TokenType.GEQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
124
frontend/ast/exp/UnaryExp.java
Normal file
124
frontend/ast/exp/UnaryExp.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.func.FuncRParams;
|
||||||
|
import midend.symbol.FuncSymbol;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
|
||||||
|
public class UnaryExp extends Node {
|
||||||
|
public UnaryExp(TokenStream ts) {
|
||||||
|
super(SyntaxType.UNARY_EXP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (isUnaryOp()) {
|
||||||
|
UnaryOp uop = new UnaryOp(ts);
|
||||||
|
uop.parse(errors);
|
||||||
|
addChild(uop);
|
||||||
|
UnaryExp uep = new UnaryExp(ts);
|
||||||
|
uep.parse(errors);
|
||||||
|
addChild(uep);
|
||||||
|
} else if (getCurrToken().getType() == TokenType.IDENFR
|
||||||
|
&& this.ts.peek(1).getType() == TokenType.LPARENT) {
|
||||||
|
addChild(new TokenNode(ts)); // idenfr
|
||||||
|
addChild(new TokenNode(ts)); // lparent
|
||||||
|
if (isExp()) {
|
||||||
|
FuncRParams frp = new FuncRParams(ts);
|
||||||
|
frp.parse(errors);
|
||||||
|
addChild(frp);
|
||||||
|
}
|
||||||
|
if (getCurrToken().getType() == TokenType.RPARENT) {
|
||||||
|
addChild(new TokenNode(ts)); // rparent
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrimaryExp pme = new PrimaryExp(ts);
|
||||||
|
pme.parse(errors);
|
||||||
|
addChild(pme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUnaryOp() {
|
||||||
|
return getCurrToken().getType() == TokenType.PLUS
|
||||||
|
|| getCurrToken().getType() == TokenType.MINU
|
||||||
|
|| getCurrToken().getType() == TokenType.NOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExp() {
|
||||||
|
TokenType t = getCurrToken().getType();
|
||||||
|
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|
||||||
|
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleFuncCall(Errors errors) { // 当其为函数调用形式时才会调用
|
||||||
|
TokenNode funcIdenfr = (TokenNode) getChild(0);
|
||||||
|
if (funcIdenfr.getName().equals("getint")) {
|
||||||
|
if (getChildren().size() == 4) {
|
||||||
|
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(funcIdenfr.getName());
|
||||||
|
if (funcSymbol == null) {
|
||||||
|
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.c));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int fparaNum = funcSymbol.getParamNum();
|
||||||
|
int rparaNum = 0;
|
||||||
|
if (getChildren().size() >= 3 && getChild(2) instanceof FuncRParams) {
|
||||||
|
FuncRParams frp = (FuncRParams) getChild(2);
|
||||||
|
rparaNum = frp.getParamNum();
|
||||||
|
if (rparaNum == fparaNum) {
|
||||||
|
frp.checkParamType(funcSymbol, errors, funcIdenfr.getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fparaNum != rparaNum) {
|
||||||
|
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
if (getChild(0) instanceof PrimaryExp) {
|
||||||
|
return ((PrimaryExp) getChild(0)).getType();
|
||||||
|
} else if (getChild(0) instanceof TokenNode) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return ((UnaryExp) getChild(1)).getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
if (getChild(0) instanceof UnaryOp) {
|
||||||
|
UnaryOp uop = (UnaryOp) getChild(0);
|
||||||
|
TokenNode opToken = (TokenNode) uop.getChild(0);
|
||||||
|
return opToken.getType() == TokenType.PLUS ? ((UnaryExp) getChild(1)).getValue()
|
||||||
|
: -((UnaryExp) getChild(1)).getValue();
|
||||||
|
} else if (getChild(0) instanceof PrimaryExp) {
|
||||||
|
return ((PrimaryExp) getChild(0)).getValue();
|
||||||
|
} else {
|
||||||
|
return 0; // 0表示这个是函数,getvalue只是对于常量或常量表达式取值,所以正常情况调用getvalue函数时是不会跳转到这个分支的
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Exp> getParamList() {
|
||||||
|
if (!(getChild(0) instanceof TokenNode)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
if (getChildren().size() >= 3 && (getChild(2) instanceof FuncRParams)) {
|
||||||
|
return ((FuncRParams) getChild(2)).getParamList();
|
||||||
|
}
|
||||||
|
return new ArrayList<Exp>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
frontend/ast/exp/UnaryOp.java
Normal file
17
frontend/ast/exp/UnaryOp.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package frontend.ast.exp;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
|
||||||
|
public class UnaryOp extends Node {
|
||||||
|
public UnaryOp(TokenStream ts) {
|
||||||
|
super(SyntaxType.UNARY_OP, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
addChild(new TokenNode(ts)); // unary op
|
||||||
|
}
|
||||||
|
}
|
||||||
108
frontend/ast/func/FuncDef.java
Normal file
108
frontend/ast/func/FuncDef.java
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.block.Block;
|
||||||
|
import frontend.ast.block.BlockItem;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.SymbolType;
|
||||||
|
import midend.symbol.FuncSymbol;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
public class FuncDef extends Node {
|
||||||
|
public FuncDef(TokenStream ts) {
|
||||||
|
super(SyntaxType.FUNC_DEF, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
FuncType ft = new FuncType(this.ts);
|
||||||
|
ft.parse(errors);
|
||||||
|
addChild(ft);
|
||||||
|
TokenNode ident = new TokenNode(this.ts);
|
||||||
|
addChild(ident);
|
||||||
|
TokenNode lparen = new TokenNode(this.ts);
|
||||||
|
addChild(lparen);
|
||||||
|
if (getCurrToken().getType() != TokenType.RPARENT &&
|
||||||
|
getCurrToken().getType() != TokenType.LBRACE) {
|
||||||
|
FuncFParams ffp = new FuncFParams(this.ts);
|
||||||
|
ffp.parse(errors);
|
||||||
|
addChild(ffp);
|
||||||
|
if (getCurrToken().getType() == TokenType.RPARENT) {
|
||||||
|
TokenNode rparen = new TokenNode(this.ts);
|
||||||
|
addChild(rparen);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
}
|
||||||
|
} else if (getCurrToken().getType() == TokenType.LBRACE) {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
} else {
|
||||||
|
TokenNode rparen = new TokenNode(this.ts);
|
||||||
|
addChild(rparen);
|
||||||
|
}
|
||||||
|
Block block = new Block(this.ts);
|
||||||
|
block.setIsFuncBlock(true);
|
||||||
|
block.parse(errors);
|
||||||
|
addChild(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
if (((FuncType) getChild(0)).isVoid()) {
|
||||||
|
TokenNode tn = (TokenNode) getChild(1);
|
||||||
|
return new FuncSymbol(tn.getName(),
|
||||||
|
SymbolType.VOID_FUNC, tn.getLine(), 0);
|
||||||
|
} else {
|
||||||
|
TokenNode tn = (TokenNode) getChild(1);
|
||||||
|
return new FuncSymbol(tn.getName(),
|
||||||
|
SymbolType.INT_FUNC, tn.getLine(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParamSymbol(Symbol funcSymbol, Errors errors) {
|
||||||
|
if (getChild(3) instanceof FuncFParams) {
|
||||||
|
FuncFParams ffp = (FuncFParams) getChild(3);
|
||||||
|
ArrayList<FuncFParam> paramList = ffp.getParamList();
|
||||||
|
for (FuncFParam param : paramList) {
|
||||||
|
Symbol paramSymbol = param.getSymbol();
|
||||||
|
SymbolManager.addSymbol(paramSymbol, errors);
|
||||||
|
((FuncSymbol) funcSymbol).addParamSymbol(paramSymbol); // 将形参存到函数的符号中
|
||||||
|
if (paramSymbol instanceof ArraySymbol) {
|
||||||
|
((FuncSymbol) funcSymbol).addParam(1);
|
||||||
|
} else {
|
||||||
|
((FuncSymbol) funcSymbol).addParam(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkReturnNode(Errors errors) {
|
||||||
|
Block block = (Block) getChild(getChildren().size() - 1);
|
||||||
|
TokenNode rbrace = (TokenNode) block.getChild(block.getChildren().size() - 1);
|
||||||
|
if (block.getChildren().size() == 2) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
BlockItem bit = (BlockItem) block.getChild(block.getChildren().size() - 2);
|
||||||
|
if (bit.getChild(0) instanceof Decl) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
if (!(bit.getChild(0).getChild(0) instanceof TokenNode)) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
TokenNode returnNode = (TokenNode) bit.getChild(0).getChild(0);
|
||||||
|
if (returnNode.getType() != TokenType.RETURNTK) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
frontend/ast/func/FuncFParam.java
Normal file
49
frontend/ast/func/FuncFParam.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.SymbolType;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Error;
|
||||||
|
|
||||||
|
public class FuncFParam extends Node {
|
||||||
|
public FuncFParam(TokenStream ts) {
|
||||||
|
super(SyntaxType.FUNC_FORMAL_PARAM, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode intkk = new TokenNode(this.ts);
|
||||||
|
addChild(intkk);
|
||||||
|
TokenNode ident = new TokenNode(this.ts);
|
||||||
|
addChild(ident);
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACK) {
|
||||||
|
TokenNode lbrack = new TokenNode(this.ts);
|
||||||
|
addChild(lbrack);
|
||||||
|
if (getCurrToken().getType() == TokenType.RBRACK) {
|
||||||
|
TokenNode rbrack = new TokenNode(this.ts);
|
||||||
|
addChild(rbrack);
|
||||||
|
} else {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
if (getChildren().size() == 2) {
|
||||||
|
TokenNode tn = (TokenNode) getChild(1);
|
||||||
|
return new Symbol(tn.getName(), SymbolType.INT, tn.getLine());
|
||||||
|
} else {
|
||||||
|
TokenNode tn = (TokenNode) getChild(1);
|
||||||
|
return new ArraySymbol(tn.getName(), SymbolType.INT_ARRAY, tn.getLine(), -1);
|
||||||
|
//这里不求维数,因为函数形参为数组只是相当于一个指针
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
frontend/ast/func/FuncFParams.java
Normal file
38
frontend/ast/func/FuncFParams.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class FuncFParams extends Node {
|
||||||
|
public FuncFParams(TokenStream ts) {
|
||||||
|
super(SyntaxType.FUNC_FORMAL_PARAM_S, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
while (true) {
|
||||||
|
FuncFParam ffp = new FuncFParam(this.ts);
|
||||||
|
ffp.parse(errors);
|
||||||
|
addChild(ffp);
|
||||||
|
if (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
TokenNode comma = new TokenNode(this.ts);
|
||||||
|
addChild(comma);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<FuncFParam> getParamList() {
|
||||||
|
ArrayList<FuncFParam> paramList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i += 2) {
|
||||||
|
paramList.add((FuncFParam) getChild(i));
|
||||||
|
}
|
||||||
|
return paramList;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
frontend/ast/func/FuncRParams.java
Normal file
57
frontend/ast/func/FuncRParams.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import error.Errors;
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.exp.Exp;
|
||||||
|
import midend.symbol.FuncSymbol;
|
||||||
|
|
||||||
|
public class FuncRParams extends Node {
|
||||||
|
public FuncRParams(TokenStream ts) {
|
||||||
|
super(SyntaxType.FUNC_REAL_PARAM_S, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
while (true) {
|
||||||
|
Exp ep = new Exp(ts);
|
||||||
|
ep.parse(errors);
|
||||||
|
addChild(ep);
|
||||||
|
if (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
addChild(new TokenNode(ts)); // comma
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParamNum() {
|
||||||
|
return (getChildren().size() + 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkParamType(FuncSymbol funcSymbol, Errors errors, int line) {
|
||||||
|
int fparaNum = funcSymbol.getParamNum();
|
||||||
|
int rparaNum = getParamNum();
|
||||||
|
int size = rparaNum < fparaNum ? rparaNum : fparaNum;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
Exp exp = (Exp) getChild(i * 2);
|
||||||
|
if (exp.getType() != funcSymbol.getParamType(i)) {
|
||||||
|
errors.addError(new Error(line, ErrorType.e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Exp> getParamList() {
|
||||||
|
ArrayList<Exp> paramList = new ArrayList<Exp>();
|
||||||
|
for (int i = 0; i < getChildren().size(); i += 2) {
|
||||||
|
paramList.add((Exp) getChild(i));
|
||||||
|
}
|
||||||
|
return paramList;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
frontend/ast/func/FuncType.java
Normal file
27
frontend/ast/func/FuncType.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class FuncType extends Node {
|
||||||
|
public FuncType(TokenStream ts) {
|
||||||
|
super(SyntaxType.FUNC_TYPE, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode ident = new TokenNode(this.ts);
|
||||||
|
addChild(ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVoid() {
|
||||||
|
return ((TokenNode) getChild(0)).getType() == TokenType.VOIDTK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInt() {
|
||||||
|
return ((TokenNode) getChild(0)).getType() == TokenType.INTTK;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
frontend/ast/func/MainFuncDef.java
Normal file
60
frontend/ast/func/MainFuncDef.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package frontend.ast.func;
|
||||||
|
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
import error.Error;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.block.BlockItem;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.block.Block;
|
||||||
|
|
||||||
|
public class MainFuncDef extends Node {
|
||||||
|
public MainFuncDef(TokenStream ts) {
|
||||||
|
super(SyntaxType.MAIN_FUNC_DEF, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
TokenNode intkk = new TokenNode(this.ts);
|
||||||
|
addChild(intkk);
|
||||||
|
TokenNode mainkk = new TokenNode(this.ts);
|
||||||
|
addChild(mainkk);
|
||||||
|
TokenNode lparent = new TokenNode(this.ts);
|
||||||
|
addChild(lparent);
|
||||||
|
if (getCurrToken().getType() != TokenType.RPARENT) {
|
||||||
|
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
|
||||||
|
} else {
|
||||||
|
TokenNode rparent = new TokenNode(this.ts);
|
||||||
|
addChild(rparent);
|
||||||
|
}
|
||||||
|
Block block = new Block(this.ts);
|
||||||
|
block.setIsFuncBlock(true);
|
||||||
|
block.parse(errors);
|
||||||
|
addChild(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkReturnNode(Errors errors) {
|
||||||
|
Block block = (Block) getChild(getChildren().size() - 1);
|
||||||
|
TokenNode rbrace = (TokenNode) block.getChild(block.getChildren().size() - 1);
|
||||||
|
if (block.getChildren().size() == 2) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
BlockItem bit = (BlockItem) block.getChild(block.getChildren().size() - 2);
|
||||||
|
if (bit.getChild(0) instanceof Decl) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
if (!(bit.getChild(0).getChild(0) instanceof TokenNode)) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
} else {
|
||||||
|
TokenNode returnNode = (TokenNode) bit.getChild(0).getChild(0);
|
||||||
|
if (returnNode.getType() != TokenType.RETURNTK) {
|
||||||
|
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
frontend/ast/token/TokenNode.java
Normal file
50
frontend/ast/token/TokenNode.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package frontend.ast.token;
|
||||||
|
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.Token;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class TokenNode extends Node {
|
||||||
|
private Token token;
|
||||||
|
|
||||||
|
public TokenNode(TokenStream ts) {
|
||||||
|
super(SyntaxType.TOKEN, ts);
|
||||||
|
token = ts.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return token.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return token.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return token.getLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return token.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenType getType() {
|
||||||
|
return token.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFormatNum() {
|
||||||
|
int num = 0;
|
||||||
|
String str = token.getValue();
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
if (str.charAt(i) == '%' && i + 1 < str.length()
|
||||||
|
&& str.charAt(i + 1) == 'd') {
|
||||||
|
num++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
frontend/ast/val/ConstInitVal.java
Normal file
58
frontend/ast/val/ConstInitVal.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package frontend.ast.val;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.ast.exp.ConstExp;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
|
||||||
|
public class ConstInitVal extends Node {
|
||||||
|
public ConstInitVal(TokenStream ts) {
|
||||||
|
super(SyntaxType.CONST_INIT_VAL, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() != TokenType.LBRACE) {
|
||||||
|
ConstExp cep = new ConstExp(this.ts);
|
||||||
|
cep.parse(errors);
|
||||||
|
addChild(cep);
|
||||||
|
} else {
|
||||||
|
TokenNode lbrace = new TokenNode(this.ts);
|
||||||
|
addChild(lbrace);
|
||||||
|
if (getCurrToken().getType() != TokenType.RBRACE) {
|
||||||
|
while (true) { // judge rbrace or not ??
|
||||||
|
ConstExp cep = new ConstExp(this.ts);
|
||||||
|
cep.parse(errors);
|
||||||
|
addChild(cep);
|
||||||
|
if (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
TokenNode comma = new TokenNode(this.ts);
|
||||||
|
addChild(comma);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenNode rbrace = new TokenNode(this.ts);
|
||||||
|
addChild(rbrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Integer> getValue() {
|
||||||
|
ArrayList<Integer> valueList = new ArrayList<>();
|
||||||
|
if (getChild(0) instanceof ConstExp) {
|
||||||
|
valueList.add(((ConstExp) getChild(0)).getValue());
|
||||||
|
return valueList;
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i < getChildren().size(); i += 2) {
|
||||||
|
if (getChild(i) instanceof ConstExp) {
|
||||||
|
valueList.add(((ConstExp) getChild(i)).getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valueList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
frontend/ast/val/InitVal.java
Normal file
71
frontend/ast/val/InitVal.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package frontend.ast.val;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
import frontend.ast.Node;
|
||||||
|
import frontend.ast.SyntaxType;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
import frontend.lexer.TokenType;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.ast.exp.Exp;
|
||||||
|
|
||||||
|
public class InitVal extends Node {
|
||||||
|
public InitVal(TokenStream ts) {
|
||||||
|
super(SyntaxType.INIT_VAL, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
if (getCurrToken().getType() == TokenType.LBRACE) {
|
||||||
|
TokenNode lbrace = new TokenNode(this.ts);
|
||||||
|
addChild(lbrace);
|
||||||
|
if (getCurrToken().getType() != TokenType.RBRACE) {
|
||||||
|
while (true) {
|
||||||
|
Exp ep = new Exp(this.ts);
|
||||||
|
ep.parse(errors);
|
||||||
|
addChild(ep);
|
||||||
|
if (getCurrToken().getType() == TokenType.COMMA) {
|
||||||
|
TokenNode comma = new TokenNode(this.ts);
|
||||||
|
addChild(comma);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenNode rbrace = new TokenNode(this.ts);
|
||||||
|
addChild(rbrace);
|
||||||
|
} else {
|
||||||
|
Exp ep = new Exp(this.ts);
|
||||||
|
ep.parse(errors);
|
||||||
|
addChild(ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Integer> getValue() {
|
||||||
|
ArrayList<Integer> values = new ArrayList<>();
|
||||||
|
if (getChild(0) instanceof Exp) {
|
||||||
|
values.add(((Exp) getChild(0)).getValue());
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i < getChildren().size(); i += 2) {
|
||||||
|
if (getChild(i) instanceof Exp) {
|
||||||
|
values.add(((Exp) getChild(i)).getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Exp> getExpList() {
|
||||||
|
ArrayList<Exp> expList = new ArrayList<>();
|
||||||
|
if (getChild(0) instanceof Exp) {
|
||||||
|
expList.add((Exp) getChild(0));
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i < getChildren().size(); i += 2) {
|
||||||
|
if (getChild(i) instanceof Exp) {
|
||||||
|
expList.add((Exp) getChild(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expList;
|
||||||
|
}
|
||||||
|
}
|
||||||
245
frontend/lexer/Lexer.java
Normal file
245
frontend/lexer/Lexer.java
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
package frontend.lexer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Lexer {
|
||||||
|
private String input;
|
||||||
|
private ArrayList<Token> tokens;
|
||||||
|
private int position;
|
||||||
|
private int line;
|
||||||
|
private char currentChar;
|
||||||
|
|
||||||
|
public Lexer(String input) {
|
||||||
|
this.input = input;
|
||||||
|
this.tokens = new ArrayList<Token>();
|
||||||
|
this.position = 0;
|
||||||
|
this.line = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lex(Errors errors) {
|
||||||
|
int sigComment = 0;
|
||||||
|
while (this.position < this.input.length()) {
|
||||||
|
currentChar = this.input.charAt(this.position);
|
||||||
|
if (currentChar == ' ' || currentChar == '\t') {
|
||||||
|
this.position++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (currentChar == '\n' || currentChar == '\r') {
|
||||||
|
if (currentChar == '\r') {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '\n') {
|
||||||
|
this.position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.line++;
|
||||||
|
this.position++;
|
||||||
|
if (sigComment == 1) {
|
||||||
|
sigComment = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sigComment == 0) {
|
||||||
|
if (currentChar == '/') {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '/') {
|
||||||
|
sigComment = 1;
|
||||||
|
this.position += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '*') {
|
||||||
|
sigComment = 2;
|
||||||
|
this.position += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isIntCons()) {
|
||||||
|
lexInt();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.isStrCons()) {
|
||||||
|
lexStr();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.isIdenfr()) {
|
||||||
|
lexIdenfr();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lexOp(errors);
|
||||||
|
}
|
||||||
|
if (sigComment == 2) {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.currentChar == '*' && this.input.charAt(this.position + 1) == '/') {
|
||||||
|
sigComment = 0;
|
||||||
|
this.position += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sigComment != 0) {
|
||||||
|
this.position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIntCons() {
|
||||||
|
return Character.isDigit(this.currentChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStrCons() {
|
||||||
|
return this.currentChar == '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIdenfr() {
|
||||||
|
return Character.isLowerCase(this.currentChar) || Character.isUpperCase(this.currentChar)
|
||||||
|
|| this.currentChar == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotWp() {
|
||||||
|
return !Character.isWhitespace(this.currentChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOp() {
|
||||||
|
return !this.isIntCons() && !this.isStrCons() && !this.isIdenfr();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lexInt() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (this.position < this.input.length() && this.isIntCons()) {
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
this.position++;
|
||||||
|
updateCurrentChar();
|
||||||
|
}
|
||||||
|
this.tokens.add(new Token(sb.toString(), this.line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lexStr() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
this.position++;
|
||||||
|
updateCurrentChar();
|
||||||
|
while (this.position < this.input.length() && this.currentChar != '"') {
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
this.position++;
|
||||||
|
updateCurrentChar();
|
||||||
|
}
|
||||||
|
if (this.position < this.input.length() && this.currentChar == '"') {
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
this.position++;
|
||||||
|
}
|
||||||
|
this.tokens.add(new Token(sb.toString(), this.line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lexIdenfr() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (this.position < this.input.length() && (this.isIdenfr() || this.isIntCons())) {
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
this.position++;
|
||||||
|
updateCurrentChar();
|
||||||
|
}
|
||||||
|
this.tokens.add(new Token(sb.toString(), this.line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lexOp(Errors errors) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (this.currentChar == '/' && this.position + 1 < this.input.length() &&
|
||||||
|
(this.input.charAt(this.position + 1) == '/' ||
|
||||||
|
this.input.charAt(this.position + 1) == '*')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sb.append(this.currentChar);
|
||||||
|
switch (this.currentChar) {
|
||||||
|
case '&':
|
||||||
|
readAnd(sb);
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
readOr(sb);
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
readEq(sb);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
readEq(sb);
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
readEq(sb);
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
readEq(sb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.position++;
|
||||||
|
if (sb.toString().equals("&") || sb.toString().equals("|")) {
|
||||||
|
errors.addError(new Error(this.line, ErrorType.a));
|
||||||
|
}
|
||||||
|
this.tokens.add(new Token(sb.toString(), this.line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readAnd(StringBuilder sb) {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '&') {
|
||||||
|
this.position++;
|
||||||
|
currentChar = this.input.charAt(this.position);
|
||||||
|
sb.append(currentChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readOr(StringBuilder sb) {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '|') {
|
||||||
|
this.position++;
|
||||||
|
currentChar = this.input.charAt(this.position);
|
||||||
|
sb.append(currentChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readEq(StringBuilder sb) {
|
||||||
|
if (this.position + 1 < this.input.length() &&
|
||||||
|
this.input.charAt(this.position + 1) == '=') {
|
||||||
|
this.position++;
|
||||||
|
currentChar = this.input.charAt(this.position);
|
||||||
|
sb.append(currentChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateCurrentChar() {
|
||||||
|
if (this.position < this.input.length()) {
|
||||||
|
currentChar = this.input.charAt(this.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printTokens() {
|
||||||
|
for (Token token : this.tokens) {
|
||||||
|
token.adjustType();
|
||||||
|
System.out.println(token.getType() + " " + token.getValue() + " " + token.getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToFile(String fileName) {
|
||||||
|
try {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Token token : this.tokens) {
|
||||||
|
token.adjustType();
|
||||||
|
sb.append(token.toString());
|
||||||
|
}
|
||||||
|
Files.write(Paths.get(fileName), sb.toString().getBytes());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Token> getTokens() {
|
||||||
|
for (Token token : this.tokens) {
|
||||||
|
token.adjustType();
|
||||||
|
}
|
||||||
|
return this.tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
frontend/lexer/Token.java
Normal file
42
frontend/lexer/Token.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package frontend.lexer;
|
||||||
|
|
||||||
|
public class Token {
|
||||||
|
private TokenType type;
|
||||||
|
private String value;
|
||||||
|
private int line;
|
||||||
|
|
||||||
|
public Token(String value, int line) {
|
||||||
|
this.value = value;
|
||||||
|
this.type = TokenType.isWhatType(value);
|
||||||
|
this.line = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void adjustType() {
|
||||||
|
if (this.type == TokenType.IDENFR) {
|
||||||
|
if (this.value.charAt(0) == '\"' &&
|
||||||
|
this.value.charAt(this.value.length() - 1) == '\"') {
|
||||||
|
this.type = TokenType.STRCON;
|
||||||
|
}
|
||||||
|
String regex = "^\\d+$";
|
||||||
|
if (this.value.matches(regex)) {
|
||||||
|
this.type = TokenType.INTCON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenType getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return this.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.type + " " + this.value + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
42
frontend/lexer/TokenStream.java
Normal file
42
frontend/lexer/TokenStream.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package frontend.lexer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class TokenStream {
|
||||||
|
private ArrayList<Token> tokens;
|
||||||
|
private int currentIndex;
|
||||||
|
|
||||||
|
public TokenStream(ArrayList<Token> tokens) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token read() {
|
||||||
|
if (currentIndex < tokens.size()) {
|
||||||
|
return tokens.get(currentIndex++);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recall() {
|
||||||
|
if (currentIndex > 0) {
|
||||||
|
currentIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentIndex() {
|
||||||
|
return currentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetIndex(int index) {
|
||||||
|
currentIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token peek(int step) {
|
||||||
|
if (currentIndex + step < tokens.size()) {
|
||||||
|
return tokens.get(currentIndex + step);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
123
frontend/lexer/TokenType.java
Normal file
123
frontend/lexer/TokenType.java
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package frontend.lexer;
|
||||||
|
|
||||||
|
public enum TokenType {
|
||||||
|
IDENFR,
|
||||||
|
INTCON,
|
||||||
|
STRCON,
|
||||||
|
CONSTTK,
|
||||||
|
INTTK,
|
||||||
|
STATICTK,
|
||||||
|
BREAKTK,
|
||||||
|
CONTINUETK,
|
||||||
|
IFTK,
|
||||||
|
MAINTK,
|
||||||
|
ELSETK,
|
||||||
|
NOT,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
FORTK,
|
||||||
|
RETURNTK,
|
||||||
|
VOIDTK,
|
||||||
|
PLUS,
|
||||||
|
MINU,
|
||||||
|
PRINTFTK,
|
||||||
|
MULT,
|
||||||
|
DIV,
|
||||||
|
MOD,
|
||||||
|
LSS,
|
||||||
|
LEQ,
|
||||||
|
GRE,
|
||||||
|
GEQ,
|
||||||
|
EQL,
|
||||||
|
NEQ,
|
||||||
|
SEMICN,
|
||||||
|
COMMA,
|
||||||
|
LPARENT,
|
||||||
|
RPARENT,
|
||||||
|
LBRACK,
|
||||||
|
RBRACK,
|
||||||
|
LBRACE,
|
||||||
|
RBRACE,
|
||||||
|
ASSIGN;
|
||||||
|
|
||||||
|
public static TokenType isWhatType(String str) {
|
||||||
|
switch (str) {
|
||||||
|
case "const":
|
||||||
|
return TokenType.CONSTTK;
|
||||||
|
case "int":
|
||||||
|
return TokenType.INTTK;
|
||||||
|
case "static":
|
||||||
|
return TokenType.STATICTK;
|
||||||
|
case "break":
|
||||||
|
return TokenType.BREAKTK;
|
||||||
|
case "continue":
|
||||||
|
return TokenType.CONTINUETK;
|
||||||
|
case "if":
|
||||||
|
return TokenType.IFTK;
|
||||||
|
case "main":
|
||||||
|
return TokenType.MAINTK;
|
||||||
|
case "else":
|
||||||
|
return TokenType.ELSETK;
|
||||||
|
case "!":
|
||||||
|
return TokenType.NOT;
|
||||||
|
case "&&":
|
||||||
|
return TokenType.AND;
|
||||||
|
case "&":
|
||||||
|
return TokenType.AND;
|
||||||
|
case "||":
|
||||||
|
return TokenType.OR;
|
||||||
|
case "|":
|
||||||
|
return TokenType.OR;
|
||||||
|
case "for":
|
||||||
|
return TokenType.FORTK;
|
||||||
|
case "return":
|
||||||
|
return TokenType.RETURNTK;
|
||||||
|
case "void":
|
||||||
|
return TokenType.VOIDTK;
|
||||||
|
case "+":
|
||||||
|
return TokenType.PLUS;
|
||||||
|
case "-":
|
||||||
|
return TokenType.MINU;
|
||||||
|
case "printf":
|
||||||
|
return TokenType.PRINTFTK;
|
||||||
|
case "*":
|
||||||
|
return TokenType.MULT;
|
||||||
|
case "/":
|
||||||
|
return TokenType.DIV;
|
||||||
|
case "%":
|
||||||
|
return TokenType.MOD;
|
||||||
|
case "<":
|
||||||
|
return TokenType.LSS;
|
||||||
|
case "<=":
|
||||||
|
return TokenType.LEQ;
|
||||||
|
case ">":
|
||||||
|
return TokenType.GRE;
|
||||||
|
case ">=":
|
||||||
|
return TokenType.GEQ;
|
||||||
|
case "==":
|
||||||
|
return TokenType.EQL;
|
||||||
|
case "!=":
|
||||||
|
return TokenType.NEQ;
|
||||||
|
case ";":
|
||||||
|
return TokenType.SEMICN;
|
||||||
|
case ",":
|
||||||
|
return TokenType.COMMA;
|
||||||
|
case "(":
|
||||||
|
return TokenType.LPARENT;
|
||||||
|
case ")":
|
||||||
|
return TokenType.RPARENT;
|
||||||
|
case "[":
|
||||||
|
return TokenType.LBRACK;
|
||||||
|
case "]":
|
||||||
|
return TokenType.RBRACK;
|
||||||
|
case "{":
|
||||||
|
return TokenType.LBRACE;
|
||||||
|
case "}":
|
||||||
|
return TokenType.RBRACE;
|
||||||
|
case "=":
|
||||||
|
return TokenType.ASSIGN;
|
||||||
|
default:
|
||||||
|
return TokenType.IDENFR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
frontend/parser/Parser.java
Normal file
38
frontend/parser/Parser.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package frontend.parser;
|
||||||
|
|
||||||
|
import frontend.ast.CompUnit;
|
||||||
|
import frontend.lexer.TokenStream;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
private TokenStream ts;
|
||||||
|
private CompUnit compUnit;
|
||||||
|
|
||||||
|
public Parser(TokenStream ts) {
|
||||||
|
this.ts = ts;
|
||||||
|
this.compUnit = new CompUnit(this.ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(Errors errors) {
|
||||||
|
compUnit.parse(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompUnit getCompUnit() {
|
||||||
|
return compUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToFile(String fileName) {
|
||||||
|
try {
|
||||||
|
String info = this.compUnit.getInfo();
|
||||||
|
Files.write(Paths.get(fileName), info.getBytes());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
midend/Midend.java
Normal file
31
midend/Midend.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package midend;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import frontend.ast.CompUnit;
|
||||||
|
import midend.llvm.IrBuilder;
|
||||||
|
import midend.llvm.IrModule;
|
||||||
|
import midend.visit.Visitor;
|
||||||
|
|
||||||
|
public class Midend {
|
||||||
|
private IrModule module;
|
||||||
|
private Visitor visitor;
|
||||||
|
|
||||||
|
public Midend(CompUnit compUnit) {
|
||||||
|
this.module = new IrModule();
|
||||||
|
this.visitor = new Visitor(compUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateLLvmIr() {
|
||||||
|
IrBuilder.setCurrentModule(module);
|
||||||
|
visitor.visit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToFile(String fileName) {
|
||||||
|
try {
|
||||||
|
Files.write(Paths.get(fileName), module.toString().getBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
midend/errorhandle/ErrorHandler.java
Normal file
32
midend/errorhandle/ErrorHandler.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package midend.errorhandle;
|
||||||
|
|
||||||
|
import frontend.ast.CompUnit;
|
||||||
|
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class ErrorHandler {
|
||||||
|
private CompUnit compUnit;
|
||||||
|
|
||||||
|
public ErrorHandler(CompUnit compUnit) {
|
||||||
|
this.compUnit = compUnit;
|
||||||
|
SymbolManager.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visit(Errors errors) {
|
||||||
|
compUnit.fillSymbolTable(false, false, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToFile(String fileName) {
|
||||||
|
try {
|
||||||
|
String info = SymbolManager.getSymbolTableInfo();
|
||||||
|
Files.write(Paths.get(fileName), info.getBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
143
midend/llvm/IrBuilder.java
Normal file
143
midend/llvm/IrBuilder.java
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package midend.llvm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrFuncValue;
|
||||||
|
import midend.llvm.value.IrBasicBlock;
|
||||||
|
import midend.llvm.value.IrLoop;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.constant.IrConstant;
|
||||||
|
import midend.llvm.value.IrGlobalValue;
|
||||||
|
import midend.llvm.constant.IrConstantStr;
|
||||||
|
import midend.llvm.instr.IrInstr;
|
||||||
|
|
||||||
|
public class IrBuilder {
|
||||||
|
private static final String prebb = "b_";
|
||||||
|
private static final String prestr = "@s_";
|
||||||
|
private static final String prefunc = "@f_";
|
||||||
|
private static final String preglobal = "@g_";
|
||||||
|
private static final String prelocal = "%v_";
|
||||||
|
|
||||||
|
private static IrModule module = null;
|
||||||
|
private static IrFuncValue currentFunc = null;
|
||||||
|
private static IrBasicBlock currentBB = null;
|
||||||
|
private static int strId = 0;
|
||||||
|
private static int globalId = 0;
|
||||||
|
private static int bblockId = 0;
|
||||||
|
private static HashMap<IrFuncValue, Integer> funcIdMap = new HashMap<>(); // func, localId
|
||||||
|
private static Stack<IrLoop> loopStack = new Stack<>();
|
||||||
|
|
||||||
|
public static void setCurrentModule(IrModule module) {
|
||||||
|
IrBuilder.module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewFunc(String name, IrType retType) {
|
||||||
|
IrFuncValue func = new IrFuncValue(geFuncName(name), retType);
|
||||||
|
module.addFunc(func);
|
||||||
|
funcIdMap.put(func, 0);
|
||||||
|
currentFunc = func;
|
||||||
|
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||||
|
func.addBBlock(entryBB);
|
||||||
|
currentBB = entryBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewFunc(IrFuncValue func) {
|
||||||
|
module.addFunc(func);
|
||||||
|
funcIdMap.put(func, 0);
|
||||||
|
currentFunc = func;
|
||||||
|
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||||
|
func.addBBlock(entryBB);
|
||||||
|
currentBB = entryBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewBB() {
|
||||||
|
IrBasicBlock bb = new IrBasicBlock(getBlockName(), currentFunc);
|
||||||
|
currentFunc.addBBlock(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewBB(IrBasicBlock bb) {
|
||||||
|
currentFunc.addBBlock(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCurrentBBlock(IrBasicBlock bb) {
|
||||||
|
currentBB = bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewGlobal(IrType type, boolean isConstant, IrConstant initVal) {
|
||||||
|
IrGlobalValue global = new IrGlobalValue(type, getGlobalName(), isConstant, initVal);
|
||||||
|
module.addGlobalVar(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewGlobal(IrGlobalValue global) {
|
||||||
|
module.addGlobalVar(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewStr(String str) {
|
||||||
|
if (module.containStr(str)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
module.addStr(new IrConstantStr(str, getStrName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNewStr(IrConstantStr str) {
|
||||||
|
module.addStr(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addInstr(IrInstr instr) {
|
||||||
|
currentBB.addInstr(instr);
|
||||||
|
instr.setBBlock(currentBB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String geFuncName(String name) {
|
||||||
|
return name.equals("main") ? "@main" : prefunc + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBlockName() {
|
||||||
|
return prebb + bblockId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getStrName() {
|
||||||
|
return prestr + strId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getGlobalName() {
|
||||||
|
return preglobal + globalId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLocalName() {
|
||||||
|
int id = funcIdMap.get(currentFunc);
|
||||||
|
funcIdMap.put(currentFunc, id + 1);
|
||||||
|
return prelocal + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLocalName(IrFuncValue func) {
|
||||||
|
int id = funcIdMap.get(func);
|
||||||
|
funcIdMap.put(func, id + 1);
|
||||||
|
return prelocal + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrModule getCurrentModule() {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrFuncValue getCurrentFunc() {
|
||||||
|
return currentFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrBasicBlock getCurrentBB() {
|
||||||
|
return currentBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pushLoop(IrLoop loop) {
|
||||||
|
loopStack.push(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrLoop popLoop() {
|
||||||
|
return loopStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrLoop getCurrentLoop() {
|
||||||
|
return loopStack.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
100
midend/llvm/IrModule.java
Normal file
100
midend/llvm/IrModule.java
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package midend.llvm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import midend.llvm.constant.IrConstantStr;
|
||||||
|
import midend.llvm.value.IrFuncValue;
|
||||||
|
import midend.llvm.value.IrGlobalValue;
|
||||||
|
import midend.llvm.instr.GetIntInstr;
|
||||||
|
import midend.llvm.instr.PutChInstr;
|
||||||
|
import midend.llvm.instr.PutIntInstr;
|
||||||
|
import midend.llvm.instr.PutStrInstr;
|
||||||
|
|
||||||
|
public class IrModule {
|
||||||
|
private ArrayList<String> decls;
|
||||||
|
private HashMap<String, IrConstantStr> strs;
|
||||||
|
private ArrayList<IrGlobalValue> globalVars;
|
||||||
|
private ArrayList<IrFuncValue> funcs;
|
||||||
|
|
||||||
|
public IrModule() {
|
||||||
|
decls = new ArrayList<>();
|
||||||
|
strs = new HashMap<>();
|
||||||
|
globalVars = new ArrayList<>();
|
||||||
|
funcs = new ArrayList<>();
|
||||||
|
decls.add(GetIntInstr.getIntDecl());
|
||||||
|
decls.add(PutChInstr.putChDecl());
|
||||||
|
decls.add(PutIntInstr.putIntDecl());
|
||||||
|
decls.add(PutStrInstr.putStrDecl());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getDecls() {
|
||||||
|
return decls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, IrConstantStr> getStrs() {
|
||||||
|
return strs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrGlobalValue> getGlobalVars() {
|
||||||
|
return globalVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrFuncValue> getFuncs() {
|
||||||
|
return funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFunc(IrFuncValue func) {
|
||||||
|
funcs.add(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addStr(IrConstantStr str) {
|
||||||
|
if (strs.containsKey(str.getValue())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strs.put(str.getValue(), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containStr(String str) {
|
||||||
|
return strs.containsKey(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrConstantStr getStr(String str) {
|
||||||
|
if (containStr(str)) {
|
||||||
|
return strs.get(str);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addGlobalVar(IrGlobalValue globalVar) {
|
||||||
|
globalVars.add(globalVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrFuncValue getMainFunc() {
|
||||||
|
for (IrFuncValue func : funcs) {
|
||||||
|
if (func.isMain()) {
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: toString()方法编写
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String decl : decls) {
|
||||||
|
sb.append(decl).append("\n");
|
||||||
|
}
|
||||||
|
for (IrConstantStr str : strs.values()) {
|
||||||
|
sb.append(str.toString()).append("\n");
|
||||||
|
}
|
||||||
|
for (IrGlobalValue globalVar : globalVars) {
|
||||||
|
sb.append(globalVar.toString()).append("\n");
|
||||||
|
}
|
||||||
|
for (IrFuncValue func : funcs) {
|
||||||
|
sb.append(func.toString()).append("\n");
|
||||||
|
}
|
||||||
|
// System.out.println(funcs.size());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
midend/llvm/constant/IrConstant.java
Normal file
14
midend/llvm/constant/IrConstant.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package midend.llvm.constant;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
|
||||||
|
public class IrConstant extends IrValue {
|
||||||
|
public IrConstant(IrType type, String name) {
|
||||||
|
super(type, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
47
midend/llvm/constant/IrConstantArray.java
Normal file
47
midend/llvm/constant/IrConstantArray.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package midend.llvm.constant;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.type.IrArrayType;
|
||||||
|
|
||||||
|
public class IrConstantArray extends IrConstant {
|
||||||
|
private ArrayList<IrConstant> elements;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public IrConstantArray(String name, ArrayList<IrConstant> elements, int size) {
|
||||||
|
super(new IrArrayType(IrInterType.INT32, size), name);
|
||||||
|
this.elements = elements == null ? new ArrayList<>() : new ArrayList<>(elements);
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrConstant> getElements() {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getType().toString() + " ");
|
||||||
|
if (elements.size() == 0) {
|
||||||
|
sb.append("zeroinitializer");
|
||||||
|
} else {
|
||||||
|
sb.append("[");
|
||||||
|
for (IrConstant element : elements) {
|
||||||
|
sb.append(element.toString());
|
||||||
|
if (element != elements.get(elements.size() - 1)) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int left = size - elements.size();
|
||||||
|
for (int i = 0; i < left; i++) {
|
||||||
|
sb.append(", i32 0");
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
midend/llvm/constant/IrConstantInt.java
Normal file
20
midend/llvm/constant/IrConstantInt.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package midend.llvm.constant;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class IrConstantInt extends IrConstant {
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public IrConstantInt(int value) {
|
||||||
|
super(IrInterType.INT32, value + "");
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "i32 " + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
midend/llvm/constant/IrConstantStr.java
Normal file
53
midend/llvm/constant/IrConstantStr.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package midend.llvm.constant;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrArrayType;
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class IrConstantStr extends IrConstant {
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public IrConstantStr(String value, String name) {
|
||||||
|
super(new IrPointerType(
|
||||||
|
new IrArrayType(IrInterType.INT8, getLen(value) + 1)), name);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getLen(String value) {
|
||||||
|
int len = 0;
|
||||||
|
for (int i = 0; i < value.length(); i++) {
|
||||||
|
if (value.charAt(i) == '\\') {
|
||||||
|
i++;
|
||||||
|
} else if (value.charAt(i) == '"') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRealStr(String str) {
|
||||||
|
boolean start = str.charAt(0) == '"';
|
||||||
|
boolean end = str.charAt(str.length() - 1) == '"';
|
||||||
|
if (start && end) {
|
||||||
|
return str.substring(1, str.length() - 1);
|
||||||
|
} else if (start) {
|
||||||
|
return str.substring(1);
|
||||||
|
} else if (end) {
|
||||||
|
return str.substring(0, str.length() - 1);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getName() + " = constant " + ((IrPointerType) getType()).getPointeeType());
|
||||||
|
sb.append(" c\"" + getRealStr(value).replace("\\n", "\\0A"));
|
||||||
|
sb.append("\\00\"");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
21
midend/llvm/instr/AllocateInstr.java
Normal file
21
midend/llvm/instr/AllocateInstr.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
|
||||||
|
public class AllocateInstr extends IrInstr {
|
||||||
|
private IrType pointeeType;
|
||||||
|
|
||||||
|
public AllocateInstr(IrType pointeeType, String name) { // name即为局部变量的name,因为要声明一个局部变量
|
||||||
|
super(new IrPointerType(pointeeType), name, IrInstrType.ALLOCA);
|
||||||
|
this.pointeeType = pointeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getPointeeType() {
|
||||||
|
return pointeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = alloca " + this.pointeeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
midend/llvm/instr/AluInstr.java
Normal file
24
midend/llvm/instr/AluInstr.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class AluInstr extends IrInstr {
|
||||||
|
private AluType alutype;
|
||||||
|
|
||||||
|
public AluInstr(String name, String op, IrValue left, IrValue right) {
|
||||||
|
super(IrInterType.INT32, name, IrInstrType.ALU);
|
||||||
|
this.alutype = AluType.getAluType(op);
|
||||||
|
addUse(left);
|
||||||
|
addUse(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AluType getAluType() {
|
||||||
|
return alutype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = " + alutype.toString() + " " + getType()
|
||||||
|
+ " " + getUse(0).getName() + ", " + getUse(1).getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
53
midend/llvm/instr/AluType.java
Normal file
53
midend/llvm/instr/AluType.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
public enum AluType {
|
||||||
|
ADD,
|
||||||
|
SUB,
|
||||||
|
MUL,
|
||||||
|
SDIV,
|
||||||
|
SREM,
|
||||||
|
AND,
|
||||||
|
OR;
|
||||||
|
|
||||||
|
public static AluType getAluType(String op) {
|
||||||
|
switch (op) {
|
||||||
|
case "+":
|
||||||
|
return ADD;
|
||||||
|
case "-":
|
||||||
|
return SUB;
|
||||||
|
case "*":
|
||||||
|
return MUL;
|
||||||
|
case "/":
|
||||||
|
return SDIV;
|
||||||
|
case "%":
|
||||||
|
return SREM;
|
||||||
|
case "&":
|
||||||
|
return AND;
|
||||||
|
case "|":
|
||||||
|
return OR;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
switch (this) {
|
||||||
|
case ADD:
|
||||||
|
return "add";
|
||||||
|
case SUB:
|
||||||
|
return "sub";
|
||||||
|
case MUL:
|
||||||
|
return "mul";
|
||||||
|
case SDIV:
|
||||||
|
return "sdiv";
|
||||||
|
case SREM:
|
||||||
|
return "srem";
|
||||||
|
case AND:
|
||||||
|
return "and";
|
||||||
|
case OR:
|
||||||
|
return "or";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
midend/llvm/instr/BranchInstr.java
Normal file
33
midend/llvm/instr/BranchInstr.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrBasicBlock;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class BranchInstr extends IrInstr {
|
||||||
|
public BranchInstr(String name, IrValue cond, IrBasicBlock trueBB, IrBasicBlock falseBB) {
|
||||||
|
super(IrInterType.VOID, name, IrInstrType.BR);
|
||||||
|
addUse(cond);
|
||||||
|
addUse(trueBB);
|
||||||
|
addUse(falseBB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getCond() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getTrueBB() {
|
||||||
|
return (IrBasicBlock) getUse(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getFalseBB() {
|
||||||
|
return (IrBasicBlock) getUse(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "br i1 " + getCond().getName() +
|
||||||
|
", label %" + getTrueBB().getName() +
|
||||||
|
", label %" + getFalseBB().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
midend/llvm/instr/CallInstr.java
Normal file
48
midend/llvm/instr/CallInstr.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrFuncValue;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class CallInstr extends IrInstr {
|
||||||
|
public CallInstr(String name, IrFuncValue func, ArrayList<IrValue> args) {
|
||||||
|
super(func.getRetType(), name, IrInstrType.CALL);
|
||||||
|
addUse(func);
|
||||||
|
for (IrValue arg : args) {
|
||||||
|
addUse(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean callVoid() {
|
||||||
|
return getType().isVoid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrFuncValue getCalledFunc() {
|
||||||
|
return (IrFuncValue) getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrValue> getArgs() {
|
||||||
|
ArrayList<IrValue> args = new ArrayList<>();
|
||||||
|
for (int i = 1; i < getNumUses(); i++) {
|
||||||
|
args.add(getUse(i));
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (!callVoid()) {
|
||||||
|
sb.append(getName() + " = ");
|
||||||
|
}
|
||||||
|
sb.append("call " + getType() + " " + getCalledFunc().getName() + "(");
|
||||||
|
for (int i = 1; i < getNumUses(); i++) {
|
||||||
|
sb.append(getUse(i).getType() + " " + getUse(i).getName());
|
||||||
|
if (i < getNumUses() - 1) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
32
midend/llvm/instr/CmpInstr.java
Normal file
32
midend/llvm/instr/CmpInstr.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class CmpInstr extends IrInstr {
|
||||||
|
private CmpType cmpType;
|
||||||
|
|
||||||
|
public CmpInstr(String name, String op, IrValue lhs, IrValue rhs) {
|
||||||
|
super(IrInterType.BOOL, name, IrInstrType.CMP);
|
||||||
|
cmpType = CmpType.getCmpType(op);
|
||||||
|
addUse(lhs);
|
||||||
|
addUse(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CmpType getCmpType() {
|
||||||
|
return cmpType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getLhs() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getRhs() {
|
||||||
|
return getUse(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = " + "icmp " + cmpType.toString()
|
||||||
|
+ " i32 " + getLhs().getName() + ", " + getRhs().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
48
midend/llvm/instr/CmpType.java
Normal file
48
midend/llvm/instr/CmpType.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
public enum CmpType {
|
||||||
|
EQ,
|
||||||
|
NE,
|
||||||
|
SGT,
|
||||||
|
SGE,
|
||||||
|
SLT,
|
||||||
|
SLE;
|
||||||
|
|
||||||
|
public static CmpType getCmpType(String op) {
|
||||||
|
switch (op) {
|
||||||
|
case "==":
|
||||||
|
return EQ;
|
||||||
|
case "!=":
|
||||||
|
return NE;
|
||||||
|
case ">":
|
||||||
|
return SGT;
|
||||||
|
case ">=":
|
||||||
|
return SGE;
|
||||||
|
case "<":
|
||||||
|
return SLT;
|
||||||
|
case "<=":
|
||||||
|
return SLE;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
switch (this) {
|
||||||
|
case EQ:
|
||||||
|
return "eq";
|
||||||
|
case NE:
|
||||||
|
return "ne";
|
||||||
|
case SGT:
|
||||||
|
return "sgt";
|
||||||
|
case SGE:
|
||||||
|
return "sge";
|
||||||
|
case SLT:
|
||||||
|
return "slt";
|
||||||
|
case SLE:
|
||||||
|
return "sle";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
midend/llvm/instr/ExtendInstr.java
Normal file
31
midend/llvm/instr/ExtendInstr.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class ExtendInstr extends IrInstr {
|
||||||
|
private IrType targetType;
|
||||||
|
|
||||||
|
public ExtendInstr(String name, IrType targetType, IrValue src) {
|
||||||
|
super(targetType, name, IrInstrType.EXTEND);
|
||||||
|
this.targetType = targetType;
|
||||||
|
addUse(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getSrc() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getTargetType() {
|
||||||
|
return this.targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getSrcType() {
|
||||||
|
return getSrc().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = zext " + getSrc().getType()
|
||||||
|
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||||
|
}
|
||||||
|
}
|
||||||
57
midend/llvm/instr/GepInstr.java
Normal file
57
midend/llvm/instr/GepInstr.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrArrayType;
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class GepInstr extends IrInstr {
|
||||||
|
public GepInstr(IrValue pointer, IrValue offset, String name) {
|
||||||
|
super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP);
|
||||||
|
addUse(pointer);
|
||||||
|
addUse(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getPointer() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getOffset() {
|
||||||
|
return getUse(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
IrValue pointer = this.getPointer();
|
||||||
|
IrValue offset = this.getOffset();
|
||||||
|
|
||||||
|
IrPointerType pointerType = (IrPointerType) pointer.getType();
|
||||||
|
IrType targetType = pointerType.getPointeeType();
|
||||||
|
|
||||||
|
if (targetType instanceof IrArrayType arrayType) {
|
||||||
|
return getName() + " = getelementptr inbounds " +
|
||||||
|
arrayType + ", " +
|
||||||
|
pointerType + " " +
|
||||||
|
pointer.getName() + ", i32 0, " +
|
||||||
|
offset.getType() + " " +
|
||||||
|
offset.getName();
|
||||||
|
} else {
|
||||||
|
return getName() + " = getelementptr inbounds " +
|
||||||
|
targetType + ", " +
|
||||||
|
pointerType + " " +
|
||||||
|
pointer.getName() + ", " +
|
||||||
|
offset.getType() + " " +
|
||||||
|
offset.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrType getTargetType(IrValue pointer) {
|
||||||
|
IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType();
|
||||||
|
if (targetType instanceof IrArrayType arrayType) {
|
||||||
|
return arrayType.getElementType();
|
||||||
|
} else if (targetType instanceof IrPointerType pointerType) {
|
||||||
|
return pointerType.getPointeeType();
|
||||||
|
} else {
|
||||||
|
return targetType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
midend/llvm/instr/GetIntInstr.java
Normal file
17
midend/llvm/instr/GetIntInstr.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class GetIntInstr extends IrInstr {
|
||||||
|
public GetIntInstr(String name) {
|
||||||
|
super(IrInterType.INT32, name, IrInstrType.IO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = call i32 @getint()";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIntDecl() {
|
||||||
|
return "declare i32 @getint()";
|
||||||
|
}
|
||||||
|
}
|
||||||
28
midend/llvm/instr/IrInstr.java
Normal file
28
midend/llvm/instr/IrInstr.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.use.IrUser;
|
||||||
|
import midend.llvm.value.IrBasicBlock;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
|
||||||
|
public class IrInstr extends IrUser {
|
||||||
|
private IrInstrType type;
|
||||||
|
private IrBasicBlock block;
|
||||||
|
|
||||||
|
public IrInstr(IrType type, String name, IrInstrType instrType) {
|
||||||
|
super(type, name);
|
||||||
|
this.type = instrType;
|
||||||
|
this.block = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrInstrType getInstrType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getBBlock() {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBBlock(IrBasicBlock block) {
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
midend/llvm/instr/IrInstrType.java
Normal file
18
midend/llvm/instr/IrInstrType.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
public enum IrInstrType {
|
||||||
|
ALU,
|
||||||
|
CMP,
|
||||||
|
CALL,
|
||||||
|
ALLOCA,
|
||||||
|
LOAD,
|
||||||
|
STORE,
|
||||||
|
GEP,
|
||||||
|
PHI,
|
||||||
|
EXTEND,
|
||||||
|
TRUNC,
|
||||||
|
BR,
|
||||||
|
RET,
|
||||||
|
JUMP,
|
||||||
|
IO
|
||||||
|
}
|
||||||
20
midend/llvm/instr/JumpInstr.java
Normal file
20
midend/llvm/instr/JumpInstr.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrBasicBlock;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class JumpInstr extends IrInstr {
|
||||||
|
public JumpInstr(IrBasicBlock targetBlock) {
|
||||||
|
super(IrInterType.VOID, "jump", IrInstrType.JUMP);
|
||||||
|
addUse(targetBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getTargetBlock() {
|
||||||
|
return (IrBasicBlock) getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "br label " + "%" + getTargetBlock().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO:所有的指令的基本块设置还需完善
|
||||||
20
midend/llvm/instr/LoadInstr.java
Normal file
20
midend/llvm/instr/LoadInstr.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class LoadInstr extends IrInstr {
|
||||||
|
public LoadInstr(IrValue pointer, String name) {
|
||||||
|
super(((IrPointerType) pointer.getType()).getPointeeType(), name, IrInstrType.LOAD);
|
||||||
|
addUse(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getPointer() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = load " + getType() + ", "
|
||||||
|
+ getPointer().getType() + " " + getPointer().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
midend/llvm/instr/PutChInstr.java
Normal file
19
midend/llvm/instr/PutChInstr.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class PutChInstr extends IrInstr {
|
||||||
|
public PutChInstr(String name, IrValue putValue) {
|
||||||
|
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||||
|
addUse(putValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "call void @putch(i32 " + getUses().get(0).getName() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String putChDecl() {
|
||||||
|
return "declare void @putch(i32)";
|
||||||
|
}
|
||||||
|
}
|
||||||
19
midend/llvm/instr/PutIntInstr.java
Normal file
19
midend/llvm/instr/PutIntInstr.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class PutIntInstr extends IrInstr {
|
||||||
|
public PutIntInstr(String name, IrValue putValue) {
|
||||||
|
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||||
|
addUse(putValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "call void @putint(i32 " + getUses().get(0).getName() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String putIntDecl() {
|
||||||
|
return "declare void @putint(i32)";
|
||||||
|
}
|
||||||
|
}
|
||||||
26
midend/llvm/instr/PutStrInstr.java
Normal file
26
midend/llvm/instr/PutStrInstr.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.constant.IrConstantStr;
|
||||||
|
|
||||||
|
public class PutStrInstr extends IrInstr {
|
||||||
|
private IrConstantStr strVal;
|
||||||
|
|
||||||
|
public PutStrInstr(String name, IrConstantStr putValue) {
|
||||||
|
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||||
|
addUse(putValue);
|
||||||
|
strVal = putValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String putStrDecl() {
|
||||||
|
return "declare void @putstr(i8*)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
IrPointerType ptrType = (IrPointerType) strVal.getType();
|
||||||
|
return "call void @putstr(i8* getelementptr inbounds ("
|
||||||
|
+ ptrType.getPointeeType() + ", " + ptrType +
|
||||||
|
" " + strVal.getName() + ", i32 0, i32 0))";
|
||||||
|
}
|
||||||
|
}
|
||||||
20
midend/llvm/instr/ReturnInstr.java
Normal file
20
midend/llvm/instr/ReturnInstr.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class ReturnInstr extends IrInstr {
|
||||||
|
public ReturnInstr(IrValue retValue) {
|
||||||
|
super(IrInterType.VOID, "ret", IrInstrType.RET);
|
||||||
|
addUse(retValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getRetValue() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + (getRetValue() == null ? " void" :
|
||||||
|
" " + getRetValue().getType() + " " + getRetValue().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
25
midend/llvm/instr/StoreInstr.java
Normal file
25
midend/llvm/instr/StoreInstr.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
|
||||||
|
public class StoreInstr extends IrInstr {
|
||||||
|
public StoreInstr(IrValue value, IrValue pointer) {
|
||||||
|
super(IrInterType.VOID, "store", IrInstrType.STORE);
|
||||||
|
addUse(value);
|
||||||
|
addUse(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getValue() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getPointer() {
|
||||||
|
return getUse(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " " + getValue().getType() + " " + getValue().getName()
|
||||||
|
+ ", " + getPointer().getType() + " " + getPointer().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
31
midend/llvm/instr/TruncInstr.java
Normal file
31
midend/llvm/instr/TruncInstr.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package midend.llvm.instr;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class TruncInstr extends IrInstr {
|
||||||
|
private IrType targetType;
|
||||||
|
|
||||||
|
public TruncInstr(IrType targetType, IrValue value, String name) {
|
||||||
|
super(targetType, name, IrInstrType.TRUNC);
|
||||||
|
addUse(value);
|
||||||
|
this.targetType = targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getSrc() {
|
||||||
|
return getUse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getTargetType() {
|
||||||
|
return targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getSrcType() {
|
||||||
|
return getSrc().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " = trunc " + getSrcType()
|
||||||
|
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
midend/llvm/type/IrArrayType.java
Normal file
23
midend/llvm/type/IrArrayType.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
public class IrArrayType extends IrType {
|
||||||
|
private IrType elementType;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public IrArrayType(IrType elementType, int size) {
|
||||||
|
this.elementType = elementType;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getElementType() {
|
||||||
|
return elementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "[" + size + " x " + elementType.toString() + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
10
midend/llvm/type/IrBasicBlockType.java
Normal file
10
midend/llvm/type/IrBasicBlockType.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
public class IrBasicBlockType extends IrType {
|
||||||
|
public IrBasicBlockType() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
17
midend/llvm/type/IrFuncType.java
Normal file
17
midend/llvm/type/IrFuncType.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
public class IrFuncType extends IrType {
|
||||||
|
private IrType returnType;
|
||||||
|
|
||||||
|
public IrFuncType(IrType returnType) {
|
||||||
|
this.returnType = returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getReturnType() {
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return returnType.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
midend/llvm/type/IrInterType.java
Normal file
18
midend/llvm/type/IrInterType.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
public class IrInterType extends IrType {
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public IrInterType(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final IrInterType INT32 = new IrInterType(32);
|
||||||
|
public static final IrInterType INT8 = new IrInterType(8);
|
||||||
|
public static final IrInterType BOOL = new IrInterType(1);
|
||||||
|
public static final IrInterType VOID = new IrInterType(0);
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return size != 0 ? "i" + size : "void";
|
||||||
|
}
|
||||||
|
}
|
||||||
17
midend/llvm/type/IrPointerType.java
Normal file
17
midend/llvm/type/IrPointerType.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
public class IrPointerType extends IrType {
|
||||||
|
private IrType pointeeType;
|
||||||
|
|
||||||
|
public IrPointerType(IrType pointeeType) {
|
||||||
|
this.pointeeType = pointeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getPointeeType() {
|
||||||
|
return pointeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return pointeeType.toString() + "*";
|
||||||
|
}
|
||||||
|
}
|
||||||
74
midend/llvm/type/IrType.java
Normal file
74
midend/llvm/type/IrType.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package midend.llvm.type;
|
||||||
|
|
||||||
|
import midend.llvm.IrBuilder;
|
||||||
|
import midend.llvm.constant.IrConstantInt;
|
||||||
|
import midend.llvm.instr.CmpInstr;
|
||||||
|
import midend.llvm.instr.ExtendInstr;
|
||||||
|
import midend.llvm.instr.TruncInstr;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.instr.ExtendInstr;
|
||||||
|
|
||||||
|
public class IrType {
|
||||||
|
public boolean isInt32() {
|
||||||
|
return this == IrInterType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInt8() {
|
||||||
|
return this == IrInterType.INT8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBool() {
|
||||||
|
return this == IrInterType.BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVoid() {
|
||||||
|
return this == IrInterType.VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPointer() {
|
||||||
|
return this instanceof IrPointerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArray() {
|
||||||
|
return this instanceof IrArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFunc() {
|
||||||
|
return this instanceof IrFuncType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBasicBlock() {
|
||||||
|
return this instanceof IrBasicBlockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrValue convertType(IrValue originValue, IrType targetType) {
|
||||||
|
IrType originType = originValue.getType();
|
||||||
|
if (targetType.isInt32()) {
|
||||||
|
if (originType.isInt32()) {
|
||||||
|
return originValue;
|
||||||
|
} else {
|
||||||
|
ExtendInstr ei = new ExtendInstr(
|
||||||
|
IrBuilder.getLocalName(), targetType, originValue);
|
||||||
|
IrBuilder.addInstr(ei);
|
||||||
|
return ei;
|
||||||
|
}
|
||||||
|
} else if (targetType.isBool()) {
|
||||||
|
if (originType.isBool()) {
|
||||||
|
return originValue;
|
||||||
|
} else {
|
||||||
|
CmpInstr nezero = new CmpInstr(IrBuilder.getLocalName(), "!=",
|
||||||
|
originValue, new IrConstantInt(0));
|
||||||
|
IrBuilder.addInstr(nezero);
|
||||||
|
return nezero;
|
||||||
|
}
|
||||||
|
} else if (targetType.isArray()) {
|
||||||
|
IrArrayType arrayType = (IrArrayType) targetType;
|
||||||
|
return convertType(originValue, arrayType.getElementType());
|
||||||
|
}
|
||||||
|
return originValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
midend/llvm/use/IrUse.java
Normal file
21
midend/llvm/use/IrUse.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package midend.llvm.use;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class IrUse {
|
||||||
|
private IrValue value;
|
||||||
|
private IrUser user;
|
||||||
|
|
||||||
|
public IrUse(IrValue value, IrUser user) {
|
||||||
|
this.value = value;
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
midend/llvm/use/IrUser.java
Normal file
38
midend/llvm/use/IrUser.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package midend.llvm.use;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
|
||||||
|
public class IrUser extends IrValue {
|
||||||
|
private ArrayList<IrValue> uses;
|
||||||
|
|
||||||
|
public IrUser(IrType type, String name) {
|
||||||
|
super(type, name);
|
||||||
|
this.uses = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrValue> getUses() {
|
||||||
|
return uses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUse(IrValue value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uses.add(value);
|
||||||
|
value.addUser(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getUse(int index) {
|
||||||
|
if (index >= uses.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return uses.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumUses() {
|
||||||
|
return uses.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
120
midend/llvm/value/IrBasicBlock.java
Normal file
120
midend/llvm/value/IrBasicBlock.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package midend.llvm.value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import midend.llvm.instr.IrInstr;
|
||||||
|
import midend.llvm.instr.ReturnInstr;
|
||||||
|
import midend.llvm.type.IrBasicBlockType;
|
||||||
|
|
||||||
|
public class IrBasicBlock extends IrValue {
|
||||||
|
private ArrayList<IrInstr> instrs;
|
||||||
|
private IrFuncValue func;
|
||||||
|
private ArrayList<IrBasicBlock> preds; //前驱
|
||||||
|
private ArrayList<IrBasicBlock> succs; //后继
|
||||||
|
private HashSet<IrBasicBlock> domied; //支配该节点
|
||||||
|
private IrBasicBlock directDomi;
|
||||||
|
private HashSet<IrBasicBlock> directDomies; //该节点直接支配
|
||||||
|
private HashSet<IrBasicBlock> domiFrontier;
|
||||||
|
|
||||||
|
public IrBasicBlock(String name, IrFuncValue func) {
|
||||||
|
super(new IrBasicBlockType(), name);
|
||||||
|
this.func = func;
|
||||||
|
instrs = new ArrayList<>();
|
||||||
|
preds = new ArrayList<>();
|
||||||
|
succs = new ArrayList<>();
|
||||||
|
domied = new HashSet<>();
|
||||||
|
directDomi = null;
|
||||||
|
directDomies = new HashSet<>();
|
||||||
|
domiFrontier = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addInstr(IrInstr instr) {
|
||||||
|
instrs.add(instr);
|
||||||
|
instr.setBBlock(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrFuncValue getFunc() {
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return instrs.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEntry() {
|
||||||
|
return this.func.getBBlock(0) == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrBasicBlock> getPreds() {
|
||||||
|
return preds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrBasicBlock> getSuccs() {
|
||||||
|
return succs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getName() + ":\n\t");
|
||||||
|
for (IrInstr instr : instrs) {
|
||||||
|
sb.append(instr.toString());
|
||||||
|
if (instr != instrs.get(instrs.size() - 1)) {
|
||||||
|
sb.append("\n\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lastIsReturn() {
|
||||||
|
if (instrs.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return instrs.get(instrs.size() - 1) instanceof ReturnInstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCfg() {
|
||||||
|
this.preds.clear();
|
||||||
|
this.succs.clear();
|
||||||
|
domied.clear();
|
||||||
|
directDomi = null;
|
||||||
|
directDomies.clear();
|
||||||
|
domiFrontier.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrInstr> getInstrs() {
|
||||||
|
return instrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPred(IrBasicBlock bb) {
|
||||||
|
this.preds.add(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSucc(IrBasicBlock bb) {
|
||||||
|
this.succs.add(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDomied(IrBasicBlock bb) {
|
||||||
|
this.domied.add(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDirectDomies(IrBasicBlock bb) {
|
||||||
|
this.directDomies.add(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDomiFrontier(IrBasicBlock bb) {
|
||||||
|
this.domiFrontier.add(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirectDomi(IrBasicBlock bb) {
|
||||||
|
this.directDomi = bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<IrBasicBlock> getDomied() {
|
||||||
|
return domied;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getDirectDomi() {
|
||||||
|
return this.directDomi;
|
||||||
|
}
|
||||||
|
}
|
||||||
71
midend/llvm/value/IrFuncValue.java
Normal file
71
midend/llvm/value/IrFuncValue.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package midend.llvm.value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.IrBuilder;
|
||||||
|
import midend.llvm.instr.ReturnInstr;
|
||||||
|
import midend.llvm.type.IrFuncType;
|
||||||
|
|
||||||
|
public class IrFuncValue extends IrValue {
|
||||||
|
private ArrayList<IrValue> params;
|
||||||
|
private ArrayList<IrBasicBlock> bblocks;
|
||||||
|
|
||||||
|
public IrFuncValue(String name, IrType retType) {
|
||||||
|
super(new IrFuncType(retType), name);
|
||||||
|
params = new ArrayList<>();
|
||||||
|
bblocks = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrValue> getParams() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrBasicBlock> getBBlocks() {
|
||||||
|
return bblocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getBBlock(int index) {
|
||||||
|
return bblocks.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParam(IrValue param) {
|
||||||
|
params.add(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBBlock(IrBasicBlock bblock) {
|
||||||
|
bblocks.add(bblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMain() {
|
||||||
|
return getName().equals("@main");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getRetType() {
|
||||||
|
return ((IrFuncType) getType()).getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("define dso_local " + this.getRetType() + " " + this.getName() + "(");
|
||||||
|
for (int i = 0; i < params.size(); i++) {
|
||||||
|
sb.append(params.get(i).getType() + " " + params.get(i).getName());
|
||||||
|
if (i < params.size() - 1) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(") {\n");
|
||||||
|
for (IrBasicBlock bblock : bblocks) {
|
||||||
|
sb.append(bblock.toString() + "\n");
|
||||||
|
}
|
||||||
|
sb.append("}\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkReturn() {
|
||||||
|
IrBasicBlock currentBB = IrBuilder.getCurrentBB();
|
||||||
|
if (!currentBB.lastIsReturn()) {
|
||||||
|
ReturnInstr returnInstr = new ReturnInstr(null); // 确保没有return的情况只有void
|
||||||
|
IrBuilder.addInstr(returnInstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
midend/llvm/value/IrGlobalValue.java
Normal file
28
midend/llvm/value/IrGlobalValue.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package midend.llvm.value;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.constant.IrConstant;
|
||||||
|
|
||||||
|
public class IrGlobalValue extends IrValue {
|
||||||
|
private boolean isConstant;
|
||||||
|
private IrConstant initVal;
|
||||||
|
|
||||||
|
public IrGlobalValue(IrType type, String name, boolean isConstant, IrConstant initVal) {
|
||||||
|
super(type, name);
|
||||||
|
this.isConstant = isConstant;
|
||||||
|
this.initVal = initVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConstant() {
|
||||||
|
return isConstant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrConstant getInitVal() {
|
||||||
|
return initVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return isConstant ? getName() + " = dso_local constant " + initVal.toString() :
|
||||||
|
getName() + " = dso_local global " + initVal.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
32
midend/llvm/value/IrLoop.java
Normal file
32
midend/llvm/value/IrLoop.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package midend.llvm.value;
|
||||||
|
|
||||||
|
public class IrLoop {
|
||||||
|
private IrBasicBlock condBB;
|
||||||
|
private IrBasicBlock bodyBB;
|
||||||
|
private IrBasicBlock stepBB;
|
||||||
|
private IrBasicBlock followBB;
|
||||||
|
|
||||||
|
public IrLoop(IrBasicBlock condBB, IrBasicBlock bodyBB,
|
||||||
|
IrBasicBlock stepBB, IrBasicBlock followBB) {
|
||||||
|
this.condBB = condBB;
|
||||||
|
this.bodyBB = bodyBB;
|
||||||
|
this.stepBB = stepBB;
|
||||||
|
this.followBB = followBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getCondBB() {
|
||||||
|
return condBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getBodyBB() {
|
||||||
|
return bodyBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getStepBB() {
|
||||||
|
return stepBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrBasicBlock getFollowBB() {
|
||||||
|
return followBB;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
midend/llvm/value/IrValue.java
Normal file
38
midend/llvm/value/IrValue.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package midend.llvm.value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.use.IrUser;
|
||||||
|
|
||||||
|
public class IrValue {
|
||||||
|
private IrType type;
|
||||||
|
private String name;
|
||||||
|
private ArrayList<IrUser> users;
|
||||||
|
|
||||||
|
public IrValue(IrType type, String name) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.users = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IrUser> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUser(IrUser user) {
|
||||||
|
users.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return type.toString() + " " + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
112
midend/optimize/CfgMake.java
Normal file
112
midend/optimize/CfgMake.java
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
package midend.optimize;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import midend.llvm.instr.IrInstr;
|
||||||
|
import midend.llvm.instr.IrInstrType;
|
||||||
|
import midend.llvm.instr.JumpInstr;
|
||||||
|
import midend.llvm.value.IrBasicBlock;
|
||||||
|
import midend.llvm.value.IrFuncValue;
|
||||||
|
import midend.llvm.instr.BranchInstr;
|
||||||
|
|
||||||
|
public class CfgMake extends Optimizer {
|
||||||
|
public void optimize() {
|
||||||
|
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||||
|
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||||
|
bb.clearCfg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
makeCfg();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeCfg() {
|
||||||
|
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||||
|
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||||
|
for (IrInstr instr : bb.getInstrs()) {
|
||||||
|
if (instr.getInstrType() == IrInstrType.BR) {
|
||||||
|
BranchInstr branchInstr = (BranchInstr) instr;
|
||||||
|
IrBasicBlock trueBlock = branchInstr.getTrueBB();
|
||||||
|
IrBasicBlock falseBlock = branchInstr.getFalseBB();
|
||||||
|
bb.addSucc(trueBlock);
|
||||||
|
bb.addSucc(falseBlock);
|
||||||
|
trueBlock.addPred(bb);
|
||||||
|
falseBlock.addPred(bb);
|
||||||
|
} else if (instr.getInstrType() == IrInstrType.JUMP) {
|
||||||
|
JumpInstr jumpInstr = (JumpInstr) instr;
|
||||||
|
IrBasicBlock jumpBlock = jumpInstr.getTargetBlock();
|
||||||
|
bb.addSucc(jumpBlock);
|
||||||
|
jumpBlock.addPred(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeDomination() {
|
||||||
|
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||||
|
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||||
|
HashSet<IrBasicBlock> canArrive = new HashSet<>();
|
||||||
|
handleArrive(func.getBBlock(0), bb, canArrive);
|
||||||
|
for (IrBasicBlock block : func.getBBlocks()) {
|
||||||
|
if (!canArrive.contains(block)) {
|
||||||
|
block.addDomied(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleArrive(IrBasicBlock entryBlock,
|
||||||
|
IrBasicBlock deleteBlock, HashSet<IrBasicBlock> canArrive) {
|
||||||
|
if (entryBlock == deleteBlock) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!canArrive.contains(entryBlock)) {
|
||||||
|
canArrive.add(entryBlock);
|
||||||
|
}
|
||||||
|
for (IrBasicBlock succ : entryBlock.getSuccs()) {
|
||||||
|
if (succ != deleteBlock && !canArrive.contains(succ)) {
|
||||||
|
handleArrive(succ, deleteBlock, canArrive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeDirectDomi() {
|
||||||
|
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||||
|
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||||
|
for (IrBasicBlock domi : bb.getDomied()) {
|
||||||
|
HashSet<IrBasicBlock> bbDomi = bb.getDomied();
|
||||||
|
HashSet<IrBasicBlock> domiDomi = domi.getDomied();
|
||||||
|
for (IrBasicBlock domiDomiBB : domiDomi) {
|
||||||
|
if (bbDomi.contains(domiDomiBB)) {
|
||||||
|
bbDomi.remove(domiDomiBB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bbDomi.size() == 1 && bbDomi.contains(bb)) {
|
||||||
|
bb.setDirectDomi(domi);
|
||||||
|
domi.addDirectDomies(bb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeDomiFrontier() {
|
||||||
|
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||||
|
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||||
|
for (IrBasicBlock succ : bb.getSuccs()) {
|
||||||
|
IrBasicBlock currentBB = bb;
|
||||||
|
while (!succ.getDomied().contains(currentBB) || currentBB == succ) {
|
||||||
|
currentBB.addDomiFrontier(succ);
|
||||||
|
currentBB = currentBB.getDirectDomi();
|
||||||
|
if (currentBB == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
midend/optimize/Optimizer.java
Normal file
19
midend/optimize/Optimizer.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package midend.optimize;
|
||||||
|
|
||||||
|
import midend.llvm.IrModule;
|
||||||
|
|
||||||
|
public class Optimizer {
|
||||||
|
private static IrModule irModule;
|
||||||
|
|
||||||
|
public void setIrModule(IrModule irModule) {
|
||||||
|
Optimizer.irModule = irModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrModule getIrModule() {
|
||||||
|
return irModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void optimize() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
20
midend/symbol/ArraySymbol.java
Normal file
20
midend/symbol/ArraySymbol.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
public class ArraySymbol extends Symbol {
|
||||||
|
private int dim; // -1 means unknown
|
||||||
|
|
||||||
|
public ArraySymbol(String name, SymbolType type, int line, int dim) {
|
||||||
|
super(name, type, line);
|
||||||
|
this.dim = dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDim() {
|
||||||
|
return dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fullValue() {
|
||||||
|
for (int i = getValueList().size(); i < dim; i++) {
|
||||||
|
addValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
midend/symbol/FuncSymbol.java
Normal file
50
midend/symbol/FuncSymbol.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class FuncSymbol extends Symbol {
|
||||||
|
private int returnType; // 0 for void, 1 for int
|
||||||
|
private ArrayList<Integer> paramList; // 0 for var, 1 for array
|
||||||
|
private ArrayList<Symbol> paramSymbolList;
|
||||||
|
|
||||||
|
public FuncSymbol(String name, SymbolType type, int line, int returnType) {
|
||||||
|
super(name, type, line);
|
||||||
|
paramList = new ArrayList<>();
|
||||||
|
paramSymbolList = new ArrayList<>();
|
||||||
|
this.returnType = returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParam(int param) {
|
||||||
|
paramList.add(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParamSymbol(Symbol paramSymbol) {
|
||||||
|
paramSymbolList.add(paramSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParamNum() {
|
||||||
|
return paramList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReturnType() {
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParamType(int index) {
|
||||||
|
return paramList.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printParams() {
|
||||||
|
for (int i = 0; i < paramList.size(); i++) {
|
||||||
|
System.out.print(paramList.get(i) + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Integer> getParamList() {
|
||||||
|
return paramList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Symbol> getParamSymbolList() {
|
||||||
|
return paramSymbolList;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
midend/symbol/Symbol.java
Normal file
77
midend/symbol/Symbol.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
|
||||||
|
public class Symbol {
|
||||||
|
private String name;
|
||||||
|
private SymbolType type;
|
||||||
|
private int line;
|
||||||
|
private ArrayList<Integer> valueList;
|
||||||
|
private IrValue irValue;
|
||||||
|
|
||||||
|
public Symbol(String name, SymbolType type, int line) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.line = line;
|
||||||
|
valueList = new ArrayList<>();
|
||||||
|
irValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIrValue(IrValue irValue) {
|
||||||
|
this.irValue = irValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrValue getIrValue() {
|
||||||
|
return irValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addValue(int value) {
|
||||||
|
valueList.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addValue(ArrayList<Integer> valueList) {
|
||||||
|
this.valueList.addAll(valueList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Integer> getValueList() {
|
||||||
|
return valueList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue(int index) {
|
||||||
|
return valueList.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTypeStr() {
|
||||||
|
return type.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymbolType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name + " " + type.toString() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThatType(int type) { // 0 for normal var, 1 for array, 2 for func
|
||||||
|
if (type == 1) {
|
||||||
|
return this.type == SymbolType.INT_ARRAY || this.type == SymbolType.CONST_INT_ARRAY
|
||||||
|
|| this.type == SymbolType.STATIC_INT_ARRAY;
|
||||||
|
} else if (type == 2) {
|
||||||
|
return this.type == SymbolType.INT_FUNC || this.type == SymbolType.VOID_FUNC;
|
||||||
|
} else {
|
||||||
|
return this.type == SymbolType.INT || this.type == SymbolType.CONST_INT
|
||||||
|
|| this.type == SymbolType.STATIC_INT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
136
midend/symbol/SymbolManager.java
Normal file
136
midend/symbol/SymbolManager.java
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class SymbolManager {
|
||||||
|
public static ArrayList<SymbolTable> symbolTableList;
|
||||||
|
public static ArrayList<Integer> sequence;
|
||||||
|
public static SymbolTable currentTable;
|
||||||
|
public static int currentSequence;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
symbolTableList = new ArrayList<>();
|
||||||
|
sequence = new ArrayList<>();
|
||||||
|
currentTable = null;
|
||||||
|
currentSequence = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addSymbolTable() {
|
||||||
|
SymbolTable symbolTable = new SymbolTable(symbolTableList.size() + 1);
|
||||||
|
symbolTableList.add(symbolTable);
|
||||||
|
sequence.add(symbolTable.getTableId());
|
||||||
|
currentSequence++;
|
||||||
|
if (currentTable != null) {
|
||||||
|
symbolTable.setParentTable(currentTable);
|
||||||
|
}
|
||||||
|
currentTable = symbolTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<SymbolTable> getSymbolTableList() {
|
||||||
|
return symbolTableList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void releaseSymbolTable(int tableId) {
|
||||||
|
symbolTableList.get(tableId - 1).release();
|
||||||
|
currentTable = null;
|
||||||
|
for (int i = symbolTableList.size() - 1; i >= 0; i--) {
|
||||||
|
if (!symbolTableList.get(i).isReleased()) {
|
||||||
|
currentTable = symbolTableList.get(i);
|
||||||
|
currentSequence++;
|
||||||
|
sequence.add(currentTable.getTableId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void releaseSymbolTable() {
|
||||||
|
releaseSymbolTable(currentTable.getTableId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSymbolTableSize() {
|
||||||
|
return symbolTableList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addSymbol(Symbol symbol, Errors errors) {
|
||||||
|
currentTable.addSymbol(symbol, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSymbolTableInfo() {
|
||||||
|
String info = "";
|
||||||
|
for (SymbolTable symbolTable : symbolTableList) {
|
||||||
|
info += symbolTable.toString();
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Symbol getSymbol(String name) {
|
||||||
|
SymbolTable stable = currentTable;
|
||||||
|
Symbol symbol = null;
|
||||||
|
while (stable != null) {
|
||||||
|
symbol = stable.getSymbol(name);
|
||||||
|
if (symbol != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stable = stable.getParentTable();
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Symbol getSymbol(String name, boolean defined) {
|
||||||
|
SymbolTable stable = currentTable;
|
||||||
|
Symbol symbol = null;
|
||||||
|
while (stable != null) {
|
||||||
|
symbol = stable.getSymbol(name);
|
||||||
|
if (symbol != null && symbol.getIrValue() != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stable = stable.getParentTable();
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void nextTable() {
|
||||||
|
currentSequence++;
|
||||||
|
if (currentSequence >= sequence.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void lastTable() {
|
||||||
|
currentSequence--;
|
||||||
|
if (currentSequence < 0) {
|
||||||
|
currentSequence = 0;
|
||||||
|
currentTable = symbolTableList.get(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
currentSequence = -1;
|
||||||
|
currentTable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean IsGlobal() {
|
||||||
|
return currentTable.getTableId() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<Integer> getSequence() {
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getCurrentSequence() {
|
||||||
|
return currentSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getCurrentTableId() {
|
||||||
|
return sequence.get(currentSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SymbolTable getCurrentTable() {
|
||||||
|
return currentTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
midend/symbol/SymbolTable.java
Normal file
68
midend/symbol/SymbolTable.java
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import error.Error;
|
||||||
|
import error.ErrorType;
|
||||||
|
import error.Errors;
|
||||||
|
|
||||||
|
public class SymbolTable {
|
||||||
|
private ArrayList<Symbol> symbolList;
|
||||||
|
private HashMap<String, Symbol> symbolMap;
|
||||||
|
private int tableId;
|
||||||
|
private boolean isReleased;
|
||||||
|
private SymbolTable parentTable;
|
||||||
|
|
||||||
|
public SymbolTable(int tableId) {
|
||||||
|
this.tableId = tableId;
|
||||||
|
isReleased = false;
|
||||||
|
symbolList = new ArrayList<>();
|
||||||
|
symbolMap = new HashMap<>();
|
||||||
|
parentTable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTableId() {
|
||||||
|
return tableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReleased() {
|
||||||
|
return isReleased;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
isReleased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSymbol(Symbol symbol, Errors errors) {
|
||||||
|
if (symbolMap.containsKey(symbol.getName())) {
|
||||||
|
errors.addError(new Error(symbol.getLine(), ErrorType.b));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
symbolList.add(symbol);
|
||||||
|
symbolMap.put(symbol.getName(), symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentTable(SymbolTable parentTable) {
|
||||||
|
this.parentTable = parentTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymbolTable getParentTable() {
|
||||||
|
return parentTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol(String name) {
|
||||||
|
if (symbolMap.containsKey(name)) {
|
||||||
|
return symbolMap.get(name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String info = "";
|
||||||
|
for (Symbol symbol : symbolList) {
|
||||||
|
info += tableId + " " + symbol.toString();
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
midend/symbol/SymbolType.java
Normal file
22
midend/symbol/SymbolType.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package midend.symbol;
|
||||||
|
|
||||||
|
public enum SymbolType {
|
||||||
|
CONST_INT("ConstInt"),
|
||||||
|
CONST_INT_ARRAY("ConstIntArray"),
|
||||||
|
STATIC_INT("StaticInt"),
|
||||||
|
INT("Int"),
|
||||||
|
INT_ARRAY("IntArray"),
|
||||||
|
STATIC_INT_ARRAY("StaticIntArray"),
|
||||||
|
VOID_FUNC("VoidFunc"),
|
||||||
|
INT_FUNC("IntFunc");
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
SymbolType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
midend/visit/Visitor.java
Normal file
36
midend/visit/Visitor.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package midend.visit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import frontend.ast.CompUnit;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import frontend.ast.func.FuncDef;
|
||||||
|
import frontend.ast.func.MainFuncDef;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
public class Visitor {
|
||||||
|
private CompUnit compUnit;
|
||||||
|
|
||||||
|
public Visitor(CompUnit compUnit) {
|
||||||
|
this.compUnit = compUnit;
|
||||||
|
SymbolManager.reset();
|
||||||
|
SymbolManager.nextTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visit() {
|
||||||
|
ArrayList<Decl> decls = this.compUnit.GetDecls();
|
||||||
|
ArrayList<FuncDef> funcDefs = this.compUnit.GetFuncDefs();
|
||||||
|
MainFuncDef mainFuncDef = this.compUnit.GetMainFuncDef();
|
||||||
|
|
||||||
|
for (Decl decl : decls) {
|
||||||
|
VisitorDecl.visitDecl(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FuncDef funcDef : funcDefs) {
|
||||||
|
VisitorFuncDef.visitFuncDef(funcDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
VisitorFuncDef.visitMainFuncDef(mainFuncDef);
|
||||||
|
}
|
||||||
|
//:TODO:符号表的变换,什么时候往前进一个符号表,这需要人工手工来操作
|
||||||
|
}
|
||||||
35
midend/visit/VisitorBlock.java
Normal file
35
midend/visit/VisitorBlock.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package midend.visit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import frontend.ast.block.Block;
|
||||||
|
import frontend.ast.block.BlockItem;
|
||||||
|
import frontend.ast.block.Stmt;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
public class VisitorBlock {
|
||||||
|
public static void visitBlock(Block block) {
|
||||||
|
if (!block.isFuncBlock()) {
|
||||||
|
SymbolManager.nextTable();
|
||||||
|
}
|
||||||
|
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());
|
||||||
|
// System.out.println("bsequence: " + SymbolManager.getCurrentSequence());//TODO:debug
|
||||||
|
ArrayList<BlockItem> blockItems = block.getBlockItems();
|
||||||
|
for (BlockItem blockItem : blockItems) {
|
||||||
|
visitBlockItem(blockItem);
|
||||||
|
}
|
||||||
|
if (!block.isFuncBlock()) {
|
||||||
|
SymbolManager.nextTable();
|
||||||
|
}
|
||||||
|
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitBlockItem(BlockItem blockItem) {
|
||||||
|
if (blockItem.getChild(0) instanceof Decl) {
|
||||||
|
VisitorDecl.visitDecl((Decl) blockItem.getChild(0));
|
||||||
|
} else {
|
||||||
|
VisitorStmt.visitStmt((Stmt) blockItem.getChild(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
167
midend/visit/VisitorDecl.java
Normal file
167
midend/visit/VisitorDecl.java
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
package midend.visit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import frontend.ast.decl.ConstDecl;
|
||||||
|
import frontend.ast.decl.ConstDef;
|
||||||
|
import frontend.ast.decl.Decl;
|
||||||
|
import frontend.ast.decl.VarDecl;
|
||||||
|
import frontend.ast.decl.VarDef;
|
||||||
|
import frontend.ast.exp.ConstExp;
|
||||||
|
import frontend.ast.exp.Exp;
|
||||||
|
import frontend.ast.token.TokenNode;
|
||||||
|
import frontend.lexer.Token;
|
||||||
|
import midend.llvm.IrBuilder;
|
||||||
|
import midend.llvm.constant.IrConstant;
|
||||||
|
import midend.llvm.constant.IrConstantArray;
|
||||||
|
import midend.llvm.constant.IrConstantInt;
|
||||||
|
import midend.llvm.instr.AllocateInstr;
|
||||||
|
import midend.llvm.instr.StoreInstr;
|
||||||
|
import midend.llvm.instr.GepInstr;
|
||||||
|
import midend.llvm.type.IrArrayType;
|
||||||
|
import midend.llvm.type.IrFuncType;
|
||||||
|
import midend.llvm.type.IrInterType;
|
||||||
|
import midend.llvm.type.IrPointerType;
|
||||||
|
import midend.llvm.type.IrType;
|
||||||
|
import midend.llvm.value.IrGlobalValue;
|
||||||
|
import midend.llvm.value.IrValue;
|
||||||
|
import midend.symbol.SymbolType;
|
||||||
|
import midend.symbol.ArraySymbol;
|
||||||
|
import midend.symbol.Symbol;
|
||||||
|
import midend.symbol.SymbolManager;
|
||||||
|
|
||||||
|
public class VisitorDecl {
|
||||||
|
public static void visitDecl(Decl decl) {
|
||||||
|
if (decl.getChild(0) instanceof ConstDecl) {
|
||||||
|
visitConstDecl((ConstDecl) decl.getChild(0));
|
||||||
|
} else {
|
||||||
|
visitVarDecl((VarDecl) decl.getChild(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitConstDecl(ConstDecl constDecl) {
|
||||||
|
ArrayList<ConstDef> constDefs = constDecl.GetConstDefs();
|
||||||
|
for (ConstDef constDef : constDefs) {
|
||||||
|
visitConstDef(constDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitVarDecl(VarDecl varDecl) {
|
||||||
|
ArrayList<VarDef> varDefs = varDecl.GetVarDefs();
|
||||||
|
for (VarDef varDef : varDefs) {
|
||||||
|
visitVarDef(varDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitConstDef(ConstDef constDef) {
|
||||||
|
Symbol symbol = SymbolManager.getSymbol(((TokenNode) constDef.getChild(0)).getValue());
|
||||||
|
if (SymbolManager.IsGlobal()) { // 全局变量下直接声明
|
||||||
|
IrGlobalValue irGlobalValue = new IrGlobalValue(
|
||||||
|
new IrPointerType(getSymbolIrType(symbol)),
|
||||||
|
IrBuilder.getGlobalName(), true, getSymbolIrConst(symbol));
|
||||||
|
IrBuilder.addNewGlobal(irGlobalValue);
|
||||||
|
symbol.setIrValue(irGlobalValue);
|
||||||
|
} else { // 局部变量需要分配地址再存值
|
||||||
|
AllocateInstr allocateInstr = new AllocateInstr(getSymbolIrType(symbol),
|
||||||
|
IrBuilder.getLocalName());
|
||||||
|
IrBuilder.addInstr(allocateInstr);
|
||||||
|
symbol.setIrValue(allocateInstr);
|
||||||
|
ArrayList<Integer> valueList = symbol.getValueList();
|
||||||
|
if (!(symbol instanceof ArraySymbol)) {
|
||||||
|
StoreInstr storeInstr = new StoreInstr(getSymbolIrConst(symbol),
|
||||||
|
allocateInstr);
|
||||||
|
IrBuilder.addInstr(storeInstr);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < valueList.size(); i++) {
|
||||||
|
GepInstr gepInstr = new GepInstr(allocateInstr,
|
||||||
|
new IrConstantInt(i), IrBuilder.getLocalName());
|
||||||
|
IrBuilder.addInstr(gepInstr);
|
||||||
|
IrValue initValue = new IrConstantInt(valueList.get(i));
|
||||||
|
StoreInstr storeInstr = new StoreInstr(initValue, gepInstr);
|
||||||
|
IrBuilder.addInstr(storeInstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void visitVarDef(VarDef varDef) {
|
||||||
|
Symbol symbol = SymbolManager.getSymbol(((TokenNode) varDef.getChild(0)).getValue());
|
||||||
|
if (SymbolManager.IsGlobal()) {
|
||||||
|
IrGlobalValue irGlobalValue = new IrGlobalValue(
|
||||||
|
new IrPointerType(getSymbolIrType(symbol)),
|
||||||
|
IrBuilder.getGlobalName(), false, getSymbolIrConst(symbol));
|
||||||
|
IrBuilder.addNewGlobal(irGlobalValue);
|
||||||
|
symbol.setIrValue(irGlobalValue);
|
||||||
|
} else { // Think:static修饰的变量该如何实现
|
||||||
|
visitLocalVarDef(varDef, symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void visitLocalVarDef(VarDef varDef, Symbol symbol) {
|
||||||
|
if (symbol.getType().equals(SymbolType.STATIC_INT) ||
|
||||||
|
symbol.getType().equals(SymbolType.STATIC_INT_ARRAY)) {
|
||||||
|
// 当为局部变量且为static修饰的变量的时候,将其作为全局变量处理
|
||||||
|
IrGlobalValue irGlobalValue = new IrGlobalValue(
|
||||||
|
new IrPointerType(getSymbolIrType(symbol)),
|
||||||
|
IrBuilder.getGlobalName(), false, getSymbolIrConst(symbol));
|
||||||
|
IrBuilder.addNewGlobal(irGlobalValue);
|
||||||
|
symbol.setIrValue(irGlobalValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AllocateInstr allocateInstr = new AllocateInstr(
|
||||||
|
getSymbolIrType(symbol), IrBuilder.getLocalName());
|
||||||
|
IrBuilder.addInstr(allocateInstr);
|
||||||
|
if (!(symbol instanceof ArraySymbol)) { // 非数组变量
|
||||||
|
if (varDef.HaveInitVal()) {
|
||||||
|
Exp exp = varDef.getInitVal().getExpList().get(0);
|
||||||
|
IrValue irExp = VisitorExp.visitExp(exp);
|
||||||
|
StoreInstr storeInstr = new StoreInstr(irExp, allocateInstr);
|
||||||
|
IrBuilder.addInstr(storeInstr);
|
||||||
|
}
|
||||||
|
} else { // 数组变量
|
||||||
|
if (varDef.HaveInitVal()) {
|
||||||
|
ArrayList<Exp> expList = varDef.getInitVal().getExpList();
|
||||||
|
for (int i = 0; i < expList.size(); i++) {
|
||||||
|
IrValue irExp = VisitorExp.visitExp(expList.get(i));
|
||||||
|
irExp = IrType.convertType(irExp, IrInterType.INT32);
|
||||||
|
GepInstr gepInstr = new GepInstr(allocateInstr,
|
||||||
|
new IrConstantInt(i), IrBuilder.getLocalName());
|
||||||
|
IrBuilder.addInstr(gepInstr);
|
||||||
|
StoreInstr storeInstr = new StoreInstr(irExp, gepInstr);
|
||||||
|
IrBuilder.addInstr(storeInstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
symbol.setIrValue(allocateInstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrType getSymbolIrType(Symbol symbol) {
|
||||||
|
SymbolType st = symbol.getType();
|
||||||
|
if (st.equals(SymbolType.INT) || st.equals(SymbolType.CONST_INT)
|
||||||
|
|| st.equals(SymbolType.STATIC_INT)) {
|
||||||
|
return IrInterType.INT32;
|
||||||
|
} else if (st.equals(SymbolType.INT_ARRAY) || st.equals(SymbolType.CONST_INT_ARRAY)
|
||||||
|
|| st.equals(SymbolType.STATIC_INT_ARRAY)) {
|
||||||
|
return new IrArrayType(IrInterType.INT32, ((ArraySymbol) symbol).getDim());
|
||||||
|
} else {
|
||||||
|
if (st.equals(SymbolType.INT_FUNC)) {
|
||||||
|
return new IrFuncType(IrInterType.INT32);
|
||||||
|
} else {
|
||||||
|
return new IrFuncType(IrInterType.VOID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrConstant getSymbolIrConst(Symbol symbol) {
|
||||||
|
ArrayList<Integer> valueList = symbol.getValueList();
|
||||||
|
if (symbol instanceof ArraySymbol) {
|
||||||
|
ArrayList<IrConstant> elements = new ArrayList<>();
|
||||||
|
for (int i = 0; i < valueList.size(); i++) {
|
||||||
|
elements.add(new IrConstantInt(valueList.get(i)));
|
||||||
|
}
|
||||||
|
return new IrConstantArray(symbol.getName(), elements, ((ArraySymbol) symbol).getDim());
|
||||||
|
} else {
|
||||||
|
return valueList.isEmpty() ? new IrConstantInt(0) : new IrConstantInt(valueList.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user