mips without optimize
This commit is contained in:
90
Compiler.java
Normal file → Executable file
90
Compiler.java
Normal file → Executable file
@@ -1,42 +1,48 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import backend.BackEnd;
|
||||
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 mipsFile = "mips.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);
|
||||
BackEnd backEnd = new BackEnd(midend.getModule());
|
||||
backEnd.toMips();
|
||||
backEnd.writeToFile(mipsFile);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
backend/BackEnd.java
Normal file
32
backend/BackEnd.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package backend;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.MipsModule;
|
||||
import midend.llvm.IrModule;
|
||||
|
||||
public class BackEnd {
|
||||
private MipsModule mipsModule;
|
||||
private IrModule irModule;
|
||||
|
||||
public BackEnd(IrModule irModule) {
|
||||
this.irModule = irModule;
|
||||
this.mipsModule = new MipsModule();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
MipsBuilder.setModule(mipsModule);
|
||||
irModule.toMips();
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
Files.write(Paths.get(fileName), mipsModule.toString().getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
93
backend/mips/MipsBuilder.java
Normal file
93
backend/mips/MipsBuilder.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package backend.mips;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.data.MipsAsciiz;
|
||||
import backend.mips.instr.data.MipsSpace;
|
||||
import backend.mips.instr.data.MipsWord;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class MipsBuilder {
|
||||
private static MipsModule module = null;
|
||||
private static int offset = 0;
|
||||
private static HashMap<IrValue, Integer> valueOffsetMap = new HashMap<>();
|
||||
private static HashMap<IrValue, Register> valueRegisterMap = new HashMap<>();
|
||||
|
||||
public static void setModule(MipsModule module) {
|
||||
MipsBuilder.module = module;
|
||||
}
|
||||
|
||||
public static int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public static void setOffset(int offset) {
|
||||
MipsBuilder.offset = offset;
|
||||
}
|
||||
|
||||
public static void setValueOffsetMap(HashMap<IrValue, Integer> valueOffsetMap) {
|
||||
MipsBuilder.valueOffsetMap = valueOffsetMap;
|
||||
}
|
||||
|
||||
public static HashMap<IrValue, Integer> getValueOffsetMap() {
|
||||
return valueOffsetMap;
|
||||
}
|
||||
|
||||
public static void setValueRegisterMap(HashMap<IrValue, Register> valueRegisterMap) {
|
||||
MipsBuilder.valueRegisterMap = valueRegisterMap;
|
||||
}
|
||||
|
||||
public static HashMap<IrValue, Register> getValueRegisterMap() {
|
||||
return valueRegisterMap;
|
||||
}
|
||||
|
||||
public static MipsModule getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public static void addMipsInstr(MipsInstr instr) {
|
||||
if (instr instanceof MipsAsciiz || instr instanceof MipsWord || instr instanceof MipsSpace) { //data段
|
||||
module.addData(instr);
|
||||
} else {
|
||||
module.addText(instr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void enterNewFunc(IrFuncValue func) {
|
||||
offset = 0;
|
||||
valueOffsetMap = func.getValueOffsetMap();
|
||||
valueOffsetMap.clear(); //TODO:是否需要清空?
|
||||
valueRegisterMap = func.getValueRegisterMap();
|
||||
}
|
||||
|
||||
public static Register getRegister(IrValue value) {
|
||||
return valueRegisterMap.get(value);
|
||||
}
|
||||
|
||||
public static Integer getOffset(IrValue value) {
|
||||
return valueOffsetMap.get(value);
|
||||
}
|
||||
|
||||
public static void allocaRegister(IrValue value, Register reg) {
|
||||
valueRegisterMap.put(value, reg);
|
||||
}
|
||||
|
||||
public static void allocaOffset(IrValue value) {
|
||||
if (!valueOffsetMap.containsKey(value)) {
|
||||
offset -= 4;
|
||||
int valueOffset = offset;
|
||||
valueOffsetMap.put(value, valueOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void allocaOffset(int extra) {
|
||||
offset -= extra;
|
||||
}
|
||||
|
||||
public static ArrayList<Register> getUsedRegisters() {
|
||||
return new ArrayList<>(valueRegisterMap.values());
|
||||
}
|
||||
}
|
||||
51
backend/mips/MipsModule.java
Normal file
51
backend/mips/MipsModule.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package backend.mips;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.instr.MipsAnnotation;
|
||||
import backend.mips.instr.MipsLabel;
|
||||
import backend.mips.instr.MipsInstr;
|
||||
|
||||
public class MipsModule {
|
||||
private ArrayList<MipsInstr> dataList;
|
||||
private ArrayList<MipsInstr> textList;
|
||||
|
||||
public MipsModule() {
|
||||
this.dataList = new ArrayList<MipsInstr>();
|
||||
this.textList = new ArrayList<MipsInstr>();
|
||||
}
|
||||
|
||||
public ArrayList<MipsInstr> getDataList() {
|
||||
return dataList;
|
||||
}
|
||||
|
||||
public ArrayList<MipsInstr> getTextList() {
|
||||
return textList;
|
||||
}
|
||||
|
||||
public void addData(MipsInstr instr) {
|
||||
dataList.add(instr);
|
||||
}
|
||||
|
||||
public void addText(MipsInstr instr) {
|
||||
textList.add(instr);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(".data\n");
|
||||
for (MipsInstr instr : dataList) {
|
||||
sb.append("\t" + instr.toString());
|
||||
}
|
||||
sb.append("\n.text\n");
|
||||
for (MipsInstr instr : textList) {
|
||||
if (instr instanceof MipsLabel || instr instanceof MipsAnnotation) {
|
||||
sb.append(instr.toString());
|
||||
continue;
|
||||
}
|
||||
sb.append("\t" + instr.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
58
backend/mips/Register.java
Executable file
58
backend/mips/Register.java
Executable file
@@ -0,0 +1,58 @@
|
||||
package backend.mips;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public enum Register {
|
||||
ZERO("$zero"),
|
||||
AT("$at"),
|
||||
V0("$v0"),
|
||||
V1("$v1"),
|
||||
A0("$a0"),
|
||||
A1("$a1"),
|
||||
A2("$a2"),
|
||||
A3("$a3"),
|
||||
T0("$t0"),
|
||||
T1("$t1"),
|
||||
T2("$t2"),
|
||||
T3("$t3"),
|
||||
T4("$t4"),
|
||||
T5("$t5"),
|
||||
T6("$t6"),
|
||||
T7("$t7"),
|
||||
S0("$s0"),
|
||||
S1("$s1"),
|
||||
S2("$s2"),
|
||||
S3("$s3"),
|
||||
S4("$s4"),
|
||||
S5("$s5"),
|
||||
S6("$s6"),
|
||||
S7("$s7"),
|
||||
T8("$t8"),
|
||||
T9("$t9"),
|
||||
K0("$k0"),
|
||||
K1("$k1"),
|
||||
GP("$gp"),
|
||||
SP("$sp"),
|
||||
FP("$fp"),
|
||||
RA("$ra");
|
||||
|
||||
private String regName;
|
||||
|
||||
Register(String regName) {
|
||||
this.regName = regName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return regName;
|
||||
}
|
||||
|
||||
public static ArrayList<Register> availableRegisters() {
|
||||
ArrayList<Register> regs = new ArrayList<>();
|
||||
for (Register reg : Register.values()) {
|
||||
if (reg.toString().charAt(1) == 't' || reg.toString().charAt(1) == 's') {
|
||||
regs.add(reg);
|
||||
}
|
||||
}
|
||||
return regs;
|
||||
}
|
||||
}
|
||||
39
backend/mips/instr/MipsAlu.java
Executable file
39
backend/mips/instr/MipsAlu.java
Executable file
@@ -0,0 +1,39 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsAlu extends MipsInstr {
|
||||
private MipsAluType aluType;
|
||||
private Register rd;
|
||||
private Register rs;
|
||||
private Register rt;
|
||||
private int immediate;
|
||||
private boolean isImInstr;
|
||||
|
||||
public MipsAlu(MipsAluType aluType, Register rd, Register rs, Register rt) {
|
||||
super(MipsType.ALU);
|
||||
this.aluType = aluType;
|
||||
this.rd = rd;
|
||||
this.rs = rs;
|
||||
this.rt = rt;
|
||||
this.immediate = 0;
|
||||
this.isImInstr = false;
|
||||
}
|
||||
|
||||
public MipsAlu(MipsAluType aluType, Register rd, Register rs, int immediate) {
|
||||
super(MipsType.ALU);
|
||||
this.aluType = aluType;
|
||||
this.rd = rd;
|
||||
this.rs = rs;
|
||||
this.rt = null;
|
||||
this.immediate = immediate;
|
||||
this.isImInstr = true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return isImInstr ? aluType.toString() + " " + rd + ", " + rs + ", " + immediate + "\n"
|
||||
: aluType.toString() + " " + rd + ", " + rs + ", " + rt + "\n";
|
||||
}
|
||||
}
|
||||
16
backend/mips/instr/MipsAnnotation.java
Executable file
16
backend/mips/instr/MipsAnnotation.java
Executable file
@@ -0,0 +1,16 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsAnnotation extends MipsInstr {
|
||||
private String annotation;
|
||||
|
||||
public MipsAnnotation(String anno) {
|
||||
super(MipsType.ANNOTATION);
|
||||
this.annotation = anno;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "# " + this.annotation + "\n";
|
||||
}
|
||||
}
|
||||
36
backend/mips/instr/MipsBranch.java
Normal file
36
backend/mips/instr/MipsBranch.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsBranchType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsBranch extends MipsInstr{
|
||||
private MipsBranchType branchType;
|
||||
private Register rs;
|
||||
private Register rt;
|
||||
private String label;
|
||||
|
||||
public MipsBranch(MipsBranchType branchType, Register rs, Register rt, String label) {
|
||||
super(MipsType.BRANCH);
|
||||
this.branchType = branchType;
|
||||
this.rs = rs;
|
||||
this.rt = rt;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public MipsBranch(MipsBranchType branchType, Register rs, String label) {
|
||||
super(MipsType.BRANCH);
|
||||
this.branchType = branchType;
|
||||
this.rs = rs;
|
||||
this.rt = null;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.rt == null) {
|
||||
return this.branchType.toString() + " " + this.rs + ", " + this.label + "\n";
|
||||
} else {
|
||||
return this.branchType.toString() + " " + this.rs + ", " + this.rt + ", " + this.label + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
42
backend/mips/instr/MipsComp.java
Normal file
42
backend/mips/instr/MipsComp.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsCompareType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsComp extends MipsInstr {
|
||||
private MipsCompareType compareType;
|
||||
private Register rd;
|
||||
private Register rs;
|
||||
private Register rt;
|
||||
private int immediate;
|
||||
private boolean isImmediate;
|
||||
|
||||
public MipsComp(MipsCompareType compareType, Register rd, Register rs, Register rt) {
|
||||
super(MipsType.COMPARE);
|
||||
this.compareType = compareType;
|
||||
this.rd = rd;
|
||||
this.rs = rs;
|
||||
this.rt = rt;
|
||||
this.immediate = 0;
|
||||
this.isImmediate = false;
|
||||
}
|
||||
|
||||
public MipsComp(MipsCompareType compareType, Register rd, Register rs, int immediate) {
|
||||
super(MipsType.COMPARE);
|
||||
this.compareType = compareType;
|
||||
this.rd = rd;
|
||||
this.rs = rs;
|
||||
this.rt = null;
|
||||
this.immediate = immediate;
|
||||
this.isImmediate = true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.isImmediate) {
|
||||
return this.compareType.toString() + " " + this.rd + ", " + this.rs + ", " + this.immediate + "\n";
|
||||
} else {
|
||||
return this.compareType.toString() + " " + this.rd + ", " + this.rs + ", " + this.rt + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
21
backend/mips/instr/MipsInstr.java
Executable file
21
backend/mips/instr/MipsInstr.java
Executable file
@@ -0,0 +1,21 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.MipsBuilder;
|
||||
|
||||
public class MipsInstr {
|
||||
private MipsType mt;
|
||||
|
||||
public MipsInstr(MipsType mt) {
|
||||
this.mt = mt;
|
||||
MipsBuilder.addMipsInstr(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public MipsType getType() {
|
||||
return mt;
|
||||
}
|
||||
}
|
||||
33
backend/mips/instr/MipsJump.java
Normal file
33
backend/mips/instr/MipsJump.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsJump extends MipsInstr {
|
||||
private MipsJumpType jumpType;
|
||||
private String label;
|
||||
private Register rd;
|
||||
|
||||
public MipsJump(MipsJumpType jumpType, String label) {
|
||||
super(MipsType.JUMP);
|
||||
this.jumpType = jumpType;
|
||||
this.label = label;
|
||||
this.rd = null;
|
||||
}
|
||||
|
||||
public MipsJump(MipsJumpType jumpType, Register rd) {
|
||||
super(MipsType.JUMP);
|
||||
this.jumpType = jumpType;
|
||||
this.label = null;
|
||||
this.rd = rd;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.rd == null) {
|
||||
return this.jumpType.toString() + " " + this.label + "\n";
|
||||
} else {
|
||||
return this.jumpType.toString() + " " + this.rd + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
16
backend/mips/instr/MipsLabel.java
Normal file
16
backend/mips/instr/MipsLabel.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsLabel extends MipsInstr {
|
||||
private String label;
|
||||
|
||||
public MipsLabel(String label) {
|
||||
super(MipsType.LABEL);
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.label + ":\n";
|
||||
}
|
||||
}
|
||||
39
backend/mips/instr/MipsLs.java
Normal file
39
backend/mips/instr/MipsLs.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsLs extends MipsInstr {
|
||||
private MipsLsType lsType;
|
||||
private Register rd;
|
||||
private Register rt;
|
||||
private int offset;
|
||||
private String label;
|
||||
|
||||
public MipsLs(MipsLsType lsType, Register rd, Register rt, int offset) {
|
||||
super(MipsType.LS);
|
||||
this.lsType = lsType;
|
||||
this.rd = rd;
|
||||
this.rt = rt;
|
||||
this.offset = offset;
|
||||
this.label = null;
|
||||
}
|
||||
|
||||
public MipsLs(MipsLsType lsType, Register rd, int offset, String label) {
|
||||
super(MipsType.LS);
|
||||
this.lsType = lsType;
|
||||
this.rd = rd;
|
||||
this.rt = null;
|
||||
this.offset = offset;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.label == null) {
|
||||
return this.lsType.toString() + " " + this.rd + ", " + this.offset + "(" + this.rt + ")\n";
|
||||
} else {
|
||||
return this.lsType.toString() + " " + this.rd + ", " + this.label + " + " + this.offset + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
33
backend/mips/instr/MipsMd.java
Normal file
33
backend/mips/instr/MipsMd.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsMdType;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsMd extends MipsInstr {
|
||||
private MipsMdType mdType;
|
||||
private Register rd;
|
||||
private Register rt;
|
||||
|
||||
public MipsMd(MipsMdType mdType, Register rd, Register rt) {
|
||||
super(MipsType.MD);
|
||||
this.mdType = mdType;
|
||||
this.rd = rd;
|
||||
this.rt = rt;
|
||||
}
|
||||
|
||||
public MipsMd(MipsMdType mdType, Register rd) {
|
||||
super(MipsType.MD);
|
||||
this.mdType = mdType;
|
||||
this.rd = rd;
|
||||
this.rt = null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.rt == null) {
|
||||
return this.mdType.toString() + " " + this.rd + "\n";
|
||||
} else {
|
||||
return this.mdType.toString() + " " + this.rd + ", " + this.rt + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
13
backend/mips/instr/MipsSyscall.java
Normal file
13
backend/mips/instr/MipsSyscall.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package backend.mips.instr;
|
||||
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsSyscall extends MipsInstr {
|
||||
public MipsSyscall() {
|
||||
super(MipsType.SYSCALL);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "syscall\n";
|
||||
}
|
||||
}
|
||||
19
backend/mips/instr/data/MipsAsciiz.java
Normal file
19
backend/mips/instr/data/MipsAsciiz.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package backend.mips.instr.data;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsAsciiz extends MipsInstr {
|
||||
private String name;
|
||||
private String str;
|
||||
|
||||
public MipsAsciiz(String name, String str) {
|
||||
super(MipsType.DATA);
|
||||
this.name = name;
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": .asciiz \"" + str.replaceAll("\n", "\\n") + "\"\n";
|
||||
}
|
||||
}
|
||||
19
backend/mips/instr/data/MipsSpace.java
Normal file
19
backend/mips/instr/data/MipsSpace.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package backend.mips.instr.data;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsSpace extends MipsInstr {
|
||||
private int size;
|
||||
private String name;
|
||||
|
||||
public MipsSpace(int size, String name) {
|
||||
super(MipsType.DATA);
|
||||
this.size = size;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": .space " + size + "\n";
|
||||
}
|
||||
}
|
||||
39
backend/mips/instr/data/MipsWord.java
Normal file
39
backend/mips/instr/data/MipsWord.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package backend.mips.instr.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
|
||||
public class MipsWord extends MipsInstr {
|
||||
private String name;
|
||||
private ArrayList<Integer> valueList;
|
||||
|
||||
public MipsWord(String name, ArrayList<Integer> valueList) {
|
||||
super(MipsType.DATA);
|
||||
this.name = name;
|
||||
this.valueList = valueList;
|
||||
}
|
||||
|
||||
public MipsWord(String name, int value) {
|
||||
super(MipsType.DATA);
|
||||
this.name = name;
|
||||
this.valueList = new ArrayList<Integer>();
|
||||
this.valueList.add(value);
|
||||
}
|
||||
|
||||
public int getValueNum() {
|
||||
return valueList.size();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name).append(": .word ");
|
||||
for (int value : valueList) {
|
||||
sb.append(value).append(", ");
|
||||
}
|
||||
sb.delete(sb.length() - 2, sb.length());
|
||||
sb.append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
28
backend/mips/instr/fake/MipsLa.java
Normal file
28
backend/mips/instr/fake/MipsLa.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package backend.mips.instr.fake;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsLa extends MipsInstr {
|
||||
private Register rd;
|
||||
private String label;
|
||||
|
||||
public MipsLa(Register rd, String label) {
|
||||
super(MipsType.FAKE);
|
||||
this.rd = rd;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Register getRd() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "la " + rd + ", " + label + "\n";
|
||||
}
|
||||
}
|
||||
29
backend/mips/instr/fake/MipsLi.java
Normal file
29
backend/mips/instr/fake/MipsLi.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package backend.mips.instr.fake;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
|
||||
public class MipsLi extends MipsInstr {
|
||||
private Register rd;
|
||||
private int value;
|
||||
|
||||
public MipsLi(Register rd, int value) {
|
||||
super(MipsType.FAKE);
|
||||
this.rd = rd;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Register getRd() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "li " + rd + ", " + value + "\n";
|
||||
}
|
||||
}
|
||||
28
backend/mips/instr/fake/MipsMove.java
Normal file
28
backend/mips/instr/fake/MipsMove.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package backend.mips.instr.fake;
|
||||
|
||||
import backend.mips.instr.MipsInstr;
|
||||
import backend.mips.instr.type.MipsType;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class MipsMove extends MipsInstr {
|
||||
private Register rd;
|
||||
private Register rt;
|
||||
|
||||
public MipsMove(Register rd, Register rt) {
|
||||
super(MipsType.FAKE);
|
||||
this.rd = rd;
|
||||
this.rt = rt;
|
||||
}
|
||||
|
||||
public Register getDest() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
public Register getSrc() {
|
||||
return rt;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "move " + rd + ", " + rt + "\n";
|
||||
}
|
||||
}
|
||||
16
backend/mips/instr/type/MipsAluType.java
Executable file
16
backend/mips/instr/type/MipsAluType.java
Executable file
@@ -0,0 +1,16 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsAluType {
|
||||
// calc_R
|
||||
ADD, SUB, ADDU, SUBU, AND, OR, NOR, XOR, SLT, SLTU,
|
||||
// shiftv
|
||||
SLLV, SRAV, SRLV,
|
||||
// calc_I
|
||||
ADDI, ADDIU, ANDI, ORI, XORI, SLTI, SLTIU,
|
||||
// shift
|
||||
SLL, SRA, SRL;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
9
backend/mips/instr/type/MipsBranchType.java
Normal file
9
backend/mips/instr/type/MipsBranchType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsBranchType {
|
||||
BEQ, BNE, BLEZ, BGTZ, BLTZ, BGEZ;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
9
backend/mips/instr/type/MipsCompareType.java
Normal file
9
backend/mips/instr/type/MipsCompareType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsCompareType {
|
||||
SLT, SLE, SGT, SGE, SEQ, SNE, SLTI;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
9
backend/mips/instr/type/MipsJumpType.java
Normal file
9
backend/mips/instr/type/MipsJumpType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsJumpType {
|
||||
J, JAL, JR;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
9
backend/mips/instr/type/MipsLsType.java
Normal file
9
backend/mips/instr/type/MipsLsType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsLsType {
|
||||
LW, SW, LH, SH, LHU, LB, SB, LBU;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
9
backend/mips/instr/type/MipsMdType.java
Normal file
9
backend/mips/instr/type/MipsMdType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsMdType {
|
||||
MFHI, MFLO, MULT, DIV, MTHI, MTLO;
|
||||
|
||||
public String toString() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
15
backend/mips/instr/type/MipsType.java
Executable file
15
backend/mips/instr/type/MipsType.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package backend.mips.instr.type;
|
||||
|
||||
public enum MipsType {
|
||||
ALU,
|
||||
COMPARE,
|
||||
BRANCH,
|
||||
JUMP,
|
||||
SYSCALL,
|
||||
DATA,
|
||||
LABEL,
|
||||
ANNOTATION,
|
||||
LS,
|
||||
MD,
|
||||
FAKE
|
||||
}
|
||||
4
config.json
Executable file
4
config.json
Executable file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"programming language": "java",
|
||||
"object code": "mips"
|
||||
}
|
||||
54
error/Error.java
Normal file → Executable file
54
error/Error.java
Normal file → Executable file
@@ -1,27 +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";
|
||||
}
|
||||
}
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
34
error/ErrorType.java
Normal file → Executable file
34
error/ErrorType.java
Normal file → Executable file
@@ -1,17 +1,17 @@
|
||||
package error;
|
||||
|
||||
public enum ErrorType {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
f,
|
||||
g,
|
||||
h,
|
||||
i,
|
||||
j,
|
||||
k,
|
||||
l,
|
||||
m
|
||||
}
|
||||
package error;
|
||||
|
||||
public enum ErrorType {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
f,
|
||||
g,
|
||||
h,
|
||||
i,
|
||||
j,
|
||||
k,
|
||||
l,
|
||||
m
|
||||
}
|
||||
|
||||
0
error/Errors.java
Normal file → Executable file
0
error/Errors.java
Normal file → Executable file
0
frontend/.DS_Store
vendored
Normal file → Executable file
0
frontend/.DS_Store
vendored
Normal file → Executable file
0
frontend/ast/.DS_Store
vendored
Normal file → Executable file
0
frontend/ast/.DS_Store
vendored
Normal file → Executable file
0
frontend/ast/CompUnit.java
Normal file → Executable file
0
frontend/ast/CompUnit.java
Normal file → Executable file
0
frontend/ast/Node.java
Normal file → Executable file
0
frontend/ast/Node.java
Normal file → Executable file
46
frontend/ast/NodeStack.java
Normal file → Executable file
46
frontend/ast/NodeStack.java
Normal file → Executable file
@@ -1,23 +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();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/SyntaxType.java
Normal file → Executable file
0
frontend/ast/SyntaxType.java
Normal file → Executable file
0
frontend/ast/block/Block.java
Normal file → Executable file
0
frontend/ast/block/Block.java
Normal file → Executable file
56
frontend/ast/block/BlockItem.java
Normal file → Executable file
56
frontend/ast/block/BlockItem.java
Normal file → Executable file
@@ -1,28 +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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
114
frontend/ast/block/ForStmt.java
Normal file → Executable file
114
frontend/ast/block/ForStmt.java
Normal file → Executable file
@@ -1,57 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
548
frontend/ast/block/Stmt.java
Normal file → Executable file
548
frontend/ast/block/Stmt.java
Normal file → Executable file
@@ -1,274 +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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/decl/ConstDecl.java
Normal file → Executable file
0
frontend/ast/decl/ConstDecl.java
Normal file → Executable file
0
frontend/ast/decl/ConstDef.java
Normal file → Executable file
0
frontend/ast/decl/ConstDef.java
Normal file → Executable file
0
frontend/ast/decl/Decl.java
Normal file → Executable file
0
frontend/ast/decl/Decl.java
Normal file → Executable file
0
frontend/ast/decl/VarDecl.java
Normal file → Executable file
0
frontend/ast/decl/VarDecl.java
Normal file → Executable file
0
frontend/ast/decl/VarDef.java
Normal file → Executable file
0
frontend/ast/decl/VarDef.java
Normal file → Executable file
146
frontend/ast/exp/AddExp.java
Normal file → Executable file
146
frontend/ast/exp/AddExp.java
Normal file → Executable file
@@ -1,73 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
frontend/ast/exp/Cond.java
Normal file → Executable file
36
frontend/ast/exp/Cond.java
Normal file → Executable file
@@ -1,18 +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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/exp/ConstExp.java
Normal file → Executable file
0
frontend/ast/exp/ConstExp.java
Normal file → Executable file
98
frontend/ast/exp/EqExp.java
Normal file → Executable file
98
frontend/ast/exp/EqExp.java
Normal file → Executable file
@@ -1,49 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/exp/Exp.java
Normal file → Executable file
0
frontend/ast/exp/Exp.java
Normal file → Executable file
88
frontend/ast/exp/LAndExp.java
Normal file → Executable file
88
frontend/ast/exp/LAndExp.java
Normal file → Executable file
@@ -1,44 +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());
|
||||
}
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
88
frontend/ast/exp/LOrExp.java
Normal file → Executable file
88
frontend/ast/exp/LOrExp.java
Normal file → Executable file
@@ -1,44 +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());
|
||||
}
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
118
frontend/ast/exp/LVal.java
Normal file → Executable file
118
frontend/ast/exp/LVal.java
Normal file → Executable file
@@ -1,59 +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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
150
frontend/ast/exp/MulExp.java
Normal file → Executable file
150
frontend/ast/exp/MulExp.java
Normal file → Executable file
@@ -1,75 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
frontend/ast/exp/NumberExp.java
Normal file → Executable file
42
frontend/ast/exp/NumberExp.java
Normal file → Executable file
@@ -1,21 +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());
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
116
frontend/ast/exp/PrimaryExp.java
Normal file → Executable file
116
frontend/ast/exp/PrimaryExp.java
Normal file → Executable file
@@ -1,58 +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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
frontend/ast/exp/RelExp.java
Normal file → Executable file
100
frontend/ast/exp/RelExp.java
Normal file → Executable file
@@ -1,50 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
248
frontend/ast/exp/UnaryExp.java
Normal file → Executable file
248
frontend/ast/exp/UnaryExp.java
Normal file → Executable file
@@ -1,124 +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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
frontend/ast/exp/UnaryOp.java
Normal file → Executable file
34
frontend/ast/exp/UnaryOp.java
Normal file → Executable file
@@ -1,17 +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
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/func/FuncDef.java
Normal file → Executable file
0
frontend/ast/func/FuncDef.java
Normal file → Executable file
96
frontend/ast/func/FuncFParam.java
Normal file → Executable file
96
frontend/ast/func/FuncFParam.java
Normal file → Executable file
@@ -1,49 +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);
|
||||
//这里不求维数,因为函数形参为数组只是相当于一个指针
|
||||
}
|
||||
}
|
||||
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);
|
||||
//这里不求维数,因为函数形参为数组只是相当于一个指针
|
||||
}
|
||||
}
|
||||
}
|
||||
0
frontend/ast/func/FuncFParams.java
Normal file → Executable file
0
frontend/ast/func/FuncFParams.java
Normal file → Executable file
114
frontend/ast/func/FuncRParams.java
Normal file → Executable file
114
frontend/ast/func/FuncRParams.java
Normal file → Executable file
@@ -1,57 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/ast/func/FuncType.java
Normal file → Executable file
0
frontend/ast/func/FuncType.java
Normal file → Executable file
0
frontend/ast/func/MainFuncDef.java
Normal file → Executable file
0
frontend/ast/func/MainFuncDef.java
Normal file → Executable file
0
frontend/ast/token/TokenNode.java
Normal file → Executable file
0
frontend/ast/token/TokenNode.java
Normal file → Executable file
0
frontend/ast/val/ConstInitVal.java
Normal file → Executable file
0
frontend/ast/val/ConstInitVal.java
Normal file → Executable file
0
frontend/ast/val/InitVal.java
Normal file → Executable file
0
frontend/ast/val/InitVal.java
Normal file → Executable file
490
frontend/lexer/Lexer.java
Normal file → Executable file
490
frontend/lexer/Lexer.java
Normal file → Executable file
@@ -1,245 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
84
frontend/lexer/Token.java
Normal file → Executable file
84
frontend/lexer/Token.java
Normal file → Executable file
@@ -1,42 +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";
|
||||
}
|
||||
}
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
0
frontend/lexer/TokenStream.java
Normal file → Executable file
0
frontend/lexer/TokenStream.java
Normal file → Executable file
246
frontend/lexer/TokenType.java
Normal file → Executable file
246
frontend/lexer/TokenType.java
Normal file → Executable file
@@ -1,123 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
frontend/parser/Parser.java
Normal file → Executable file
76
frontend/parser/Parser.java
Normal file → Executable file
@@ -1,38 +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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
midend/Midend.java
Normal file → Executable file
67
midend/Midend.java
Normal file → Executable file
@@ -1,31 +1,36 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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 IrModule getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
Files.write(Paths.get(fileName), module.toString().getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
64
midend/errorhandle/ErrorHandler.java
Normal file → Executable file
64
midend/errorhandle/ErrorHandler.java
Normal file → Executable file
@@ -1,32 +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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
286
midend/llvm/IrBuilder.java
Normal file → Executable file
286
midend/llvm/IrBuilder.java
Normal file → Executable file
@@ -1,143 +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();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
225
midend/llvm/IrModule.java
Normal file → Executable file
225
midend/llvm/IrModule.java
Normal file → Executable file
@@ -1,100 +1,125 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAnnotation;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.MipsLabel;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
for (IrGlobalValue globalVar : this.globalVars) {
|
||||
globalVar.toMips();
|
||||
}
|
||||
for (IrConstantStr str : this.strs.values()) {
|
||||
str.toMips(str.getMipsLabel());
|
||||
}
|
||||
new MipsAnnotation("jump to main");
|
||||
new MipsJump(MipsJumpType.JAL, "main");
|
||||
new MipsJump(MipsJumpType.J, "end");
|
||||
|
||||
for (IrFuncValue irFunction : this.funcs) {
|
||||
irFunction.toMips();
|
||||
}
|
||||
new MipsLabel("end");
|
||||
new MipsLi(Register.V0, 10);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
4
midend/llvm/constant/IrConstant.java
Normal file → Executable file
4
midend/llvm/constant/IrConstant.java
Normal file → Executable file
@@ -11,4 +11,8 @@ public class IrConstant extends IrValue {
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
17
midend/llvm/constant/IrConstantArray.java
Normal file → Executable file
17
midend/llvm/constant/IrConstantArray.java
Normal file → Executable file
@@ -2,6 +2,8 @@ package midend.llvm.constant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.instr.data.MipsSpace;
|
||||
import backend.mips.instr.data.MipsWord;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
|
||||
@@ -44,4 +46,19 @@ public class IrConstantArray extends IrConstant {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
ArrayList<Integer> values = new ArrayList<>();
|
||||
if (elements.size() == 0) {
|
||||
new MipsSpace(size * 4, label);
|
||||
} else {
|
||||
for (IrConstant element : elements) {
|
||||
values.add(((IrConstantInt) element).getValue());
|
||||
}
|
||||
for (int i = 0; i < size - elements.size(); i++) {
|
||||
values.add(0);
|
||||
}
|
||||
new MipsWord(label, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
midend/llvm/constant/IrConstantInt.java
Normal file → Executable file
5
midend/llvm/constant/IrConstantInt.java
Normal file → Executable file
@@ -1,5 +1,6 @@
|
||||
package midend.llvm.constant;
|
||||
|
||||
import backend.mips.instr.data.MipsWord;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class IrConstantInt extends IrConstant {
|
||||
@@ -17,4 +18,8 @@ public class IrConstantInt extends IrConstant {
|
||||
public String toString() {
|
||||
return "i32 " + value;
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
new MipsWord(label, value);
|
||||
}
|
||||
}
|
||||
|
||||
111
midend/llvm/constant/IrConstantStr.java
Normal file → Executable file
111
midend/llvm/constant/IrConstantStr.java
Normal file → Executable file
@@ -1,53 +1,58 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.constant;
|
||||
|
||||
import backend.mips.instr.data.MipsAsciiz;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
new MipsAsciiz(label, getRealStr(value));
|
||||
}
|
||||
}
|
||||
|
||||
70
midend/llvm/instr/AllocateInstr.java
Normal file → Executable file
70
midend/llvm/instr/AllocateInstr.java
Normal file → Executable file
@@ -1,21 +1,49 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrType;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
// 想法:在栈上分配数据所需要的空间,再分配四字节的指针,这就是个指针,将其当作指针就好理解了
|
||||
if (pointeeType instanceof IrArrayType) {
|
||||
MipsBuilder.allocaOffset(4 * ((IrArrayType) pointeeType).getSize());
|
||||
} else {
|
||||
MipsBuilder.allocaOffset(4);
|
||||
}
|
||||
|
||||
Register reg = MipsBuilder.getRegister(this);
|
||||
if (reg == null) { // 未分配寄存器情况
|
||||
int offset = MipsBuilder.getOffset();
|
||||
new MipsAlu(MipsAluType.ADDI, Register.K0, Register.SP, offset);
|
||||
MipsBuilder.allocaOffset(this); // 将该变量的偏移量设置为其指针的偏移量,后续取值先取指针,再根据指针取值
|
||||
offset = MipsBuilder.getOffset();
|
||||
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset);
|
||||
} else {
|
||||
int offset = MipsBuilder.getOffset();
|
||||
new MipsAlu(MipsAluType.ADDI, reg, Register.SP, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
85
midend/llvm/instr/AluInstr.java
Normal file → Executable file
85
midend/llvm/instr/AluInstr.java
Normal file → Executable file
@@ -1,24 +1,61 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsMd;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsMdType;
|
||||
import backend.mips.Register;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
IrValue left = getUse(0);
|
||||
IrValue right = getUse(1);
|
||||
Register leftReg = MipsBuilder.getRegister(left) != null ? MipsBuilder.getRegister(left) : Register.K0;
|
||||
Register rightReg = MipsBuilder.getRegister(right) != null ? MipsBuilder.getRegister(right) : Register.K1;
|
||||
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
|
||||
loadValueToReg(left, leftReg);
|
||||
loadValueToReg(right, rightReg);
|
||||
|
||||
if (getAluType() == AluType.ADD) {
|
||||
new MipsAlu(MipsAluType.ADDU, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.SUB) {
|
||||
new MipsAlu(MipsAluType.SUBU, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.AND) {
|
||||
new MipsAlu(MipsAluType.AND, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.OR) {
|
||||
new MipsAlu(MipsAluType.OR, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.MUL) {
|
||||
new MipsMd(MipsMdType.MULT, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFLO, resultReg);
|
||||
} else if (getAluType() == AluType.SDIV) {
|
||||
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFLO, resultReg);
|
||||
} else if (getAluType() == AluType.SREM) {
|
||||
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFHI, resultReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
104
midend/llvm/instr/AluType.java
Normal file → Executable file
104
midend/llvm/instr/AluType.java
Normal file → Executable file
@@ -1,53 +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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
81
midend/llvm/instr/BranchInstr.java
Normal file → Executable file
81
midend/llvm/instr/BranchInstr.java
Normal file → Executable file
@@ -1,33 +1,48 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsBranch;
|
||||
import backend.mips.instr.type.MipsBranchType;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import backend.mips.instr.MipsJump;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register condReg = MipsBuilder.getRegister(getCond());
|
||||
if (condReg == null) {
|
||||
condReg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getCond(), condReg);
|
||||
new MipsBranch(MipsBranchType.BNE, condReg, Register.ZERO, getTrueBB().getMipsLabel());
|
||||
new MipsJump(MipsJumpType.J, getFalseBB().getMipsLabel());
|
||||
}
|
||||
}
|
||||
|
||||
165
midend/llvm/instr/CallInstr.java
Normal file → Executable file
165
midend/llvm/instr/CallInstr.java
Normal file → Executable file
@@ -1,48 +1,117 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
import backend.mips.MipsBuilder;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
ArrayList<Register> usedRegisters = MipsBuilder.getUsedRegisters();
|
||||
int offset = MipsBuilder.getOffset();
|
||||
save(usedRegisters, offset);
|
||||
ArrayList<IrValue> args = getArgs();
|
||||
saveArgs(args, offset, usedRegisters);
|
||||
offset -= (usedRegisters.size() + 2) * 4;
|
||||
new MipsAlu(MipsAluType.ADDI, Register.SP, Register.SP, offset);
|
||||
new MipsJump(MipsJumpType.JAL, getCalledFunc().getMipsLabel());
|
||||
offset += (usedRegisters.size() + 2) * 4;
|
||||
recover(usedRegisters, offset);
|
||||
saveResult(this, Register.V0);
|
||||
}
|
||||
|
||||
public void save(ArrayList<Register> usedRegisters, int offset) {
|
||||
int num = 0;
|
||||
for (Register reg : usedRegisters) {
|
||||
num++;
|
||||
new MipsLs(MipsLsType.SW, reg, Register.SP, offset - num * 4);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, Register.SP, Register.SP, offset - (num + 1) * 4);
|
||||
new MipsLs(MipsLsType.SW, Register.RA, Register.SP, offset - (num + 2) * 4);
|
||||
}
|
||||
|
||||
public void saveArgs(ArrayList<IrValue> args, int offset, ArrayList<Register> usedRegisters) {
|
||||
int num = 0;
|
||||
ArrayList<Register> argRegs = new ArrayList<>();
|
||||
argRegs.add(Register.A1);
|
||||
argRegs.add(Register.A2);
|
||||
argRegs.add(Register.A3);
|
||||
for (IrValue arg : args) {
|
||||
num++;
|
||||
if (num <= 3) { // 分配到A1、A2、A3
|
||||
if (argRegs.contains(MipsBuilder.getRegister(arg))) {
|
||||
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
|
||||
new MipsLs(MipsLsType.LW, argRegs.get(num - 1), Register.SP, offset - (index + 1) * 4);
|
||||
} else {
|
||||
loadValueToReg(arg, argRegs.get(num - 1));
|
||||
}
|
||||
} else {
|
||||
if (MipsBuilder.getRegister(arg) == Register.K0 || argRegs.contains(MipsBuilder.getRegister(arg))) {
|
||||
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
|
||||
new MipsLs(MipsLsType.LW, Register.K0, Register.SP, offset - (index + 1) * 4);
|
||||
} else {
|
||||
loadValueToReg(arg, Register.K0);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset - (usedRegisters.size() + num + 2) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void recover(ArrayList<Register> usedRegisters, int offset) {
|
||||
new MipsLs(MipsLsType.LW, Register.RA, Register.SP, 0);
|
||||
new MipsLs(MipsLsType.LW, Register.SP, Register.SP, 4);
|
||||
int num = 0;
|
||||
for (Register reg : usedRegisters) {
|
||||
num++;
|
||||
new MipsLs(MipsLsType.LW, reg, Register.SP, offset - num * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
90
midend/llvm/instr/CmpInstr.java
Normal file → Executable file
90
midend/llvm/instr/CmpInstr.java
Normal file → Executable file
@@ -1,32 +1,58 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsComp;
|
||||
import backend.mips.instr.type.MipsCompareType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import backend.mips.MipsBuilder;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register leftReg = MipsBuilder.getRegister(getLhs()) != null ? MipsBuilder.getRegister(getLhs()) : Register.K0;
|
||||
Register rightReg = MipsBuilder.getRegister(getRhs()) != null ? MipsBuilder.getRegister(getRhs()) : Register.K1;
|
||||
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
|
||||
loadValueToReg(getLhs(), leftReg);
|
||||
loadValueToReg(getRhs(), rightReg);
|
||||
if (getCmpType() == CmpType.EQ) {
|
||||
new MipsComp(MipsCompareType.SEQ, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.NE) {
|
||||
new MipsComp(MipsCompareType.SNE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SGE) {
|
||||
new MipsComp(MipsCompareType.SGE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SLE) {
|
||||
new MipsComp(MipsCompareType.SLE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SGT) {
|
||||
new MipsComp(MipsCompareType.SGT, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SLT) {
|
||||
new MipsComp(MipsCompareType.SLT, resultReg, leftReg, rightReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
96
midend/llvm/instr/CmpType.java
Normal file → Executable file
96
midend/llvm/instr/CmpType.java
Normal file → Executable file
@@ -1,48 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
73
midend/llvm/instr/ExtendInstr.java
Normal file → Executable file
73
midend/llvm/instr/ExtendInstr.java
Normal file → Executable file
@@ -1,31 +1,42 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register reg = MipsBuilder.getRegister(this);
|
||||
if (reg == null) {
|
||||
reg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getSrc(), reg);
|
||||
saveResult(this, reg);
|
||||
}
|
||||
}
|
||||
|
||||
143
midend/llvm/instr/GepInstr.java
Normal file → Executable file
143
midend/llvm/instr/GepInstr.java
Normal file → Executable file
@@ -1,57 +1,86 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register pointerReg = MipsBuilder.getRegister(getPointer());
|
||||
if (pointerReg == null) {
|
||||
pointerReg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getPointer(), pointerReg);
|
||||
Register offsetReg = MipsBuilder.getRegister(getOffset());
|
||||
if (offsetReg == null) {
|
||||
offsetReg = Register.K1;
|
||||
}
|
||||
Register resultReg = MipsBuilder.getRegister(this);
|
||||
if (resultReg == null) {
|
||||
resultReg = Register.K1;
|
||||
}
|
||||
if (getOffset() instanceof IrConstantInt intOffset) {
|
||||
new MipsAlu(MipsAluType.ADDI, resultReg, pointerReg, 4 * intOffset.getValue());
|
||||
} else {
|
||||
loadValueToReg(getOffset(), offsetReg);
|
||||
new MipsAlu(MipsAluType.SLL, resultReg, offsetReg, 2);
|
||||
new MipsAlu(MipsAluType.ADDU, resultReg, resultReg, pointerReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
43
midend/llvm/instr/GetIntInstr.java
Normal file → Executable file
43
midend/llvm/instr/GetIntInstr.java
Normal file → Executable file
@@ -1,17 +1,26 @@
|
||||
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()";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
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()";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLi(Register.V0, 5);
|
||||
new MipsSyscall();
|
||||
saveResult(this, Register.V0);
|
||||
}
|
||||
}
|
||||
|
||||
103
midend/llvm/instr/IrInstr.java
Normal file → Executable file
103
midend/llvm/instr/IrInstr.java
Normal file → Executable file
@@ -1,28 +1,75 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.use.IrUser;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.fake.MipsLa;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.fake.MipsMove;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
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;
|
||||
}
|
||||
|
||||
public void saveResult(IrValue value, Register reg) {
|
||||
Register valueReg = MipsBuilder.getRegister(value);
|
||||
if (valueReg == null) {
|
||||
Integer offset = MipsBuilder.getOffset(value);
|
||||
if (offset == null) {
|
||||
MipsBuilder.allocaOffset(value);
|
||||
offset = MipsBuilder.getOffset(value);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, reg, Register.SP, offset);
|
||||
} else {
|
||||
new MipsMove(valueReg, reg);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadValueToReg(IrValue value, Register reg) {
|
||||
if (value instanceof IrGlobalValue) {
|
||||
new MipsLa(reg, value.getMipsLabel());
|
||||
return;
|
||||
}
|
||||
if (value instanceof IrConstantInt) {
|
||||
new MipsLi(reg, ((IrConstantInt) value).getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
Register valueReg = MipsBuilder.getRegister(value);
|
||||
if (valueReg != null) {
|
||||
new MipsMove(reg, valueReg);
|
||||
return;
|
||||
}
|
||||
Integer offset = MipsBuilder.getOffset(value);
|
||||
if (offset == null) {
|
||||
MipsBuilder.allocaOffset(value);
|
||||
offset = MipsBuilder.getOffset(value);
|
||||
}
|
||||
new MipsLs(MipsLsType.LW, reg, Register.SP, offset);
|
||||
}
|
||||
}
|
||||
|
||||
36
midend/llvm/instr/IrInstrType.java
Normal file → Executable file
36
midend/llvm/instr/IrInstrType.java
Normal file → Executable file
@@ -1,18 +1,18 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum IrInstrType {
|
||||
ALU,
|
||||
CMP,
|
||||
CALL,
|
||||
ALLOCA,
|
||||
LOAD,
|
||||
STORE,
|
||||
GEP,
|
||||
PHI,
|
||||
EXTEND,
|
||||
TRUNC,
|
||||
BR,
|
||||
RET,
|
||||
JUMP,
|
||||
IO
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum IrInstrType {
|
||||
ALU,
|
||||
CMP,
|
||||
CALL,
|
||||
ALLOCA,
|
||||
LOAD,
|
||||
STORE,
|
||||
GEP,
|
||||
PHI,
|
||||
EXTEND,
|
||||
TRUNC,
|
||||
BR,
|
||||
RET,
|
||||
JUMP,
|
||||
IO
|
||||
}
|
||||
|
||||
45
midend/llvm/instr/JumpInstr.java
Normal file → Executable file
45
midend/llvm/instr/JumpInstr.java
Normal file → Executable file
@@ -1,20 +1,25 @@
|
||||
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:所有的指令的基本块设置还需完善
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsJump(MipsJumpType.J, getTargetBlock().getMipsLabel()); //TODO: 该用JAL吗?
|
||||
}
|
||||
}
|
||||
|
||||
59
midend/llvm/instr/LoadInstr.java
Normal file → Executable file
59
midend/llvm/instr/LoadInstr.java
Normal file → Executable file
@@ -1,20 +1,39 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
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();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
IrValue pointer = getPointer();
|
||||
Register reg = MipsBuilder.getRegister(pointer);
|
||||
if (reg == null) { // 未分配寄存器情况
|
||||
reg = Register.K0;
|
||||
}
|
||||
loadValueToReg(pointer, reg);
|
||||
Register resultReg = MipsBuilder.getRegister(this);
|
||||
if (resultReg == null) {
|
||||
resultReg = Register.K1;
|
||||
}
|
||||
new MipsLs(MipsLsType.LW, resultReg, reg, 0);
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
47
midend/llvm/instr/PutChInstr.java
Normal file → Executable file
47
midend/llvm/instr/PutChInstr.java
Normal file → Executable file
@@ -1,19 +1,28 @@
|
||||
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)";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
|
||||
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)";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
loadValueToReg(getUse(0), Register.A0);
|
||||
new MipsLi(Register.V0, 11);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
47
midend/llvm/instr/PutIntInstr.java
Normal file → Executable file
47
midend/llvm/instr/PutIntInstr.java
Normal file → Executable file
@@ -1,19 +1,28 @@
|
||||
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)";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
|
||||
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)";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
loadValueToReg(getUse(0), Register.A0);
|
||||
new MipsLi(Register.V0, 1);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
62
midend/llvm/instr/PutStrInstr.java
Normal file → Executable file
62
midend/llvm/instr/PutStrInstr.java
Normal file → Executable file
@@ -1,26 +1,36 @@
|
||||
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))";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import backend.mips.instr.fake.MipsLa;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.Register;
|
||||
|
||||
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))";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLa(Register.A0, strVal.getMipsLabel());
|
||||
new MipsLi(Register.V0, 4);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user