├── Compiler.java ├── META-INF └── MANIFEST.MF ├── SymTable ├── Func.java ├── FuncFormVar.java ├── Lval.java ├── SymItem.java ├── SymLinker.java ├── SymbolTable.java └── Var.java ├── back ├── MipsGenerator.java ├── RegAlloc.java └── utils.java ├── div_alg1.png ├── div_alg2.png ├── front ├── ASD │ ├── ASDNode.java │ ├── AddExp.java │ ├── BType.java │ ├── Block.java │ ├── BlockItem.java │ ├── CompUnit.java │ ├── Cond.java │ ├── ConstDecl.java │ ├── ConstDef.java │ ├── ConstExp.java │ ├── ConstInitVal.java │ ├── Decl.java │ ├── EqExp.java │ ├── ErrorRepresent.java │ ├── Exp.java │ ├── FormatString.java │ ├── FuncDef.java │ ├── FuncFParam.java │ ├── FuncFParams.java │ ├── FuncRParams.java │ ├── FuncType.java │ ├── Indent.java │ ├── InitVal.java │ ├── IntConst.java │ ├── Jump.java │ ├── LAndExp.java │ ├── LOrExp.java │ ├── LVal.java │ ├── MainFuncDef.java │ ├── MulExp.java │ ├── Number.java │ ├── PrimaryExp.java │ ├── RelExp.java │ ├── Stmt.java │ ├── UnaryExp.java │ ├── UnaryOp.java │ ├── VarDecl.java │ └── VarDef.java ├── Compiler.java ├── Error.java ├── ErrorRecorder.java ├── LexicalAnalyser.java ├── Parser.java └── Token.java ├── mid ├── Block.java ├── DataFlower.java ├── MidCode.java ├── MidCodeList.java └── VarConfliction.java ├── readme.md └── stack.png /Compiler.java: -------------------------------------------------------------------------------- 1 | import SymTable.SymItem; 2 | import SymTable.SymbolTable; 3 | import back.MipsGenerator; 4 | import front.ASD.CompUnit; 5 | import front.ErrorRecorder; 6 | import front.LexicalAnalyser; 7 | import front.Parser; 8 | import SymTable.SymLinker; 9 | import mid.DataFlower; 10 | import mid.MidCodeList; 11 | import mid.VarConfliction; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.FileInputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.InputStreamReader; 18 | import java.util.ArrayList; 19 | import java.util.HashMap; 20 | 21 | public class Compiler { 22 | public static int debugging = 2; 23 | private static final String inputFilePath = "testfile.txt"; 24 | public static boolean branch_opt = true; 25 | 26 | 27 | private static String readFile() throws IOException { 28 | InputStream is = new FileInputStream(inputFilePath); 29 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 30 | StringBuilder buffer = new StringBuilder(); 31 | String line = reader.readLine(); 32 | while (line != null) { 33 | buffer.append(line).append("\n"); 34 | line = reader.readLine(); 35 | } 36 | reader.close(); 37 | is.close(); 38 | return buffer.toString(); 39 | } 40 | 41 | 42 | public static void main(String[] args) throws IOException { 43 | front.Compiler.branch_opt = branch_opt; 44 | LexicalAnalyser analyser = new LexicalAnalyser(); 45 | analyser.analyze(readFile()); 46 | if (debugging == 1) { 47 | System.out.print(analyser.result()); 48 | } 49 | 50 | // parsing the source code 51 | Parser parser = new Parser(analyser.getTokenList()); 52 | if (!parser.analyze()){ 53 | System.out.println("Error parsing your testfile"); 54 | ErrorRecorder.PrintErrorRecord(); 55 | return; 56 | } 57 | CompUnit unit = parser.getASDTree(); 58 | if (debugging == 1) { 59 | unit.printTestInfo(); 60 | } 61 | 62 | // linking 63 | SymLinker symLinker = new SymLinker(unit); 64 | symLinker.link(); 65 | if (!ErrorRecorder.withoutError()) { 66 | System.out.println("Error linking your testfile"); 67 | ErrorRecorder.PrintErrorRecord(); 68 | return; 69 | } 70 | 71 | //generate mid_code 72 | HashMap> funcTables = symLinker.getFuncTable(); 73 | System.out.println("finish parsing your code, start generating mid-code..."); 74 | MidCodeList midCodeList = new MidCodeList(symLinker.node2tableItem, funcTables); 75 | unit.gen_mid(midCodeList); 76 | midCodeList.printCode("testfile1_19375341_孙泽一_优化前中间代码.txt"); 77 | SymbolTable global_table = symLinker.getBlockLoc2table().get("<0,0>"); 78 | midCodeList.addTmp(funcTables, global_table); 79 | // midCodeList.remove_useless_code(); 80 | 81 | for (int i = 0; i < 20; i++) { 82 | DataFlower.refresh(midCodeList); 83 | 84 | // mid_code_optimization 85 | midCodeList.remove_redundant_arith(); 86 | midCodeList.remove_redundant_compare(); 87 | midCodeList.arith_to_assign(); 88 | midCodeList.remove_redundant_assign(); 89 | midCodeList.remove_redundant_tmp(); 90 | midCodeList.remove_redundant_jump(); 91 | 92 | // data_flow_analysis 93 | DataFlower.define_point_ranking(midCodeList); 94 | DataFlower.divide_base_block(midCodeList); 95 | // DataFlower.printBlockInfo("block_info_before.txt"); 96 | DataFlower.remove_redundant(); 97 | DataFlower.const_broadcast(); 98 | // DataFlower.printBlockInfo("block_info_after.txt"); 99 | } 100 | 101 | VarConfliction.get_func_vars(midCodeList); 102 | midCodeList.printCode("testfile1_19375341_孙泽一_优化后中间代码.txt"); 103 | 104 | // generate mips_code 105 | System.out.println("finish generating mid code, start generating mips-code..."); 106 | MipsGenerator mips = new MipsGenerator(midCodeList.midCodes, midCodeList.strCons, funcTables, global_table); 107 | mips.translate(); 108 | mips.toFile(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: Compiler 3 | 4 | -------------------------------------------------------------------------------- /SymTable/Func.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | public class Func implements SymItem{ 4 | 5 | public enum Type{ 6 | voidFunc, intFunc; 7 | } 8 | private Integer argc; 9 | private String name; 10 | private Type type; 11 | public String loc; 12 | public int addr; 13 | 14 | public Func(String name, Type type, Integer argc, String loc) { 15 | this.name = name; 16 | this.argc = argc; 17 | this.type = type; 18 | this.loc = loc; 19 | } 20 | 21 | @Override 22 | public String getName() { 23 | return this.name; 24 | } 25 | 26 | @Override 27 | public boolean isConst() { 28 | return false; 29 | } 30 | 31 | @Override 32 | public String get_loc() { 33 | return this.loc; 34 | } 35 | 36 | @Override 37 | public int set_addr(int addr) { 38 | this.addr = addr; 39 | return this.addr; 40 | } 41 | 42 | @Override 43 | public Integer getAddr() { 44 | return this.addr; 45 | } 46 | 47 | @Override 48 | public Integer getSize() { 49 | return 0; 50 | } 51 | 52 | @Override 53 | public String getUniqueName() { 54 | return this.name; 55 | } 56 | 57 | public boolean checkForm(int number) { 58 | return argc == number; 59 | } 60 | 61 | public Type getType() { 62 | return this.type; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SymTable/FuncFormVar.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class FuncFormVar implements SymItem{ 6 | public String name; 7 | private int dimension; 8 | private ArrayList shape; 9 | public int addr; 10 | public String loc; 11 | 12 | public FuncFormVar(String name, int dimension, ArrayList shape, String loc) { 13 | this.name = name; 14 | this.dimension = dimension; 15 | this.shape = shape; 16 | this.loc = loc; 17 | } 18 | 19 | public String getName() { 20 | return this.name; 21 | } 22 | 23 | public boolean isConst() { 24 | return false; 25 | } 26 | 27 | @Override 28 | public String get_loc() { 29 | return this.loc; 30 | } 31 | 32 | @Override 33 | public int set_addr(int addr) { 34 | this.addr = addr; 35 | return this.addr + 4; 36 | } 37 | 38 | @Override 39 | public Integer getAddr() { 40 | return this.addr; 41 | } 42 | 43 | @Override 44 | public Integer getSize() { 45 | int size = 1; 46 | for (Integer dimensionSize: shape) { 47 | size *= dimensionSize; 48 | } 49 | return size * 4; 50 | } 51 | 52 | @Override 53 | public String getUniqueName() { 54 | return this.name + "@" + loc; 55 | } 56 | 57 | public int getDimension() { 58 | return this.dimension; 59 | } 60 | public ArrayList getShape() { 61 | return this.shape; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SymTable/Lval.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | public class Lval { 4 | } 5 | -------------------------------------------------------------------------------- /SymTable/SymItem.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | public interface SymItem { 4 | public String getName(); 5 | boolean isConst(); 6 | public String get_loc(); 7 | public int set_addr(int addr); 8 | public Integer getAddr(); 9 | public Integer getSize(); 10 | 11 | String getUniqueName(); 12 | } 13 | -------------------------------------------------------------------------------- /SymTable/SymLinker.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | import front.ASD.ASDNode; 4 | import front.ASD.Block; 5 | import front.ASD.ConstDef; 6 | import front.ASD.ConstInitVal; 7 | import front.ASD.Exp; 8 | import front.ASD.FormatString; 9 | import front.ASD.FuncDef; 10 | import front.ASD.FuncFParam; 11 | import front.ASD.FuncFParams; 12 | import front.ASD.FuncType; 13 | import front.ASD.Indent; 14 | import front.ASD.InitVal; 15 | import front.ASD.ErrorRepresent; 16 | import front.ASD.IntConst; 17 | import front.ASD.LVal; 18 | import front.ASD.MainFuncDef; 19 | import front.ASD.PrimaryExp; 20 | import front.ASD.Stmt; 21 | import front.ASD.UnaryExp; 22 | import front.ASD.VarDef; 23 | import front.Error; 24 | import front.ErrorRecorder; 25 | import front.Token; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | import java.util.ArrayList; 29 | import java.util.Comparator; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | import java.util.Stack; 33 | 34 | public class SymLinker { 35 | private final Stack stack = new Stack<>(); 36 | private final HashMap blockLoc2table = new HashMap<>(); 37 | public final HashMap node2tableItem = new HashMap<>(); 38 | private final ASDNode root; 39 | private SymbolTable currentTable; 40 | private final HashMap> funcSymbolsTables = new HashMap<>(); 41 | private ArrayList funcTable = new ArrayList<>(); 42 | private final ArrayList symbolTables = new ArrayList<>(); 43 | private final Stack tableStack = new Stack<>(); 44 | private final int[] depths = new int[100]; 45 | private int currentDepth; 46 | private final HashMap name2Table = new HashMap<>(); 47 | private String currentFucName; 48 | private boolean inAssign = false; 49 | private SymbolTable currentFormVarTable; // for recursive-call only 50 | public SymLinker(ASDNode root) { 51 | this.root = root; 52 | this.currentDepth = 0; 53 | for (int i = 0; i < 100; i += 1) { 54 | depths[i] = 0; 55 | } 56 | } 57 | 58 | String get_loc() { 59 | return "<" + currentDepth + "," + (depths[currentDepth] > 0 ? depths[currentDepth] - 1 : 0) + ">"; 60 | } 61 | 62 | public HashMap getBlockLoc2table() { 63 | return this.blockLoc2table; 64 | } 65 | 66 | public HashMap> getFuncTable() { 67 | HashMap> res = new HashMap<>(); 68 | for (Map.Entry> pair : funcSymbolsTables.entrySet()) { 69 | String funcName = pair.getKey(); 70 | ArrayList funcTable = new ArrayList<>(); 71 | int addr = 4; 72 | ArrayList tables = pair.getValue(); 73 | tables.sort(Comparator.comparing(a -> a.int_loc[0])); 74 | for (SymbolTable table : pair.getValue()) { 75 | for (SymItem item : table.symItems) { 76 | addr = item.set_addr(addr); 77 | funcTable.add(item); 78 | } 79 | } 80 | res.put(funcName, funcTable); 81 | } 82 | return res; 83 | } 84 | 85 | public void travel_to_link_value(ASDNode node) { 86 | if (node == null) { 87 | return; 88 | } 89 | if (node instanceof PrimaryExp && ((PrimaryExp) node).lVal != null) { 90 | LVal lVal = ((PrimaryExp) node).lVal; 91 | SymItem item = findInStack(lVal.indent.getName(), lVal.indent, "Var", false); 92 | if (item == null) { 93 | return; 94 | } 95 | if (item.isConst() && item instanceof Var) { 96 | Var var = (Var) item; 97 | ArrayList initValues = new ArrayList<>(); 98 | var.constInitVal.getInitValue(initValues); 99 | if (lVal.exps.size() == ((Var) item).getShape().size()) { 100 | String value = ""; 101 | if (lVal.exps.size() == 0) { 102 | value = initValues.get(0); 103 | } else if (lVal.exps.size() == 1) { 104 | if (lVal.exps.get(0).getValue() != null) { //constExp 105 | value = initValues.get(lVal.exps.get(0).getValue()); 106 | } 107 | } else if (lVal.exps.size() == 2) { 108 | if (lVal.exps.get(0).getValue() != null && lVal.exps.get(1).getValue() != null) { 109 | value = initValues.get(var.getShape().get(1) * lVal.exps.get(0).getValue() + lVal.exps.get(1).getValue()); 110 | } 111 | } 112 | if (!value.equals("")) { 113 | ((PrimaryExp) node).value = value; 114 | } 115 | } 116 | } 117 | } 118 | for (ASDNode asdNode: node.getChild()) { 119 | travel_to_link_value(asdNode); 120 | } 121 | } 122 | 123 | private void travel(ASDNode node, ASDNode funcFormalArgs) throws Error { 124 | if (node == null) { 125 | return; 126 | } 127 | if (node instanceof MainFuncDef) { 128 | funcTable = new ArrayList<>(); 129 | } 130 | 131 | if (node instanceof Block) { 132 | currentDepth += 1; 133 | currentTable = new SymbolTable(new int[]{currentDepth, depths[currentDepth]}); 134 | blockLoc2table.put("<" + currentDepth + "," + depths[currentDepth] + ">", currentTable); 135 | tableStack.push(currentTable); 136 | depths[currentDepth] += 1; 137 | if (funcFormalArgs != null) { //函数块, 将形参加入符号表 138 | addFormalArgs(funcFormalArgs); 139 | } 140 | } 141 | if (node instanceof VarDef) { 142 | VarDef varDef = (VarDef) node; 143 | checkTable(varDef.getName(), varDef.getIndent(), "Var"); 144 | String name = varDef.getName(); 145 | for (ASDNode asdNode : node.getChild()) { 146 | travel(asdNode, null); 147 | } 148 | InitVal initVal = varDef.getInitVal(); 149 | SymItem item = new Var(name, false, initVal, varDef.getDimension(), varDef.getArrayShape(), get_loc()); 150 | currentTable.symItems.add(item); 151 | stack.add(item); 152 | node2tableItem.put(((VarDef) node).indent, item); 153 | } else if (node instanceof ConstDef) { 154 | ConstDef constDef = (ConstDef) node; 155 | checkTable(constDef.getName(), constDef.getIndent(), "Var"); 156 | String name = constDef.getName(); 157 | for (ASDNode asdNode : node.getChild()) { 158 | travel(asdNode, null); 159 | } 160 | ConstInitVal constInitVal = constDef.getInitVal(); 161 | SymItem item = new Var(name, true, constInitVal, constDef.getDimension(), constDef.getArrayShape(), get_loc()); 162 | currentTable.symItems.add(item); 163 | stack.add(item); 164 | node2tableItem.put(((ConstDef) node).indent, item); 165 | } else if (node instanceof FuncDef) { 166 | checkTable(((FuncDef) node).getName(), ((FuncDef) node).getIndent(), "Func"); 167 | String name = ((FuncDef) node).getName(); 168 | Integer argc = ((FuncDef) node).getArgc(); 169 | Func.Type type = ((FuncDef) node).getType().equals(FuncType.Type.Int) ? Func.Type.intFunc : Func.Type.voidFunc; 170 | SymItem item = new Func(name, type, argc, get_loc()); 171 | currentFucName = ((FuncDef) node).getName(); 172 | currentTable.symItems.add(item); 173 | stack.add(item); 174 | node2tableItem.put(((FuncDef) node).getIndent(), item); 175 | funcTable = new ArrayList<>(); 176 | travel_to_link_value(node.getChild().get(node.getChild().size() - 3)); 177 | travel(node.getChild().get(node.getChild().size() - 2), node.getChild().get(node.getChild().size() - 3)); //函数形参需要加入符号表 178 | funcSymbolsTables.put(name, (ArrayList) funcTable.clone()); 179 | funcTable = new ArrayList<>(); 180 | return; 181 | } else if (node instanceof UnaryExp && ((UnaryExp) node).type.equals(UnaryExp.Type.FuncCall)) { 182 | Indent indent = (Indent) node.getChild().get(0); 183 | SymItem item = findInStack(((UnaryExp) node).getFuncCallName(), indent, "Func", true); 184 | int size = 0; 185 | if (node.getChild().size() > 1) { 186 | size = node.getChild().get(1).getChild().size(); 187 | } 188 | if (item != null && !((Func) item).checkForm(size)) { 189 | ErrorRecorder.recordError(new Error(Error.Type.func_arg_cnt_mismatch, indent.getLineNum())); 190 | } else { 191 | if (node.getChild().size() > 1) { 192 | String funcName = ((Indent) node.getChild().get(0)).getName(); 193 | SymbolTable table = name2Table.get(funcName); 194 | if (funcName == null) { 195 | return; 196 | } 197 | if (table == null && funcName.equals(currentFucName)) { // recursive_call 198 | table = currentFormVarTable; 199 | if (currentTable == null) { 200 | return; 201 | } 202 | } 203 | if (!(table == null)) { // happen when no name find! 204 | int index = 0; 205 | ArrayList realShape = null; 206 | for (ASDNode nod : node.getChild().get(1).getChild()) { 207 | Exp exp = (Exp) nod; 208 | int formDimension = 0; 209 | if (exp.getName() != null) { 210 | SymItem funcCall = findInStack(exp.getName(), indent, "Func", false); 211 | if (funcCall != null) { 212 | if (((Func) funcCall).getType().equals(Func.Type.voidFunc) && exp.isFunCall()) { 213 | ErrorRecorder.recordError(new Error(Error.Type.func_arg_type_mismatch, indent.getLineNum())); 214 | index += 1; 215 | continue; 216 | } else if (((Func) funcCall).getType().equals(Func.Type.intFunc) && exp.isFunCall()) { 217 | if (((FuncFormVar) table.getTable().get(index)).getDimension() != 0) { 218 | ErrorRecorder.recordError(new Error(Error.Type.func_arg_type_mismatch, indent.getLineNum())); 219 | } 220 | index += 1; 221 | continue; 222 | } 223 | } 224 | SymItem symItem = findInStack(exp.getName(), null, "Var", false); 225 | if (symItem == null) { 226 | break; 227 | } 228 | int var_dimension; 229 | if (symItem instanceof Var) { 230 | var_dimension = ((Var) symItem).getDimension(); 231 | } else { 232 | var_dimension = ((FuncFormVar) symItem).getDimension(); 233 | } 234 | formDimension = var_dimension - exp.getDimension(); 235 | } 236 | if (((FuncFormVar) table.getTable().get(index)).getDimension() != formDimension) { 237 | ErrorRecorder.recordError(new Error(Error.Type.func_arg_type_mismatch, indent.getLineNum())); 238 | } 239 | index += 1; 240 | } 241 | } 242 | } 243 | } 244 | node2tableItem.put(node, item); 245 | } else if (node instanceof Stmt && (((Stmt) node).getType().equals(Stmt.Type.Assign) || 246 | ((Stmt) node).getType().equals(Stmt.Type.input))) { 247 | this.inAssign = true; 248 | Indent indent = (Indent) node.getChild().get(0).getChild().get(0); 249 | SymItem item = findInStack(indent.getName(), indent, "Var", true); 250 | if (item != null && item.isConst()) { 251 | ErrorRecorder.recordError(new Error(Error.Type.changeConst, indent.getLineNum())); 252 | } 253 | node2tableItem.put(indent, item); 254 | } else if (node instanceof Stmt && ((Stmt) node).getType().equals(Stmt.Type.output)) { 255 | Token token = ((ErrorRepresent) node.getChild().get(0)).getToken(); 256 | FormatString formatString = ((FormatString) node.getChild().get(1)); 257 | if (formatString.getFormatCharNum() != node.getChild().size() - 2) { 258 | ErrorRecorder.recordError(new Error(Error.Type.printf_num_miss_match, token.getLineNum())); 259 | } 260 | } else if (node instanceof PrimaryExp && ((PrimaryExp) node).lVal != null) { 261 | Indent indent = (Indent) ((PrimaryExp) node).lVal.getChild().get(0); 262 | SymItem item = findInStack(indent.getName(), indent, "Var", true); 263 | node2tableItem.put(indent, item); 264 | } 265 | 266 | for (ASDNode childNode : node.getChild()) { 267 | travel(childNode, null); 268 | } 269 | 270 | if (node instanceof Block) { 271 | if (funcFormalArgs != null) { 272 | name2Table.put(currentFucName, currentTable); 273 | } 274 | currentDepth -= 1; 275 | popFromStack(); 276 | } else if (node instanceof Stmt && (((Stmt) node).getType().equals(Stmt.Type.Assign) || 277 | ((Stmt) node).getType().equals(Stmt.Type.input))) { 278 | this.inAssign = false; 279 | } 280 | 281 | if (node instanceof PrimaryExp && ((PrimaryExp) node).lVal != null) { 282 | LVal lVal = ((PrimaryExp) node).lVal; 283 | SymItem item = findInStack(lVal.indent.getName(), lVal.indent, "Var", false); 284 | if (item == null) { 285 | return; 286 | } 287 | if (item.isConst() && item instanceof Var) { 288 | Var var = (Var) item; 289 | ArrayList initValues = new ArrayList<>(); 290 | var.constInitVal.getInitValue(initValues); 291 | if (lVal.exps.size() == ((Var) item).getShape().size()) { 292 | String value = ""; 293 | if (lVal.exps.size() == 0) { 294 | value = initValues.get(0); 295 | } else if (lVal.exps.size() == 1) { 296 | if (lVal.exps.get(0).getValue() != null) { //constExp 297 | value = initValues.get(lVal.exps.get(0).getValue()); 298 | } 299 | } else if (lVal.exps.size() == 2) { 300 | if (lVal.exps.get(0).getValue() != null && lVal.exps.get(1).getValue() != null) { 301 | value = initValues.get(var.getShape().get(1) * lVal.exps.get(0).getValue() + lVal.exps.get(1).getValue()); 302 | } 303 | } 304 | if (!value.equals("")) { 305 | ((PrimaryExp) node).value = value; 306 | } 307 | } 308 | } 309 | } 310 | } 311 | 312 | private void addFormalArgs(ASDNode funcFormalArgs) throws Error { 313 | FuncFParams params = (FuncFParams) funcFormalArgs; 314 | currentFormVarTable = new SymbolTable(new int[]{-1, -1}); 315 | for (FuncFParam param : params.getFuncFParams()) { 316 | String name = param.getName(); 317 | checkTable(name, param.getIndent(), "Var"); 318 | int dimension = param.getDimension(); 319 | FuncFormVar formVar = new FuncFormVar(name, dimension, param.getShape(), "<" + currentDepth + "," + depths[currentDepth + 1] + ">"); 320 | currentTable.symItems.add(formVar); 321 | stack.add(formVar); 322 | node2tableItem.put(param.indent, formVar); 323 | currentFormVarTable.symItems.add(formVar); 324 | } 325 | } 326 | 327 | private SymItem findInStack(String name, Indent indent, String type, boolean checkError) { 328 | ArrayList items = new ArrayList<>(stack); 329 | for (int i = items.size() - 1; i >= 0; i -= 1) { 330 | SymItem item = items.get(i); 331 | if (item.getName().equals(name)) { 332 | if (item instanceof Func && type.equals("Func")) { 333 | return item; 334 | } else if ((item instanceof Var || item instanceof FuncFormVar) && type.equals("Var")) { 335 | return item; 336 | } 337 | } 338 | } 339 | if (checkError) ErrorRecorder.recordError(new Error(Error.Type.undefined_name, indent.getLineNum())); 340 | return null; //返回null一定要检查! 341 | } 342 | 343 | private void checkTable(String name, Indent indent, String type) { 344 | for (SymItem item : currentTable.symItems) { 345 | if (item.getName().equals(name) && ((type.equals("Func") && item instanceof Func) || ((item instanceof Var || item instanceof FuncFormVar) && type.equals("Var")))) { 346 | ErrorRecorder.recordError(new Error(Error.Type.name_redefine, indent.getLineNum())); 347 | } 348 | } 349 | } 350 | 351 | private void popFromStack() { 352 | stack.removeAll(currentTable.symItems); 353 | symbolTables.add(currentTable); 354 | funcTable.add(currentTable); 355 | tableStack.pop(); 356 | currentTable = tableStack.peek(); 357 | } 358 | 359 | public void link() { 360 | currentTable = new SymbolTable(new int[]{0, 0}); 361 | tableStack.push(currentTable); 362 | symbolTables.add(currentTable); 363 | try { 364 | travel(root, null); 365 | travelForCheck(root); 366 | funcSymbolsTables.put("main", (ArrayList) funcTable.clone()); 367 | } catch (Error ignored) { 368 | ignored.printStackTrace(); 369 | } 370 | blockLoc2table.put("<0,0>", currentTable); 371 | } 372 | 373 | private enum BlockType { 374 | whileBlock, voidFuncBlock, intFuncBlock 375 | } 376 | 377 | private final Stack blockStack = new Stack<>(); 378 | private int returnNum; 379 | 380 | private void travelForCheck(ASDNode node) { 381 | if (node == null) { 382 | return; 383 | } 384 | if (node instanceof FuncDef && ((FuncDef) node).getType().equals(FuncType.Type.Void)) { 385 | blockStack.add(BlockType.voidFuncBlock); 386 | returnNum = 0; 387 | } else if (node instanceof FuncDef && ((FuncDef) node).getType().equals(FuncType.Type.Int)) { 388 | blockStack.add(BlockType.intFuncBlock); 389 | returnNum = 0; 390 | Block block = (Block) node.getChild().get(node.getChild().size() - 2); 391 | if (block.getChild().size() != 0) { 392 | ASDNode stmt = block.getChild().get(block.getChild().size() - 1).getChild().get(0); 393 | if (!(stmt instanceof Stmt 394 | && ((Stmt) stmt).getType().equals(Stmt.Type.returnStmt))) { 395 | ErrorRecorder.recordError(new Error(Error.Type.non_void_non_return, 396 | ((ErrorRepresent) node.getChild().get(node.getChild().size() - 1)).getToken().getLineNum())); 397 | } 398 | } else { 399 | ErrorRecorder.recordError(new Error(Error.Type.non_void_non_return, 400 | ((ErrorRepresent) node.getChild().get(node.getChild().size() - 1)).getToken().getLineNum())); 401 | } 402 | } else if (node instanceof MainFuncDef) { 403 | blockStack.add(BlockType.intFuncBlock); 404 | Block block = (Block) node.getChild().get(node.getChild().size() - 2); 405 | boolean noReturn = false; 406 | if (block.getChild().size() != 0) { 407 | ASDNode stmt = block.getChild().get(block.getChild().size() - 1).getChild().get(0); 408 | if (!(stmt instanceof Stmt 409 | && ((Stmt) stmt).getType().equals(Stmt.Type.returnStmt))) { 410 | ErrorRecorder.recordError(new Error(Error.Type.non_void_non_return, 411 | ((ErrorRepresent) node.getChild().get(node.getChild().size() - 1)).getToken().getLineNum())); 412 | } 413 | } else { 414 | ErrorRecorder.recordError(new Error(Error.Type.non_void_non_return, 415 | ((ErrorRepresent) node.getChild().get(node.getChild().size() - 1)).getToken().getLineNum())); 416 | } 417 | } else if (node instanceof Stmt) { 418 | Stmt.Type type = ((Stmt) node).getType(); 419 | if (type.equals(Stmt.Type.whileBranch)) { 420 | blockStack.add(BlockType.whileBlock); 421 | } else if (type.equals(Stmt.Type.returnStmt)) { 422 | if (node.getChild().size() > 1 && blockStack.peek().equals(BlockType.voidFuncBlock)) { 423 | ErrorRecorder.recordError(new Error(Error.Type.void_return, 424 | ((ErrorRepresent) node.getChild().get(0)).getToken().getLineNum())); 425 | returnNum += 1; 426 | } else if (blockStack.peek().equals(BlockType.intFuncBlock)) { 427 | returnNum += 1; 428 | } 429 | } else if (type.equals(Stmt.Type.breakStmt) || type.equals(Stmt.Type.continueStmt)) { 430 | if (!blockStack.peek().equals(BlockType.whileBlock)) { 431 | ErrorRecorder.recordError(new Error(Error.Type.misused_BC, 432 | ((ErrorRepresent) node.getChild().get(0)).getToken().getLineNum())); 433 | } 434 | } 435 | } 436 | for (ASDNode childNode : node.getChild()) { 437 | travelForCheck(childNode); 438 | } 439 | if (node instanceof FuncDef && ((FuncDef) node).getType().equals(FuncType.Type.Int) 440 | || node instanceof MainFuncDef) { 441 | if (!blockStack.isEmpty() && blockStack.peek().equals(BlockType.intFuncBlock) && returnNum == 0) { 442 | ErrorRecorder.recordError(new Error(Error.Type.non_void_non_return, 443 | ((ErrorRepresent) node.getChild().get(node.getChild().size() - 1)).getToken().getLineNum())); 444 | blockStack.pop(); 445 | } 446 | } else if (node instanceof FuncDef && ((FuncDef) node).getType().equals(FuncType.Type.Void)) { 447 | if (blockStack.peek().equals(BlockType.voidFuncBlock)) { 448 | blockStack.pop(); 449 | } 450 | } else if (node instanceof Stmt && ((Stmt) node).getType().equals(Stmt.Type.whileBranch)) { 451 | blockStack.pop(); 452 | } 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /SymTable/SymbolTable.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class SymbolTable { 6 | public final ArrayList symItems = new ArrayList<>(); 7 | public String loc; 8 | public Integer[] int_loc; 9 | 10 | public SymbolTable(int[] indent) { 11 | this.loc = "<" + indent[0] + "," + indent[1] + ">"; 12 | int_loc = new Integer[]{indent[0], indent[1]}; 13 | } 14 | 15 | public ArrayList getTable() { 16 | return this.symItems; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SymTable/Var.java: -------------------------------------------------------------------------------- 1 | package SymTable; 2 | 3 | import front.ASD.ConstInitVal; 4 | import front.ASD.InitVal; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class Var implements SymItem{ 9 | private String name; 10 | private boolean isConst; 11 | private InitVal initVal; 12 | public ConstInitVal constInitVal; 13 | public int addr; 14 | private int dimension; 15 | private ArrayList shape; 16 | public String loc; 17 | 18 | public Var(String name, boolean isConst, InitVal initVal, int dimension, ArrayList shape, String loc) { 19 | this.name = name; 20 | this.isConst = isConst; 21 | this.initVal = initVal; 22 | this.constInitVal = null; 23 | this.dimension = dimension; 24 | this.shape = shape; 25 | this.loc = loc; 26 | } 27 | 28 | public Var(String name, boolean isConst, ConstInitVal constInitVal, int dimension, ArrayList shape, String loc) { 29 | this.name = name; 30 | this.isConst = isConst; 31 | this.constInitVal = constInitVal; 32 | this.dimension = dimension; 33 | this.shape = shape; 34 | this.loc = loc; 35 | } 36 | 37 | public String getName() { 38 | return this.name; 39 | } 40 | public boolean isConst() { 41 | return this.isConst; 42 | } 43 | 44 | @Override 45 | public String get_loc() { 46 | return this.loc; 47 | } 48 | 49 | @Override 50 | public int set_addr(int addr) { 51 | int size = 1; 52 | for (Integer dimensionSize: shape) { 53 | size *= dimensionSize; 54 | } 55 | this.addr = addr; 56 | return this.addr + size * 4; 57 | } 58 | 59 | @Override 60 | public Integer getAddr() { 61 | return this.addr; 62 | } 63 | 64 | @Override 65 | public Integer getSize() { 66 | int size = 1; 67 | for (Integer dimensionSize: shape) { 68 | size *= dimensionSize; 69 | } 70 | return size * 4; 71 | } 72 | 73 | @Override 74 | public String getUniqueName() { 75 | if (this.name.charAt(0) == '#') { 76 | return this.name; 77 | } 78 | return this.name + "@" + this.loc; 79 | } 80 | 81 | public int getDimension() { 82 | return this.dimension; 83 | } 84 | 85 | public ArrayList getShape() { 86 | return this.shape; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /back/RegAlloc.java: -------------------------------------------------------------------------------- 1 | package back; 2 | 3 | import SymTable.SymItem; 4 | import mid.Block; 5 | import mid.MidCode; 6 | import mid.VarConfliction; 7 | 8 | import javax.print.attribute.HashAttributeSet; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.HashSet; 12 | import java.util.Map; 13 | 14 | public class RegAlloc { 15 | public static final HashMap> funcVars = VarConfliction.funcVars; 16 | public static final HashMap var_weight = VarConfliction.var_weight; 17 | public static final HashMap> funcVarByWeight = new HashMap>() { 18 | private int compare(String x1, String x2) { 19 | return (var_weight.get(x1) - var_weight.get(x2)); 20 | } 21 | 22 | { 23 | for (Map.Entry> funcVar: funcVars.entrySet()) { 24 | ArrayList vars = new ArrayList<>(funcVar.getValue()); 25 | vars.sort(this::compare); 26 | put(funcVar.getKey(), vars); 27 | } 28 | }}; 29 | 30 | public static final ArrayList blocks = VarConfliction.blocks; 31 | 32 | public static final HashMap midCode2Bno = VarConfliction.midCode2Bno; 33 | 34 | public HashMap bno2block = new HashMap(){{ 35 | for (Block block: VarConfliction.blocks) { 36 | bno2block.put(block.bno, block); 37 | } 38 | }}; 39 | 40 | 41 | public static ArrayList reg_pool = new ArrayList(){{ 42 | for (int i = 0; i < 8; i++) { 43 | add("$s" + i); 44 | } 45 | add("$fp"); 46 | }}; 47 | 48 | public static String alloc_reg(String VarName, String funcName) { 49 | ArrayList funcTable = funcVarByWeight.get(funcName); 50 | int i = funcTable.indexOf(VarName); 51 | if (i > 8) { 52 | return null; 53 | } 54 | return reg_pool.get(i); 55 | } 56 | 57 | public static final HashMap> alive_vars = new HashMap>(){{ 58 | for (Block block: blocks) { 59 | for (int i = 0; i < block.midCodes.size(); i++) { 60 | HashSet alive_var = new HashSet<>(block.out); 61 | alive_var.addAll(block.in); 62 | for (int j = i + 1; j < block.midCodes.size(); j++) { 63 | alive_var.addAll(block.midCodes.get(j).get_use()); 64 | } 65 | put(block.midCodes.get(i), alive_var); 66 | } 67 | } 68 | }}; 69 | 70 | public static void try_release_s_reg(ArrayList sRegTable, MidCode midCode, ArrayList mipsCodes) { 71 | for (String s_reg: sRegTable) { 72 | if (s_reg.equals("#VACANT")) { 73 | return; 74 | } 75 | } 76 | if (alive_vars.containsKey(midCode)) { 77 | for (int i = 0; i < sRegTable.size(); i++) { 78 | String var = sRegTable.get(i); 79 | if (midCode.get_use().contains(sRegTable.get(i)) || (midCode.get_def() != null) && midCode.get_def().equals(sRegTable.get(i))) { 80 | continue; 81 | } 82 | if (!var.startsWith("#") && var_weight.containsKey(var) && var_weight.get(var) < 30 && !alive_vars.get(midCode).contains(var)) { 83 | mipsCodes.add("# release s_reg["+i+"] bind " + sRegTable.get(i)); 84 | sRegTable.set(i, "#VACANT"); 85 | return; 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /back/utils.java: -------------------------------------------------------------------------------- 1 | package back; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import static java.lang.Math.log; 6 | 7 | public class utils { 8 | public static final int N = 32; 9 | public static final Pattern IS_DIGIT = Pattern.compile("[0-9]*"); 10 | public static boolean begins_num(String operand) { 11 | return IS_DIGIT.matcher(operand).matches() || operand.charAt(0) == '+' || operand.charAt(0) == '-'; 12 | } 13 | 14 | public static boolean is_2_power(Integer integer) { 15 | int x = integer; 16 | return (x & (x - 1)) == 0; 17 | } 18 | 19 | public static long[] choose_multiplier(int d, int prec) { 20 | long l = (long) Math.ceil((Math.log(d) / Math.log(2))); 21 | long sh_post = l; 22 | long m_low = (long) Math.floor(Math.pow(2, N+l)/d); 23 | long m_high = (long) Math.floor((Math.pow(2, N+l) + Math.pow(2, N+l-prec))/d); 24 | while ((Math.floor(m_low >> 1) < Math.floor(m_high >> 1)) && sh_post>0) { 25 | m_low = (long) Math.floor(m_low >> 1); 26 | m_high = (long) Math.floor(m_high >> 1); 27 | sh_post = sh_post - 1; 28 | } 29 | return new long[]{m_high, sh_post, l}; 30 | } 31 | 32 | public static int log2(Integer integer) { 33 | return (int) Math.floor(Math.log(integer) / Math.log(2)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /div_alg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunzeY/SysCompiler/662344a2a05b849fb4fbb1770e37a93a36c96879/div_alg1.png -------------------------------------------------------------------------------- /div_alg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunzeY/SysCompiler/662344a2a05b849fb4fbb1770e37a93a36c96879/div_alg2.png -------------------------------------------------------------------------------- /front/ASD/ASDNode.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import java.util.ArrayList; 4 | 5 | public interface ASDNode { 6 | public void printTestInfo(); 7 | public void linkWithSymbolTable(); 8 | ArrayList getChild(); 9 | 10 | public String gen_mid(mid.MidCodeList midCodeList); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /front/ASD/AddExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import front.Token; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class AddExp implements ASDNode{ 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | public ArrayList Ops; 12 | public ArrayList mulExps; 13 | 14 | public AddExp(ArrayList Ops, ArrayList mulExps) { 15 | this.Ops = Ops; 16 | this.mulExps = mulExps; 17 | asdNodes.addAll(mulExps); 18 | } 19 | 20 | @Override 21 | public void printTestInfo() { 22 | int i = 0; 23 | for (MulExp mulExp: mulExps) { 24 | mulExp.printTestInfo(); 25 | System.out.println(""); 26 | if (i < Ops.size()) { 27 | System.out.println(Ops.get(i).toString()); 28 | } 29 | i += 1; 30 | } 31 | } 32 | 33 | @Override 34 | public void linkWithSymbolTable() { 35 | } 36 | 37 | @Override 38 | public ArrayList getChild() { 39 | return asdNodes; 40 | } 41 | 42 | @Override 43 | public String gen_mid(MidCodeList midCodeList) { 44 | try { 45 | return Integer.toString(this.getValue()); 46 | } catch (Error ignored) { 47 | } 48 | String op1 = mulExps.get(0).gen_mid(midCodeList); 49 | String result = op1; 50 | for (int i =0; i < Ops.size(); i += 1) { 51 | String op2 = mulExps.get(i+1).gen_mid(midCodeList); 52 | mid.MidCode.Op op = Ops.get(i).getTokenClass().equals("PLUS") ? mid.MidCode.Op.ADD : mid.MidCode.Op.SUB; 53 | result = midCodeList.add(op, op1, op2, "#AUTO"); 54 | op1 = result; 55 | } 56 | return result; 57 | } 58 | 59 | public int getDimension() { 60 | if (!Ops.isEmpty()) { 61 | return 0; 62 | } 63 | return this.mulExps.get(0).getDimension(); 64 | } 65 | 66 | public String getName() { 67 | if (!Ops.isEmpty()) { 68 | return null; 69 | } 70 | return this.mulExps.get(0).getName(); 71 | } 72 | 73 | public int getValue() throws Error { 74 | int value = mulExps.get(0).getValue(); 75 | for (int index = 1; index < mulExps.size(); index += 1) { 76 | if (Ops.get(index-1).toString().equals("PLUS +")) { 77 | value = value + mulExps.get(index).getValue(); 78 | } else { 79 | value = value - mulExps.get(index).getValue(); 80 | } 81 | } 82 | return value; 83 | } 84 | 85 | public boolean isFunCall() { 86 | return this.mulExps.size() == 1 && mulExps.get(0).isFunCall(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /front/ASD/BType.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class BType implements ASDNode{ 8 | 9 | private final ArrayList asdNodes = new ArrayList<>(); 10 | public enum Type{ 11 | Int 12 | } 13 | private Type type; 14 | 15 | public BType(Type type) { 16 | this.type = type; 17 | } 18 | 19 | @Override 20 | public void printTestInfo() { 21 | System.out.println("INTTK int"); 22 | } 23 | 24 | @Override 25 | public void linkWithSymbolTable() { 26 | } 27 | 28 | @Override 29 | public ArrayList getChild() { 30 | return asdNodes; 31 | } 32 | 33 | @Override 34 | public String gen_mid(MidCodeList midCodeList) { 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /front/ASD/Block.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class Block implements ASDNode{ 9 | private ArrayList blockItems; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | public Block(ArrayList blockItems) { 12 | this.blockItems = blockItems; 13 | asdNodes.addAll(blockItems); 14 | } 15 | 16 | 17 | @Override 18 | public void printTestInfo() { 19 | System.out.println("LBRACE {"); 20 | for (BlockItem blockItem: blockItems) { 21 | blockItem.printTestInfo(); 22 | } 23 | System.out.println("RBRACE }"); 24 | System.out.println(""); 25 | } 26 | 27 | @Override 28 | public void linkWithSymbolTable() { 29 | } 30 | 31 | @Override 32 | public ArrayList getChild() { 33 | return asdNodes; 34 | } 35 | 36 | @Override 37 | public String gen_mid(MidCodeList midCodeList) { 38 | midCodeList.add(MidCode.Op.NEW_BLOCK, "#VACANT", "#VACANT", "#VACANT"); 39 | for (BlockItem blockItem: blockItems) { 40 | blockItem.gen_mid(midCodeList); 41 | } 42 | midCodeList.add(MidCode.Op.EXIT_BLOCK, "#VACANT", "#VACANT", "#VACANT"); 43 | return ""; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /front/ASD/BlockItem.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class BlockItem implements ASDNode{ 8 | private Decl decl; 9 | private Stmt stmt; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public BlockItem(Decl decl) { 13 | this.decl = decl; 14 | this.stmt = null; 15 | asdNodes.add(decl); 16 | } 17 | 18 | public BlockItem(Stmt stmt) { 19 | this.stmt = stmt; 20 | this.decl = null; 21 | asdNodes.add(stmt); 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | if (this.decl == null) { 27 | this.stmt.printTestInfo(); 28 | } else { 29 | this.decl.printTestInfo(); 30 | } 31 | //System.out.println(""); 32 | } 33 | 34 | @Override 35 | public void linkWithSymbolTable() { 36 | 37 | } 38 | 39 | @Override 40 | public ArrayList getChild() { 41 | return asdNodes; 42 | } 43 | 44 | @Override 45 | public String gen_mid(MidCodeList midCodeList) { 46 | if (this.decl == null) { 47 | this.stmt.gen_mid(midCodeList); 48 | } else { 49 | this.decl.gen_mid(midCodeList); 50 | } 51 | return ""; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /front/ASD/CompUnit.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.io.IOException; 6 | import java.io.PrintStream; 7 | import java.util.ArrayList; 8 | 9 | public class CompUnit implements ASDNode { 10 | 11 | private ArrayList decls; 12 | private ArrayList funcDefs; 13 | private MainFuncDef mainDuncDef; 14 | private final ArrayList asdNodes = new ArrayList<>(); 15 | public CompUnit(ArrayList decls, ArrayList funcDefs, MainFuncDef mainDuncDef) { 16 | this.decls = decls; 17 | this.funcDefs = funcDefs; 18 | this.mainDuncDef = mainDuncDef; 19 | asdNodes.addAll(decls); 20 | asdNodes.addAll(funcDefs); 21 | asdNodes.add(mainDuncDef); 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | PrintStream out = System.out; 27 | try { 28 | PrintStream os = new PrintStream("output.txt"); 29 | System.setOut(os); 30 | } catch (IOException ignored) { 31 | } 32 | 33 | for (Decl decl: decls) { 34 | decl.printTestInfo(); 35 | } 36 | for (FuncDef funcDef: funcDefs) { 37 | funcDef.printTestInfo(); 38 | } 39 | mainDuncDef.printTestInfo(); 40 | System.out.println(""); 41 | System.setOut(out); 42 | } 43 | 44 | @Override 45 | public void linkWithSymbolTable() { 46 | } 47 | 48 | @Override 49 | public ArrayList getChild() { 50 | return asdNodes; 51 | } 52 | 53 | @Override 54 | public String gen_mid(MidCodeList midCodeList) { 55 | for (ASDNode asdNode: asdNodes) { 56 | asdNode.gen_mid(midCodeList); 57 | } 58 | return ""; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /front/ASD/Cond.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class Cond implements ASDNode{ 8 | 9 | private LOrExp lOrExp; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public Cond(LOrExp lOrExp) { 13 | this.lOrExp = lOrExp; 14 | asdNodes.add(lOrExp); 15 | } 16 | 17 | @Override 18 | public void printTestInfo() { 19 | lOrExp.printTestInfo(); 20 | System.out.println(""); 21 | } 22 | 23 | @Override 24 | public void linkWithSymbolTable() { 25 | } 26 | 27 | @Override 28 | public ArrayList getChild() { 29 | return asdNodes; 30 | } 31 | 32 | @Override 33 | public String gen_mid(MidCodeList midCodeList) { 34 | return this.asdNodes.get(0).gen_mid(midCodeList); 35 | } 36 | 37 | 38 | public void gen_mid_opt(MidCodeList midCodeList, String else_label, String endIf, ASDNode stmt) { 39 | this.lOrExp.gen_mid_opt(midCodeList, else_label, endIf, stmt); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /front/ASD/ConstDecl.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class ConstDecl implements ASDNode{ 8 | private BType bType; 9 | private ArrayList constDefs; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public ConstDecl(BType bType, ArrayList constDefs) { 13 | this.bType = bType; 14 | this.constDefs = constDefs; 15 | asdNodes.add(bType); 16 | asdNodes.addAll(constDefs); 17 | } 18 | 19 | @Override 20 | public void printTestInfo() { 21 | System.out.println("CONSTTK const"); 22 | System.out.println("INTTK int"); 23 | boolean tag = false; 24 | for (ConstDef constDef: constDefs) { 25 | if (tag) { 26 | System.out.println("COMMA ,"); 27 | } 28 | constDef.printTestInfo(); 29 | tag = true; 30 | } 31 | System.out.println("SEMICN ;"); 32 | System.out.println(""); 33 | } 34 | 35 | @Override 36 | public void linkWithSymbolTable() { 37 | } 38 | 39 | @Override 40 | public ArrayList getChild() { 41 | return asdNodes; 42 | } 43 | 44 | @Override 45 | public String gen_mid(MidCodeList midCodeList) { 46 | for (ConstDef constDef: constDefs) { 47 | constDef.gen_mid(midCodeList); 48 | } 49 | return ""; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /front/ASD/ConstDef.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class ConstDef implements ASDNode{ 10 | public Indent indent; 11 | private ArrayList constExps; 12 | private ConstInitVal constInitVal; 13 | private final ArrayList asdNodes = new ArrayList<>(); 14 | 15 | public ConstDef(Indent indent, ArrayList constExps, ConstInitVal constInitVal) { 16 | this.indent = indent; 17 | this.constExps = constExps; 18 | this.constInitVal = constInitVal; 19 | asdNodes.add(indent); 20 | asdNodes.addAll(constExps); 21 | asdNodes.add(constInitVal); 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | indent.printTestInfo(); 27 | for (ConstExp constExp: constExps) { 28 | System.out.println("LBRACK ["); 29 | constExp.printTestInfo(); 30 | System.out.println("RBRACK ]"); 31 | } 32 | System.out.println("ASSIGN ="); 33 | constInitVal.printTestInfo(); 34 | System.out.println(""); 35 | } 36 | 37 | @Override 38 | public void linkWithSymbolTable() { 39 | } 40 | 41 | @Override 42 | public ArrayList getChild() { 43 | return asdNodes; 44 | } 45 | 46 | @Override 47 | public String gen_mid(MidCodeList midCodeList) { 48 | String name = indent.getName() + "@" + midCodeList.node2symItem.get(indent).get_loc(); 49 | if (constExps.size() == 0) { // not-Array 50 | String value = constInitVal.gen_mid(midCodeList); 51 | midCodeList.add(MidCode.Op.CONST_DEF, name, value, "#VACANT"); 52 | } else { 53 | String value = constInitVal.gen_mid(midCodeList); 54 | assert value.equals("#ARRAY"); 55 | ArrayList initValues = new ArrayList<>(); 56 | constInitVal.getInitValue(initValues); 57 | int index = 0; 58 | for (String res: initValues) { 59 | midCodeList.add(MidCode.Op.ARR_SAVE, name + "[" + index + "]", res, "#VACANT"); 60 | index += 1; 61 | } 62 | } 63 | return ""; 64 | } 65 | 66 | public String getName() { 67 | return this.indent.getName(); 68 | } 69 | 70 | public ConstInitVal getInitVal() { 71 | return this.constInitVal; 72 | } 73 | 74 | public Indent getIndent() { 75 | return this.indent; 76 | } 77 | 78 | public int getDimension() { 79 | return this.constExps.size(); 80 | } 81 | 82 | public ArrayList getArrayShape() throws Error { 83 | ArrayList shape = new ArrayList<>(); 84 | for (ConstExp exp : constExps) { 85 | shape.add(exp.getValue()); 86 | } 87 | return shape; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /front/ASD/ConstExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class ConstExp implements ASDNode{ 9 | private AddExp addExp; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public ConstExp(AddExp addExp) { 13 | this.addExp = addExp; 14 | asdNodes.add(addExp); 15 | } 16 | 17 | @Override 18 | public void printTestInfo() { 19 | addExp.printTestInfo(); 20 | System.out.println(""); 21 | } 22 | 23 | @Override 24 | public void linkWithSymbolTable() { 25 | } 26 | 27 | @Override 28 | public ArrayList getChild() { 29 | return asdNodes; 30 | } 31 | 32 | @Override 33 | public String gen_mid(MidCodeList midCodeList) { 34 | try { 35 | return Integer.toString(this.addExp.getValue()); 36 | } catch (Error ignored) { 37 | } 38 | return this.addExp.gen_mid(midCodeList); 39 | } 40 | 41 | public int getValue() throws Error { 42 | return this.addExp.getValue(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /front/ASD/ConstInitVal.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class ConstInitVal implements ASDNode { 10 | 11 | public enum Type { 12 | mulInitVal, 13 | Exp 14 | } 15 | 16 | private ArrayList asdNodes; 17 | private ConstInitVal.Type type; 18 | 19 | public ConstInitVal(ConstInitVal.Type type, ArrayList asdNodes) { 20 | this.asdNodes = asdNodes; 21 | this.type = type; 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | if (this.type.equals(ConstInitVal.Type.Exp)) { 27 | this.asdNodes.get(0).printTestInfo(); 28 | } else { 29 | System.out.println("LBRACE {"); 30 | boolean tag = false; 31 | for (ASDNode asdNode : asdNodes) { 32 | if (tag) { 33 | System.out.println("COMMA ,"); 34 | } 35 | asdNode.printTestInfo(); 36 | tag = true; 37 | } 38 | System.out.println("RBRACE }"); 39 | } 40 | System.out.println(""); 41 | } 42 | 43 | @Override 44 | public void linkWithSymbolTable() { 45 | } 46 | 47 | @Override 48 | public ArrayList getChild() { 49 | if (asdNodes == null) { 50 | return new ArrayList<>(); 51 | } 52 | return asdNodes; 53 | } 54 | 55 | @Override 56 | public String gen_mid(MidCodeList midCodeList) { 57 | String value = ""; 58 | if (this.type.equals(Type.Exp)) { 59 | try { 60 | value = Integer.toString(((ConstExp) asdNodes.get(0)).getValue()); 61 | } catch (Error ignored) { 62 | value = asdNodes.get(0).gen_mid(midCodeList); // const with special type need gen-mid-code 63 | } 64 | 65 | } else { 66 | // TODO array 67 | value = "#ARRAY"; 68 | } 69 | return value; 70 | } 71 | 72 | public void getInitValue(ArrayList initValues) { 73 | if (this.type.equals(Type.Exp)) { 74 | try { 75 | initValues.add(Integer.toString(((ConstExp) asdNodes.get(0)).getValue())); 76 | } catch (Error ignored) { 77 | } 78 | } else { 79 | for (ASDNode asdNode : asdNodes) { 80 | ((ConstInitVal) asdNode).getInitValue(initValues); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /front/ASD/Decl.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class Decl implements ASDNode { 8 | public ConstDecl constDecl; 9 | public VarDecl varDecl; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public Decl(ConstDecl constDecl) { 13 | this.constDecl = constDecl; 14 | this.varDecl = null; 15 | asdNodes.add(constDecl); 16 | } 17 | 18 | public Decl(VarDecl varDecl) { 19 | this.constDecl = null; 20 | this.varDecl = varDecl; 21 | asdNodes.add(varDecl); 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | if (constDecl != null) { 27 | constDecl.printTestInfo(); 28 | } else { 29 | varDecl.printTestInfo(); 30 | } 31 | // System.out.println(""); 32 | } 33 | 34 | @Override 35 | public void linkWithSymbolTable() { 36 | } 37 | 38 | @Override 39 | public ArrayList getChild() { 40 | return asdNodes; 41 | } 42 | 43 | @Override 44 | public String gen_mid(MidCodeList midCodeList) { 45 | if (constDecl != null) { 46 | constDecl.gen_mid(midCodeList); 47 | } else { 48 | varDecl.gen_mid(midCodeList); 49 | } 50 | return ""; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /front/ASD/EqExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class EqExp implements ASDNode{ 10 | 11 | public ArrayList Ops; 12 | public ArrayList relExps; 13 | private final ArrayList asdNodes = new ArrayList<>(); 14 | 15 | public EqExp(ArrayList Ops, ArrayList relExps) { 16 | this.Ops = Ops; 17 | this.relExps = relExps; 18 | asdNodes.addAll(relExps); 19 | } 20 | 21 | @Override 22 | public void printTestInfo() { 23 | relExps.get(0).printTestInfo(); 24 | System.out.println(""); 25 | for (int i = 0; i < Ops.size(); i++) { 26 | System.out.println(Ops.get(i).toString()); 27 | relExps.get(i+1).printTestInfo(); 28 | System.out.println(""); 29 | } 30 | } 31 | 32 | @Override 33 | public void linkWithSymbolTable() { 34 | } 35 | 36 | @Override 37 | public ArrayList getChild() { 38 | return asdNodes; 39 | } 40 | 41 | @Override 42 | public String gen_mid(MidCodeList midCodeList) { 43 | RelExp left = relExps.get(0); 44 | String true_label = ""; 45 | String bool_var = ""; 46 | if (relExps.size() == 1) { 47 | return relExps.get(0).gen_mid(midCodeList); 48 | } 49 | String left_ans = left.gen_mid(midCodeList); 50 | for (int i = 1; i < relExps.size(); i++) { 51 | bool_var = midCodeList.add(MidCode.Op.ASSIGN, "#AUTO", "1", "#VACANT"); 52 | String op = Ops.get(i-1).getString(); 53 | RelExp right = relExps.get(i); 54 | String right_ans = right.gen_mid(midCodeList); 55 | true_label = midCodeList.add(MidCode.Op.JUMP_IF, left_ans + " " + right_ans, op, "#AUTO_LABEL"); 56 | midCodeList.add(MidCode.Op.ASSIGN, bool_var, "0", "#VACANT"); 57 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", true_label); 58 | left_ans = bool_var; 59 | } 60 | assert !bool_var.equals(""); 61 | return bool_var; 62 | } 63 | 64 | public void gen_mid_opt(MidCodeList midCodeList, String next_or, ASDNode stmt, String end_if, boolean containsIfBlock) { 65 | if (relExps.size() == 1) { 66 | this.relExps.get(0).gen_mid_opt(midCodeList, next_or, stmt, end_if, true, containsIfBlock); 67 | } else { 68 | String left = relExps.get(0).gen_mid_opt(midCodeList, next_or, stmt, end_if, false, containsIfBlock); 69 | for (int i = 1; i < relExps.size(); i++) { 70 | String op = Ops.get(i - 1).getString(); 71 | String right = relExps.get(i).gen_mid_opt(midCodeList, next_or, stmt, end_if, false, containsIfBlock); 72 | if (Ops.size() == i) { 73 | op = reverseOp(op); 74 | midCodeList.add(MidCode.Op.JUMP_IF, left + " " + right, op, next_or); 75 | if (containsIfBlock) { 76 | stmt.gen_mid(midCodeList); 77 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end_if); 78 | } 79 | } else { 80 | left = midCodeList.add(MidCode.Op.SET, left + " " + right, op, "#AUTO"); 81 | } 82 | } 83 | } 84 | } 85 | 86 | public String reverseOp(String op) { 87 | return op.equals("==") ? "!=" : 88 | op.equals("!=") ? "==" : "2333"; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /front/ASD/ErrorRepresent.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.ASD.ASDNode; 4 | import front.Token; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class ErrorRepresent implements ASDNode { 10 | private Token token; 11 | 12 | public ErrorRepresent(Token sym) { 13 | token = sym; 14 | } 15 | 16 | @Override 17 | public void printTestInfo() { 18 | } 19 | 20 | @Override 21 | public void linkWithSymbolTable() { 22 | 23 | } 24 | 25 | @Override 26 | public ArrayList getChild() { 27 | return new ArrayList<>(); 28 | } 29 | 30 | @Override 31 | public String gen_mid(MidCodeList midCodeList) { 32 | return null; 33 | } 34 | 35 | public Token getToken() { 36 | return token; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /front/ASD/Exp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import jdk.nashorn.internal.ir.annotations.Ignore; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class Exp implements ASDNode{ 10 | private AddExp addExp; 11 | private final ArrayList asdNodes = new ArrayList<>(); 12 | 13 | public Exp(AddExp addExp) { 14 | this.addExp = addExp; 15 | asdNodes.add(addExp); 16 | } 17 | 18 | @Override 19 | public void printTestInfo() { 20 | addExp.printTestInfo(); 21 | System.out.println(""); 22 | } 23 | 24 | @Override 25 | public void linkWithSymbolTable() { 26 | } 27 | 28 | @Override 29 | public ArrayList getChild() { 30 | return asdNodes; 31 | } 32 | 33 | @Override 34 | public String gen_mid(MidCodeList midCodeList) { 35 | try { 36 | return Integer.toString(this.addExp.getValue()); 37 | } catch (Error ignored) { 38 | } 39 | return this.addExp.gen_mid(midCodeList); 40 | } 41 | 42 | public int getDimension() { 43 | return addExp.getDimension(); 44 | } 45 | 46 | public String getName() { 47 | return this.addExp.getName(); 48 | } 49 | 50 | public Integer getValue() { 51 | try { 52 | return this.addExp.getValue(); 53 | } catch (Error ignored){ 54 | } 55 | return null; 56 | } 57 | 58 | public boolean isFunCall() { 59 | return this.addExp.isFunCall(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /front/ASD/FormatString.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FormatString implements ASDNode { 9 | private Token token; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public FormatString(Token token) { 13 | this.token = token; 14 | } 15 | 16 | @Override 17 | public void printTestInfo() { 18 | System.out.println(token.toString()); 19 | } 20 | 21 | @Override 22 | public void linkWithSymbolTable() { 23 | } 24 | 25 | @Override 26 | public ArrayList getChild() { 27 | return asdNodes; 28 | } 29 | 30 | @Override 31 | public String gen_mid(MidCodeList midCodeList) { 32 | return null; 33 | } 34 | 35 | public int getFormatCharNum() { 36 | return this.token.getFormatCharNum(); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return this.token.toString(); 42 | } 43 | 44 | public String getString() { 45 | return this.token.getString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /front/ASD/FuncDef.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FuncDef implements ASDNode{ 9 | private FuncType funcType; 10 | private Indent indent; 11 | private FuncFParams funcFParams; 12 | private Block block; 13 | private final ArrayList asdNodes = new ArrayList<>(); 14 | 15 | public FuncDef(FuncType funcType, Indent indent, FuncFParams funcFParams, Block block, ASDNode blockEnd) { 16 | this.funcType = funcType; 17 | this.indent = indent; 18 | this.funcFParams = funcFParams; 19 | this.block = block; 20 | asdNodes.add(funcType); 21 | asdNodes.add(indent); 22 | asdNodes.add(funcFParams); 23 | asdNodes.add(block); 24 | asdNodes.add(blockEnd); 25 | } 26 | 27 | @Override 28 | public void printTestInfo() { 29 | this.funcType.printTestInfo(); 30 | this.indent.printTestInfo(); 31 | System.out.println("LPARENT ("); 32 | this.funcFParams.printTestInfo(); 33 | System.out.println("RPARENT )"); 34 | block.printTestInfo(); 35 | System.out.println(""); 36 | } 37 | 38 | @Override 39 | public void linkWithSymbolTable() { 40 | } 41 | 42 | public String getName() { 43 | return this.indent.getName(); 44 | } 45 | 46 | @Override 47 | public ArrayList getChild() { 48 | return asdNodes; 49 | } 50 | 51 | @Override 52 | public String gen_mid(MidCodeList midCodeList) { 53 | midCodeList.add(MidCode.Op.FUNC, this.funcType.getType().equals(FuncType.Type.Void) ? "void" : "int", 54 | indent.getName(), "#VACANT"); 55 | this.block.gen_mid(midCodeList); 56 | midCodeList.add(MidCode.Op.RETURN, "#VACANT", "#VACANT", "#VACANT"); 57 | midCodeList.add(MidCode.Op.END_FUNC, this.funcType.getType().equals(FuncType.Type.Void) ? "void" : "int", 58 | indent.getName(), "#VACANT"); 59 | return ""; 60 | } 61 | 62 | public Integer getArgc() { 63 | return this.funcFParams.getArgc(); 64 | } 65 | 66 | public FuncType.Type getType() { 67 | return this.funcType.getType(); 68 | } 69 | 70 | public Indent getIndent() { 71 | return this.indent; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /front/ASD/FuncFParam.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FuncFParam implements ASDNode{ 9 | private BType bType; 10 | public Indent indent; 11 | private ArrayList constExps; 12 | private boolean isArray; 13 | 14 | private final ArrayList asdNodes = new ArrayList<>(); 15 | private int dimension; 16 | 17 | public FuncFParam(BType bType, Indent indent, ArrayList constExps, int dimension) { 18 | this.bType = bType; 19 | this.indent = indent; 20 | this.constExps = constExps; 21 | this.dimension = dimension; 22 | asdNodes.add(bType); 23 | asdNodes.add(indent); 24 | asdNodes.addAll(constExps); 25 | this.isArray = dimension > 0; 26 | } 27 | 28 | @Override 29 | public void printTestInfo() { 30 | bType.printTestInfo(); 31 | indent.printTestInfo(); 32 | if (isArray) { 33 | System.out.println("LBRACK ["); 34 | System.out.println("RBRACK ]"); 35 | for (ConstExp constExp: constExps) { 36 | System.out.println("LBRACK ["); 37 | constExp.printTestInfo(); 38 | System.out.println("RBRACK ]"); 39 | } 40 | } 41 | System.out.println(""); 42 | } 43 | 44 | @Override 45 | public void linkWithSymbolTable() { 46 | } 47 | 48 | @Override 49 | public ArrayList getChild() { 50 | return asdNodes; 51 | } 52 | 53 | @Override 54 | public String gen_mid(MidCodeList midCodeList) { 55 | return null; 56 | } 57 | 58 | public String getName() { 59 | return this.indent.getName(); 60 | } 61 | 62 | public boolean getIsArray() { 63 | return this.isArray; 64 | } 65 | 66 | public Indent getIndent() { 67 | return this.indent; 68 | } 69 | 70 | public int getDimension() { 71 | return this.dimension; 72 | } 73 | 74 | public ArrayList getShape() throws Error { 75 | ArrayList shape = new ArrayList<>(); 76 | if (isArray) { 77 | shape.add(-1); 78 | } 79 | for (ConstExp exp: constExps) { 80 | shape.add(exp.getValue()); 81 | } 82 | return shape; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /front/ASD/FuncFParams.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class FuncFParams implements ASDNode{ 8 | private ArrayList funcFParams; 9 | private final ArrayList asdNodes = new ArrayList<>(); 10 | 11 | public FuncFParams(ArrayList funcFParams) { 12 | this.funcFParams = funcFParams; 13 | asdNodes.addAll(funcFParams); 14 | } 15 | 16 | @Override 17 | public void printTestInfo() { 18 | if (funcFParams.size() == 0) { 19 | return; 20 | } 21 | boolean flag = false; 22 | for (FuncFParam funcFParam: funcFParams) { 23 | if (flag) { 24 | System.out.println("COMMA ,"); 25 | } 26 | funcFParam.printTestInfo(); 27 | flag = true; 28 | } 29 | System.out.println(""); 30 | } 31 | 32 | @Override 33 | public void linkWithSymbolTable() { 34 | } 35 | 36 | @Override 37 | public ArrayList getChild() { 38 | return asdNodes; 39 | } 40 | 41 | @Override 42 | public String gen_mid(MidCodeList midCodeList) { 43 | return null; 44 | } 45 | 46 | public Integer getArgc() { 47 | return this.funcFParams.size(); 48 | } 49 | 50 | public ArrayList getFuncFParams() { 51 | return this.funcFParams; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /front/ASD/FuncRParams.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FuncRParams implements ASDNode{ 9 | public ArrayList exps; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public FuncRParams(ArrayList exps) { 13 | this.exps = exps; 14 | asdNodes.addAll(exps); 15 | } 16 | 17 | @Override 18 | public void printTestInfo() { 19 | if (exps.size() == 0) { 20 | return; 21 | } 22 | boolean flag = false; 23 | for (Exp exp: exps) { 24 | if (flag) { 25 | System.out.println("COMMA ,"); 26 | } 27 | exp.printTestInfo(); 28 | flag = true; 29 | } 30 | System.out.println(""); 31 | } 32 | 33 | @Override 34 | public void linkWithSymbolTable() { 35 | } 36 | 37 | @Override 38 | public ArrayList getChild() { 39 | return asdNodes; 40 | } 41 | 42 | @Override 43 | public String gen_mid(MidCodeList midCodeList) { 44 | return ""; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /front/ASD/FuncType.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class FuncType implements ASDNode{ 8 | 9 | public enum Type { 10 | Int, Void 11 | } 12 | 13 | private Type type; 14 | private final ArrayList asdNodes = new ArrayList<>(); 15 | public FuncType(Type type) { 16 | this.type = type; 17 | } 18 | 19 | @Override 20 | public void printTestInfo() { 21 | if (type.equals(Type.Int)) { 22 | System.out.println("INTTK int"); 23 | } else { 24 | System.out.println("VOIDTK void"); 25 | } 26 | System.out.println(""); 27 | } 28 | 29 | @Override 30 | public void linkWithSymbolTable() { 31 | } 32 | 33 | @Override 34 | public ArrayList getChild() { 35 | return asdNodes; 36 | } 37 | 38 | @Override 39 | public String gen_mid(MidCodeList midCodeList) { 40 | return null; 41 | } 42 | 43 | public Type getType() { 44 | return this.type; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /front/ASD/Indent.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class Indent implements ASDNode{ 9 | private Token token; 10 | private String name; 11 | 12 | private final ArrayList asdNodes = new ArrayList<>(); 13 | 14 | public Indent(Token token) { 15 | this.token = token; 16 | this.name = token.getName(); 17 | } 18 | 19 | @Override 20 | public void printTestInfo() { 21 | System.out.println(token.toString()); 22 | } 23 | 24 | @Override 25 | public void linkWithSymbolTable() { 26 | 27 | } 28 | 29 | @Override 30 | public ArrayList getChild() { 31 | return asdNodes; 32 | } 33 | 34 | @Override 35 | public String gen_mid(MidCodeList midCodeList) { 36 | return null; 37 | } 38 | 39 | public String getName() { 40 | return this.name; 41 | } 42 | 43 | public int getLineNum() { 44 | return this.token.getLineNum(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /front/ASD/InitVal.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | import java.util.zip.InflaterInputStream; 8 | 9 | public class InitVal implements ASDNode{ 10 | 11 | 12 | public enum Type{ 13 | mulInitVal, 14 | Exp 15 | } 16 | private ArrayList asdNodes; 17 | private Type type; 18 | 19 | public InitVal(Type type, ArrayList asdNodes) { 20 | this.asdNodes = asdNodes; 21 | this.type = type; 22 | } 23 | 24 | @Override 25 | public void printTestInfo() { 26 | if (this.type.equals(Type.Exp)) { 27 | this.asdNodes.get(0).printTestInfo(); 28 | } else { 29 | System.out.println("LBRACE {"); 30 | boolean tag = false; 31 | for (ASDNode asdNode: asdNodes) { 32 | if (tag) { 33 | System.out.println("COMMA ,"); 34 | } 35 | asdNode.printTestInfo(); 36 | tag = true; 37 | } 38 | System.out.println("RBRACE }"); 39 | } 40 | System.out.println(""); 41 | } 42 | 43 | @Override 44 | public void linkWithSymbolTable() { 45 | } 46 | @Override 47 | public ArrayList getChild() { 48 | if (asdNodes == null) { 49 | return new ArrayList<>(); 50 | } 51 | return asdNodes; 52 | } 53 | 54 | @Override 55 | public String gen_mid(MidCodeList midCodeList) { 56 | String value = ""; 57 | if (this.type.equals(InitVal.Type.Exp)) { 58 | Integer try_value = ((Exp) asdNodes.get(0)).getValue(); 59 | if (try_value != null) { // const initVal 60 | return try_value.toString(); 61 | } 62 | value = (asdNodes.get(0)).gen_mid(midCodeList); 63 | } else { 64 | return "#ARRAY"; 65 | } 66 | return value; 67 | 68 | } 69 | 70 | public void getInitValue(ArrayList initValues, MidCodeList midCodeList) { 71 | if (this.type.equals(InitVal.Type.Exp)) { 72 | initValues.add((asdNodes.get(0)).gen_mid(midCodeList)); 73 | } else { 74 | for (ASDNode asdNode : asdNodes) { 75 | ((InitVal) asdNode).getInitValue(initValues, midCodeList); 76 | } 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /front/ASD/IntConst.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class IntConst implements ASDNode{ 9 | private Token token; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | public IntConst(Token token) { 12 | this.token = token; 13 | } 14 | 15 | @Override 16 | public void printTestInfo() { 17 | System.out.println(token.toString()); 18 | } 19 | 20 | @Override 21 | public void linkWithSymbolTable() { 22 | } 23 | 24 | @Override 25 | public ArrayList getChild() { 26 | return asdNodes; 27 | } 28 | 29 | @Override 30 | public String gen_mid(MidCodeList midCodeList) { 31 | return null; 32 | } 33 | 34 | public int getValue() { 35 | return this.token.getInitValue(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /front/ASD/Jump.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class Jump implements ASDNode{ 9 | public String label; 10 | 11 | public Jump(String label) { 12 | this.label = label; 13 | } 14 | 15 | @Override 16 | public void printTestInfo() { 17 | } 18 | 19 | @Override 20 | public void linkWithSymbolTable() { 21 | } 22 | 23 | @Override 24 | public ArrayList getChild() { 25 | return null; 26 | } 27 | 28 | @Override 29 | public String gen_mid(MidCodeList midCodeList) { 30 | return midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", label); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /front/ASD/LAndExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class LAndExp implements ASDNode{ 9 | private ArrayList eqExps; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public LAndExp(ArrayList eqExps) { 13 | this.eqExps = eqExps; 14 | asdNodes.addAll(eqExps); 15 | } 16 | 17 | @Override 18 | public void printTestInfo() { 19 | eqExps.get(0).printTestInfo(); 20 | System.out.println(""); 21 | for (int i = 0; i < eqExps.size()-1; i++) { 22 | System.out.println("AND &&"); 23 | eqExps.get(i+1).printTestInfo(); 24 | System.out.println(""); 25 | } 26 | } 27 | 28 | @Override 29 | public void linkWithSymbolTable() { 30 | } 31 | 32 | @Override 33 | public ArrayList getChild() { 34 | return asdNodes; 35 | } 36 | 37 | @Override 38 | public String gen_mid(MidCodeList midCodeList) { 39 | String false_label = ""; 40 | String bool_var = ""; 41 | if (eqExps.size() == 1) { 42 | return eqExps.get(0).gen_mid(midCodeList); 43 | } 44 | bool_var = midCodeList.add(MidCode.Op.ASSIGN, "#AUTO", "0", "#VACANT"); 45 | for (EqExp eqExp : eqExps) { 46 | String ans = eqExp.gen_mid(midCodeList); 47 | if (false_label.equals("")) { 48 | false_label = midCodeList.add(MidCode.Op.JUMP_IF, ans + " " + "0", "==", "#AUTO_LABEL"); 49 | } else { 50 | midCodeList.add(MidCode.Op.JUMP_IF, ans + " " + "0", "==", false_label); 51 | } 52 | } 53 | midCodeList.add(MidCode.Op.ASSIGN, bool_var, "1", "#VACANT"); 54 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", false_label); 55 | assert !bool_var.equals(""); 56 | return bool_var; 57 | } 58 | 59 | public void gen_mid_opt(MidCodeList midCodeList, String next_or, ASDNode stmt, String end_if) { 60 | if (eqExps.size() == 1) { 61 | eqExps.get(0).gen_mid_opt(midCodeList, next_or, stmt, end_if, true); 62 | return; 63 | } 64 | for (EqExp eqExp : eqExps) { 65 | eqExp.gen_mid_opt(midCodeList, next_or, stmt, end_if, false); 66 | } 67 | stmt.gen_mid(midCodeList); 68 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end_if); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /front/ASD/LOrExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class LOrExp implements ASDNode{ 9 | private ArrayList lAndExps; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public LOrExp(ArrayList lAndExps) { 13 | this.lAndExps = lAndExps; 14 | asdNodes.addAll(lAndExps); 15 | } 16 | 17 | @Override 18 | public void printTestInfo() { 19 | lAndExps.get(0).printTestInfo(); 20 | System.out.println(""); 21 | for (int i = 0; i < lAndExps.size()-1; i++) { 22 | System.out.println("OR ||"); 23 | lAndExps.get(i+1).printTestInfo(); 24 | System.out.println(""); 25 | } 26 | } 27 | 28 | @Override 29 | public void linkWithSymbolTable() { 30 | } 31 | 32 | @Override 33 | public ArrayList getChild() { 34 | return asdNodes; 35 | } 36 | 37 | @Override 38 | public String gen_mid(MidCodeList midCodeList) { 39 | String true_label = ""; 40 | String bool_var = ""; 41 | if (lAndExps.size() == 1) { 42 | return lAndExps.get(0).gen_mid(midCodeList); 43 | } 44 | bool_var = midCodeList.add(MidCode.Op.ASSIGN, "#AUTO", "1", "#VACANT"); 45 | for (LAndExp eqExp : lAndExps) { 46 | String ans = eqExp.gen_mid(midCodeList); 47 | if (true_label.equals("")) { 48 | true_label = midCodeList.add(MidCode.Op.JUMP_IF, ans + " " + "0", "!=", "#AUTO_LABEL"); 49 | } else { 50 | midCodeList.add(MidCode.Op.JUMP_IF, ans + " " + "0", "!=", true_label); 51 | } 52 | } 53 | midCodeList.add(MidCode.Op.ASSIGN, bool_var, "0", "#VACANT"); 54 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", true_label); 55 | assert !bool_var.equals(""); 56 | return bool_var; 57 | } 58 | 59 | public void gen_mid_opt(MidCodeList midCodeList, String else_label, String endIf, ASDNode stmt) { 60 | int index = 0; 61 | for (LAndExp lAndExp : lAndExps) { 62 | String next_or = midCodeList.alloc_label(); 63 | if (index == lAndExps.size() - 1) { 64 | next_or = else_label; 65 | } 66 | lAndExp.gen_mid_opt(midCodeList, next_or, stmt, endIf); 67 | if (!(index == lAndExps.size() - 1)) { 68 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", next_or); 69 | } 70 | index += 1; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /front/ASD/LVal.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import SymTable.FuncFormVar; 4 | import SymTable.SymItem; 5 | import SymTable.Var; 6 | import mid.MidCode; 7 | import mid.MidCodeList; 8 | 9 | import java.util.ArrayList; 10 | 11 | public class LVal implements ASDNode{ 12 | public Indent indent; 13 | public ArrayList exps; 14 | private final ArrayList asdNodes = new ArrayList<>(); 15 | 16 | public LVal(Indent indent, ArrayList exps) { 17 | this.indent = indent; 18 | this.exps = exps; 19 | asdNodes.add(indent); 20 | asdNodes.addAll(exps); 21 | } 22 | 23 | @Override 24 | public void printTestInfo() { 25 | indent.printTestInfo(); 26 | for (Exp exp: exps) { 27 | System.out.println("LBRACK ["); 28 | exp.printTestInfo(); 29 | System.out.println("RBRACK ]"); 30 | } 31 | System.out.println(""); 32 | } 33 | 34 | @Override 35 | public void linkWithSymbolTable() { 36 | } 37 | 38 | @Override 39 | public ArrayList getChild() { 40 | return asdNodes; 41 | } 42 | 43 | @Override 44 | public String gen_mid(MidCodeList midCodeList) { 45 | // 变量名@ 46 | String name = indent.getName() + "@" + midCodeList.node2symItem.get(indent).get_loc(); 47 | SymItem item = midCodeList.node2symItem.get(indent); 48 | ArrayList shape; 49 | if (item instanceof Var) { 50 | shape = ((Var) item).getShape(); 51 | } else { 52 | shape = ((FuncFormVar) item).getShape(); 53 | } 54 | if (!exps.isEmpty()) { 55 | if (shape.size() > 1 && shape.size() == exps.size()) { 56 | String x = exps.get(0).gen_mid(midCodeList); 57 | String y = exps.get(1).gen_mid(midCodeList); 58 | String base; 59 | try { 60 | base = String.valueOf(Integer.parseInt(x) * Integer.parseInt(shape.get(1).toString())); 61 | } catch (Exception ignore) { 62 | base = midCodeList.add(MidCode.Op.MUL, x, shape.get(1).toString(), "#AUTO"); 63 | } 64 | try { 65 | name += "[" + (Integer.parseInt(y) + Integer.parseInt(base)) + "]"; 66 | } catch (Exception ignore) { 67 | name += "[" + midCodeList.add(MidCode.Op.ADD, y, base, "#AUTO") + "]"; 68 | } 69 | } else { 70 | String rank = exps.get(0).gen_mid(midCodeList); 71 | if (rank.contains("[")) { 72 | rank = midCodeList.add(MidCode.Op.ARR_LOAD, "#AUTO", rank, "#VACANT"); 73 | } 74 | if (shape.size() != exps.size()) { 75 | midCodeList.add(MidCode.Op.SIGNAL_ARR_ADDR, "#VACANT", "#VACANT", "#VACANT"); 76 | } 77 | name += "[" + rank + "]"; 78 | } 79 | } else if (!shape.isEmpty() && shape.get(0) != -1) { 80 | midCodeList.add(MidCode.Op.SIGNAL_ARR_ADDR, "#VACANT", "#VACANT", "#VACANT"); 81 | } 82 | return name; 83 | } 84 | 85 | public int getDimension() { 86 | return this.exps.size(); 87 | } 88 | 89 | public String getName() { 90 | return this.indent.getName(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /front/ASD/MainFuncDef.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCode; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class MainFuncDef implements ASDNode{ 9 | private Block block; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public MainFuncDef(Block block, ASDNode blockEnd) { 13 | this.block = block; 14 | asdNodes.add(block); 15 | asdNodes.add(blockEnd); 16 | } 17 | 18 | @Override 19 | public void printTestInfo() { 20 | System.out.println("INTTK int"); 21 | System.out.println("MAINTK main"); 22 | System.out.println("LPARENT ("); 23 | System.out.println("RPARENT )"); 24 | block.printTestInfo(); 25 | System.out.println(""); 26 | } 27 | 28 | @Override 29 | public void linkWithSymbolTable() { 30 | } 31 | 32 | @Override 33 | public ArrayList getChild() { 34 | return asdNodes; 35 | } 36 | 37 | @Override 38 | public String gen_mid(MidCodeList midCodeList) { 39 | midCodeList.add(MidCode.Op.FUNC, "int", "main", "#VACANT"); 40 | this.block.gen_mid(midCodeList); 41 | midCodeList.add(MidCode.Op.END_FUNC, "int", "main", "#VACANT"); 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /front/ASD/MulExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import front.Token; 5 | import mid.MidCode; 6 | import mid.MidCodeList; 7 | 8 | import java.util.ArrayList; 9 | 10 | public class MulExp implements ASDNode{ 11 | 12 | public ArrayList Ops; 13 | public ArrayList unaryExps; 14 | private final ArrayList asdNodes = new ArrayList<>(); 15 | 16 | public MulExp(ArrayList Ops, ArrayList unaryExps) { 17 | this.Ops = Ops; 18 | this.unaryExps = unaryExps; 19 | asdNodes.addAll(unaryExps); 20 | } 21 | 22 | @Override 23 | public void printTestInfo() { 24 | int i = 0; 25 | for (UnaryExp unaryExp: unaryExps) { 26 | unaryExp.printTestInfo(); 27 | System.out.println(""); 28 | if (i < Ops.size()) { 29 | System.out.println(Ops.get(i).toString()); 30 | } 31 | i += 1; 32 | } 33 | } 34 | 35 | @Override 36 | public void linkWithSymbolTable() { 37 | } 38 | 39 | @Override 40 | public ArrayList getChild() { 41 | return asdNodes; 42 | } 43 | 44 | @Override 45 | public String gen_mid(MidCodeList midCodeList) { 46 | try { 47 | return Integer.toString(this.getValue()); 48 | } catch (Error ignored) { 49 | } 50 | String op1 = unaryExps.get(0).gen_mid(midCodeList); 51 | String result = op1; 52 | for (int i =0; i < Ops.size(); i += 1) { 53 | String op2 = unaryExps.get(i+1).gen_mid(midCodeList); 54 | mid.MidCode.Op op = Ops.get(i).getTokenClass().equals("MULT") ? mid.MidCode.Op.MUL : 55 | Ops.get(i).getTokenClass().equals("DIV") ? mid.MidCode.Op.DIV : mid.MidCode.Op.MOD; 56 | result = midCodeList.add(op, op1, op2, "#AUTO"); 57 | op1 = result; 58 | } 59 | return result; 60 | } 61 | 62 | public int getDimension() { 63 | if (!Ops.isEmpty()) { 64 | return 0; 65 | } 66 | return this.unaryExps.get(0).getDimension(); 67 | } 68 | 69 | public String getName() { 70 | if (!Ops.isEmpty()) { 71 | return null; 72 | } 73 | 74 | return this.unaryExps.get(0).getName(); 75 | } 76 | 77 | public int getValue() throws Error { 78 | int value = unaryExps.get(0).getValue(); 79 | for (int index = 1; index < unaryExps.size(); index += 1) { 80 | if (Ops.get(index-1).toString().equals("MULT *")) { 81 | value = value * unaryExps.get(index).getValue(); 82 | } else if (Ops.get(index-1).toString().equals("DIV /")){ 83 | value = value / unaryExps.get(index).getValue(); 84 | } else { 85 | value = value % unaryExps.get(index).getValue(); 86 | } 87 | } 88 | return value; 89 | } 90 | 91 | public boolean isFunCall() { 92 | return this.unaryExps.size() == 1 && this.unaryExps.get(0).isFunCall(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /front/ASD/Number.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class Number implements ASDNode{ 8 | private IntConst intConst; 9 | private final ArrayList asdNodes = new ArrayList<>(); 10 | 11 | public Number(IntConst intConst) { 12 | this.intConst = intConst; 13 | this.asdNodes.add(intConst); 14 | } 15 | 16 | @Override 17 | public void printTestInfo() { 18 | intConst.printTestInfo(); 19 | System.out.println(""); 20 | } 21 | 22 | @Override 23 | public void linkWithSymbolTable() { 24 | } 25 | 26 | @Override 27 | public ArrayList getChild() { 28 | return asdNodes; 29 | } 30 | 31 | @Override 32 | public String gen_mid(MidCodeList midCodeList) { 33 | return null; 34 | } 35 | 36 | public int getValue() { 37 | return this.intConst.getValue(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /front/ASD/PrimaryExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class PrimaryExp implements ASDNode{ 9 | public Exp exp; 10 | public LVal lVal; 11 | public Number number; 12 | private final ArrayList asdNodes = new ArrayList<>(); 13 | public String value; 14 | 15 | public PrimaryExp(Exp exp) { 16 | this.exp = exp; 17 | this.lVal = null; 18 | this.number = null; 19 | this.value = null; 20 | asdNodes.add(exp); 21 | } 22 | 23 | public PrimaryExp(LVal lVal) { 24 | this.lVal = lVal; 25 | this.exp = null; 26 | this.number = null; 27 | this.value = null; 28 | asdNodes.add(lVal); 29 | } 30 | 31 | public PrimaryExp(Number number) { 32 | this.number = number; 33 | this.exp = null; 34 | this.lVal = null; 35 | this.value = null; 36 | asdNodes.add(number); 37 | } 38 | 39 | @Override 40 | public void printTestInfo() { 41 | if (exp != null) { 42 | System.out.println("LPARENT ("); 43 | exp.printTestInfo(); 44 | System.out.println("RPARENT )"); 45 | } else if (lVal != null) { 46 | lVal.printTestInfo(); 47 | } else { 48 | number.printTestInfo(); 49 | } 50 | System.out.println(""); 51 | } 52 | 53 | @Override 54 | public void linkWithSymbolTable() { 55 | } 56 | 57 | @Override 58 | public ArrayList getChild() { 59 | return asdNodes; 60 | } 61 | 62 | @Override 63 | public String gen_mid(MidCodeList midCodeList) { 64 | try { 65 | return Integer.toString(this.getValue()); 66 | } catch (Error ignored) { 67 | } 68 | if (this.exp != null) { 69 | return exp.gen_mid(midCodeList); 70 | } else if (this.lVal != null) { 71 | return this.lVal.gen_mid(midCodeList); 72 | } else { 73 | return Integer.toString(this.number.getValue()); 74 | } 75 | } 76 | 77 | public int getDimension() { 78 | if (this.lVal != null) { 79 | return this.lVal.getDimension(); 80 | } else if (this.exp != null){ 81 | return this.exp.getDimension(); 82 | } 83 | return 0; 84 | } 85 | 86 | public String getName() { 87 | if (this.lVal != null) { 88 | return this.lVal.getName(); 89 | } else if (this.exp != null){ 90 | return this.exp.getName(); 91 | } 92 | return null; 93 | } 94 | 95 | public int getValue() throws Error { 96 | if (this.value != null) { 97 | return Integer.parseInt(value); 98 | } 99 | if (this.number != null) { 100 | return this.number.getValue(); 101 | } 102 | if (this.exp != null) { 103 | Integer value = this.exp.getValue(); 104 | if (value != null) { 105 | return this.exp.getValue(); 106 | } 107 | } 108 | throw new Error(Error.Type.other_error, -1); 109 | } 110 | 111 | public boolean isFunCall() { 112 | return this.exp != null && this.exp.isFunCall(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /front/ASD/RelExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class RelExp implements ASDNode { 10 | 11 | public ArrayList Ops; 12 | public ArrayList addExps; 13 | private final ArrayList asdNodes = new ArrayList<>(); 14 | 15 | public RelExp(ArrayList Ops, ArrayList addExps) { 16 | this.Ops = Ops; 17 | this.addExps = addExps; 18 | asdNodes.addAll(addExps); 19 | } 20 | 21 | @Override 22 | public void printTestInfo() { 23 | int i = 0; 24 | for (AddExp addExp : addExps) { 25 | addExp.printTestInfo(); 26 | System.out.println(""); 27 | if (i < Ops.size()) { 28 | System.out.println(Ops.get(i).toString()); 29 | } 30 | i += 1; 31 | } 32 | } 33 | 34 | @Override 35 | public void linkWithSymbolTable() { 36 | } 37 | 38 | @Override 39 | public ArrayList getChild() { 40 | return asdNodes; 41 | } 42 | 43 | @Override 44 | public String gen_mid(MidCodeList midCodeList) { 45 | AddExp left = addExps.get(0); 46 | String true_label = ""; 47 | String bool_var = ""; 48 | if (addExps.size() == 1) { 49 | return addExps.get(0).gen_mid(midCodeList); 50 | } 51 | String left_ans = left.gen_mid(midCodeList); 52 | for (int i = 1; i < addExps.size(); i++) { 53 | bool_var = midCodeList.add(MidCode.Op.ASSIGN, "#AUTO", "1", "#VACANT"); 54 | String op = Ops.get(i - 1).getString(); 55 | AddExp right = addExps.get(i); 56 | String right_ans = right.gen_mid(midCodeList); 57 | true_label = midCodeList.add(MidCode.Op.JUMP_IF, left_ans + " " + right_ans, op, "#AUTO_LABEL"); 58 | midCodeList.add(MidCode.Op.ASSIGN, bool_var, "0", "#VACANT"); 59 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", true_label); 60 | left_ans = bool_var; 61 | } 62 | assert !bool_var.equals(""); 63 | return bool_var; 64 | } 65 | 66 | public String gen_mid_opt(MidCodeList midCodeList, String next_or, ASDNode stmt, String end_if, boolean reverse, boolean containsIfBlock) { 67 | if (addExps.size() == 2 && reverse) { 68 | String left = addExps.get(0).gen_mid(midCodeList); 69 | String right = addExps.get(1).gen_mid(midCodeList); 70 | String op = reverseOp(Ops.get(0).toString().split(" ")[1]); 71 | midCodeList.add(MidCode.Op.JUMP_IF, left + " " + right, op, next_or); 72 | if (containsIfBlock) { 73 | stmt.gen_mid(midCodeList); 74 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end_if); 75 | } 76 | return null; 77 | } 78 | if (addExps.size() == 1) { 79 | if (reverse) { 80 | midCodeList.add(MidCode.Op.JUMP_IF, addExps.get(0).gen_mid(midCodeList) + " " + "0", "==", next_or); 81 | if (containsIfBlock) { 82 | stmt.gen_mid(midCodeList); 83 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end_if); 84 | } 85 | return null; 86 | } 87 | return addExps.get(0).gen_mid(midCodeList); 88 | } 89 | 90 | String left = addExps.get(0).gen_mid(midCodeList); 91 | if (reverse) { 92 | for (int i = 1; i < addExps.size(); i++) { 93 | String op = Ops.get(i - 1).getString(); 94 | String right = addExps.get(i).gen_mid(midCodeList); 95 | if (Ops.size() == i) { 96 | op = reverseOp(op); 97 | left = midCodeList.add(MidCode.Op.JUMP_IF, left + " " + right, op, next_or); 98 | if (containsIfBlock) { 99 | stmt.gen_mid(midCodeList); 100 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end_if); 101 | } 102 | } else { 103 | left = midCodeList.add(MidCode.Op.SET, left + " " + right, op, "#AUTO"); 104 | } 105 | } 106 | return null; 107 | } 108 | for (int i = 1; i < addExps.size(); i++) { 109 | String op = Ops.get(i - 1).getString(); 110 | String right = addExps.get(i).gen_mid(midCodeList); 111 | left = midCodeList.add(MidCode.Op.SET, left + " " + right, op, "#AUTO"); 112 | } 113 | return left; 114 | } 115 | 116 | public String reverseOp(String op) { 117 | return op.equals(">=") ? "<" : 118 | op.equals(">") ? "<=" : 119 | op.equals("<=") ? ">" : 120 | op.equals("<") ? ">=" : "2333"; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /front/ASD/Stmt.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Compiler; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class Stmt implements ASDNode { 10 | 11 | public enum Type { 12 | Assign, Exp, ifBranch, whileBranch, breakStmt, continueStmt, 13 | returnStmt, input, output, None, Block 14 | } 15 | 16 | private Type type; 17 | private ArrayList asdNodes; 18 | 19 | 20 | public Stmt(Type type, ArrayList asdNodes) { 21 | this.type = type; 22 | this.asdNodes = asdNodes; 23 | } 24 | 25 | @Override 26 | public void printTestInfo() { 27 | switch (type) { 28 | case Assign: 29 | asdNodes.get(0).printTestInfo(); 30 | System.out.println("ASSIGN ="); 31 | asdNodes.get(1).printTestInfo(); 32 | System.out.println("SEMICN ;"); 33 | break; 34 | case Exp: 35 | asdNodes.get(0).printTestInfo(); 36 | System.out.println("SEMICN ;"); 37 | break; 38 | case Block: 39 | asdNodes.get(0).printTestInfo(); 40 | break; 41 | case ifBranch: 42 | System.out.println("IFTK if"); 43 | System.out.println("LPARENT ("); 44 | asdNodes.get(0).printTestInfo(); 45 | System.out.println("RPARENT )"); 46 | asdNodes.get(1).printTestInfo(); 47 | if (asdNodes.size() > 2) { 48 | System.out.println("ELSETK else"); 49 | asdNodes.get(2).printTestInfo(); 50 | } 51 | break; 52 | case whileBranch: 53 | System.out.println("WHILETK while"); 54 | System.out.println("LPARENT ("); 55 | asdNodes.get(0).printTestInfo(); 56 | System.out.println("RPARENT )"); 57 | asdNodes.get(1).printTestInfo(); 58 | break; 59 | case breakStmt: 60 | System.out.println("BREAKTK break"); 61 | System.out.println("SEMICN ;"); 62 | break; 63 | case continueStmt: 64 | System.out.println("CONTINUETK continue"); 65 | System.out.println("SEMICN ;"); 66 | break; 67 | case returnStmt: 68 | System.out.println("RETURNTK return"); 69 | if (asdNodes.size() == 2) { 70 | asdNodes.get(1).printTestInfo(); 71 | } 72 | System.out.println("SEMICN ;"); 73 | break; 74 | case input: 75 | asdNodes.get(0).printTestInfo(); 76 | System.out.println("ASSIGN ="); 77 | System.out.println("GETINTTK getint"); 78 | System.out.println("LPARENT ("); 79 | System.out.println("RPARENT )"); 80 | System.out.println("SEMICN ;"); 81 | break; 82 | case output: 83 | System.out.println("PRINTFTK printf"); 84 | System.out.println("LPARENT ("); 85 | boolean flag = false; 86 | for (ASDNode asdNode : asdNodes.subList(1, asdNodes.size())) { 87 | if (flag) { 88 | System.out.println("COMMA ,"); 89 | } 90 | asdNode.printTestInfo(); 91 | flag = true; 92 | } 93 | System.out.println("RPARENT )"); 94 | System.out.println("SEMICN ;"); 95 | break; 96 | case None: 97 | System.out.println("SEMICN ;"); 98 | default: 99 | break; 100 | } 101 | System.out.println(""); 102 | } 103 | 104 | @Override 105 | public void linkWithSymbolTable() { 106 | } 107 | 108 | @Override 109 | public ArrayList getChild() { 110 | if (asdNodes == null) { 111 | return new ArrayList<>(); 112 | } 113 | return asdNodes; 114 | } 115 | 116 | @Override 117 | public String gen_mid(MidCodeList midCodeList) { 118 | String result = ""; 119 | switch (type) { 120 | case Assign: 121 | String name = this.asdNodes.get(0).gen_mid(midCodeList); 122 | if (name.contains("[")) { 123 | String tmp = midCodeList.add(MidCode.Op.ASSIGN, 124 | "#AUTO", 125 | this.asdNodes.get(1).gen_mid(midCodeList), "#VACANT"); 126 | midCodeList.add(MidCode.Op.ARR_SAVE, name, tmp, "#VACANT"); 127 | } else { 128 | result = midCodeList.add(MidCode.Op.ASSIGN, 129 | this.asdNodes.get(0).gen_mid(midCodeList), 130 | this.asdNodes.get(1).gen_mid(midCodeList), "#VACANT"); 131 | } 132 | break; 133 | case Exp: 134 | case Block: 135 | result = this.asdNodes.get(0).gen_mid(midCodeList); 136 | break; 137 | case ifBranch: 138 | if (!Compiler.branch_opt) { 139 | String bool_value = asdNodes.get(0).gen_mid(midCodeList); 140 | if (asdNodes.size() == 2) { //no else 141 | String endIf = midCodeList.add(MidCode.Op.JUMP_IF, bool_value + " " + 0, "==", "#AUTO_LABEL"); 142 | asdNodes.get(1).gen_mid(midCodeList); 143 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", endIf); 144 | } else { 145 | String else_label = midCodeList.add(MidCode.Op.JUMP_IF, bool_value + " " + 0, "==", "#AUTO_LABEL"); 146 | asdNodes.get(1).gen_mid(midCodeList); 147 | String endIf = midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", "#AUTO_LABEL"); 148 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", else_label); 149 | asdNodes.get(2).gen_mid(midCodeList); 150 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", endIf); 151 | } 152 | } else { // branch_opt 153 | if (asdNodes.size() == 2) { 154 | String endIf = midCodeList.alloc_label(); 155 | ((Cond) asdNodes.get(0)).gen_mid_opt(midCodeList, endIf, endIf, (Stmt) asdNodes.get(1)); 156 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", endIf); 157 | } else { 158 | String else_label = midCodeList.alloc_label(); 159 | String endIf = midCodeList.alloc_label(); 160 | ((Cond) asdNodes.get(0)).gen_mid_opt(midCodeList, else_label, endIf, (Stmt) asdNodes.get(1)); 161 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", else_label); 162 | asdNodes.get(2).gen_mid(midCodeList); 163 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACNAT", endIf); 164 | } 165 | } 166 | break; 167 | case whileBranch: 168 | // convert into if(cond)(do{block}while(cond)) 169 | if (!Compiler.branch_opt) { 170 | String judge_value = midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", "#AUTO_LABEL"); 171 | String cond_bool_value = asdNodes.get(0).gen_mid(midCodeList); 172 | String end_loop = midCodeList.add(MidCode.Op.JUMP_IF, cond_bool_value + " " + 0, "==", "#AUTO_LABEL"); 173 | String begin_loop = midCodeList.alloc_label(); 174 | midCodeList.add(MidCode.Op.WHILE_BIND, judge_value, end_loop, "#VACANT"); 175 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", begin_loop); 176 | asdNodes.get(1).gen_mid(midCodeList); 177 | midCodeList.begin_tables.pop(); 178 | midCodeList.end_tables.pop(); 179 | String re_cond_bool_value = asdNodes.get(0).gen_mid(midCodeList); 180 | midCodeList.add(MidCode.Op.JUMP_IF, re_cond_bool_value + " " + 0, "!=", begin_loop); 181 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", end_loop); 182 | } else { 183 | String judge_value = midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", "#AUTO_LABEL"); 184 | String begin_loop = midCodeList.alloc_label(); 185 | ASDNode jump = new Jump(begin_loop); 186 | String endJudgeIf = midCodeList.alloc_label(); 187 | ((Cond) asdNodes.get(0)).gen_mid_opt(midCodeList, endJudgeIf, endJudgeIf, jump); 188 | midCodeList.add(MidCode.Op.WHILE_BIND, judge_value, endJudgeIf, "#VACANT"); 189 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", begin_loop); 190 | midCodeList.add(MidCode.Op.ENTER_WHILE, "#VACANT", "#VACANT", "#VACANT"); 191 | asdNodes.get(1).gen_mid(midCodeList); 192 | midCodeList.begin_tables.pop(); 193 | midCodeList.end_tables.pop(); 194 | ((Cond) asdNodes.get(0)).gen_mid_opt(midCodeList, endJudgeIf, endJudgeIf, jump); 195 | midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", endJudgeIf); 196 | midCodeList.add(MidCode.Op.EXIT_WHILE, "#VACANT", "#VACANT", "#VACANT"); 197 | } 198 | break; 199 | case breakStmt: 200 | String end = midCodeList.end_tables.peek(); 201 | assert end != null; 202 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", end); 203 | break; 204 | case continueStmt: 205 | String begin = midCodeList.begin_tables.peek(); 206 | assert begin != null; 207 | midCodeList.add(MidCode.Op.JUMP, "#VACANT", "#VACANT", begin); 208 | break; 209 | case returnStmt: 210 | result = midCodeList.add(MidCode.Op.RETURN, 211 | (asdNodes.size() == 2) ? asdNodes.get(1).gen_mid(midCodeList) : "#VACANT", 212 | "#VACANT", 213 | "#VACANT"); 214 | break; 215 | case input: 216 | result = midCodeList.add(MidCode.Op.GETINT, 217 | this.asdNodes.get(0).gen_mid(midCodeList), 218 | "#VACANT", 219 | "#VACANT"); 220 | break; 221 | case output: 222 | // midCodeList.add(MidCode.Op.PRINT, ((FormatString)asdNodes.get(1)).toString(), "#VACANT", "#VACANT"); 223 | String[] cutFStrings = ((FormatString) asdNodes.get(1)).getString().split("%d"); 224 | int i = 0; 225 | for (ASDNode asdNode : asdNodes.subList(2, asdNodes.size())) { 226 | if (i < cutFStrings.length && !cutFStrings[i].equals("")) { 227 | midCodeList.add(MidCode.Op.PRINT, cutFStrings[i], "#STRCONS", "#VACANT"); 228 | } 229 | midCodeList.add(MidCode.Op.PRINT, asdNode.gen_mid(midCodeList), "#VACANT", "#VACANT"); 230 | i += 1; 231 | } 232 | if (i < cutFStrings.length && !cutFStrings[i].equals("")) { 233 | midCodeList.add(MidCode.Op.PRINT, cutFStrings[i], "#STRCONS", "#VACANT"); 234 | } 235 | break; 236 | case None: 237 | default: 238 | break; 239 | } 240 | return result; 241 | } 242 | 243 | public Type getType() { 244 | return this.type; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /front/ASD/UnaryExp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class UnaryExp implements ASDNode{ 10 | 11 | public boolean isFunCall() { 12 | return this.type == Type.FuncCall || this.type == Type.PrimaryExp && ((PrimaryExp) this.asdNodes.get(0)).isFunCall(); 13 | } 14 | 15 | public enum Type { 16 | PrimaryExp, FuncCall, mulUnaryExp 17 | } 18 | public Type type; 19 | public ArrayList asdNodes; 20 | 21 | public UnaryExp(Type type, ArrayList asdNodes) { 22 | this.type = type; 23 | this.asdNodes = asdNodes; 24 | } 25 | 26 | @Override 27 | public void printTestInfo() { 28 | if (type.equals(Type.PrimaryExp)) { 29 | asdNodes.get(0).printTestInfo(); 30 | } else if (type.equals(Type.FuncCall)) { 31 | asdNodes.get(0).printTestInfo(); 32 | System.out.println("LPARENT ("); 33 | if (asdNodes.size() > 1) { 34 | asdNodes.get(1).printTestInfo(); 35 | } 36 | System.out.println("RPARENT )"); 37 | } else { 38 | asdNodes.get(0).printTestInfo(); 39 | asdNodes.get(1).printTestInfo(); 40 | } 41 | System.out.println(""); 42 | } 43 | 44 | public String getFuncCallName() { 45 | assert (type.equals(Type.FuncCall)); 46 | return ((Indent)asdNodes.get(0)).getName(); 47 | } 48 | 49 | @Override 50 | public void linkWithSymbolTable() { 51 | } 52 | 53 | @Override 54 | public ArrayList getChild() { 55 | if (asdNodes == null) { 56 | return new ArrayList<>(); 57 | } 58 | return asdNodes; 59 | } 60 | 61 | @Override 62 | public String gen_mid(MidCodeList midCodeList) { 63 | try { 64 | return Integer.toString(this.getValue()); 65 | } catch (Error ignored) { 66 | } 67 | if (this.type.equals(Type.mulUnaryExp)) { 68 | String type = ((UnaryOp) asdNodes.get(0)).getType(); 69 | MidCode.Op op = type.equals("MINU") ? MidCode.Op.SUB : 70 | type.equals("PLUS") ? MidCode.Op.ADD : MidCode.Op.NOT; 71 | if (op.equals(MidCode.Op.NOT)) { 72 | // String tmp = midCodeList.add(MidCode.Op.ASSIGN, "#AUTO", "1", "#VACANT"); 73 | // String label = midCodeList.add(MidCode.Op.JUMP_IF, asdNodes.get(1).gen_mid(midCodeList) + " 0", "==", "#AUTO_LABEL"); 74 | // midCodeList.add(MidCode.Op.ASSIGN, tmp, "0", "#VACANT"); 75 | // midCodeList.add(MidCode.Op.LABEL, "#VACANT", "#VACANT", label); 76 | return midCodeList.add(MidCode.Op.SET, asdNodes.get(1).gen_mid(midCodeList) + " 0", "==", "#AUTO"); 77 | } else { 78 | return midCodeList.add(op, "0", this.asdNodes.get(1).gen_mid(midCodeList), "#AUTO"); 79 | } 80 | } else if (this.type.equals(Type.FuncCall)) { 81 | String funcName = ((Indent) asdNodes.get(0)).getName(); 82 | midCodeList.add(MidCode.Op.PREPARE_CALL, funcName, "#VACANT", "#VACANT"); 83 | if (asdNodes.size()> 1) { 84 | for (Exp exp: ((FuncRParams)asdNodes.get(1)).exps) { 85 | String name = exp.gen_mid(midCodeList); 86 | midCodeList.add(MidCode.Op.PUSH_PARA, name, funcName, "#VACANT"); 87 | } 88 | } 89 | midCodeList.add(MidCode.Op.CALL, funcName, "#VACANT", "#VACANT"); 90 | // TODO return value pass by %RET or void 91 | return midCodeList.add(MidCode.Op.ADD, "%RTX", "0", "#AUTO"); 92 | } 93 | return this.asdNodes.get(0).gen_mid(midCodeList); 94 | } 95 | 96 | public int getDimension() { 97 | if (this.type != Type.PrimaryExp) { 98 | return 0; 99 | } 100 | return ((PrimaryExp) this.asdNodes.get(0)).getDimension(); 101 | } 102 | 103 | public String getName() { 104 | if (this.type == Type.PrimaryExp) { 105 | return ((PrimaryExp) this.asdNodes.get(0)).getName(); 106 | } else if (this.type == Type.FuncCall) { 107 | return ((Indent) this.asdNodes.get(0)).getName(); 108 | } 109 | return null; 110 | } 111 | 112 | public int getValue() throws Error { 113 | if (this.type.equals(Type.PrimaryExp)) { 114 | return ((PrimaryExp) this.asdNodes.get(0)).getValue(); 115 | } 116 | else if(this.type.equals(Type.mulUnaryExp)) { 117 | if (asdNodes.get(0).toString().equals("PLUS +")) { 118 | return ((UnaryExp) this.asdNodes.get(1)).getValue(); 119 | } 120 | if (((UnaryOp) asdNodes.get(0)).toString().equals("MINU -")) { 121 | return -((UnaryExp) this.asdNodes.get(1)).getValue(); 122 | } else if (((UnaryOp) asdNodes.get(0)).toString().equals("Not")) { 123 | if (((UnaryExp) this.asdNodes.get(1)).getValue() == 0) { 124 | return 0; 125 | } 126 | else { 127 | return 1; 128 | } 129 | } 130 | } 131 | throw new Error(Error.Type.other_error, -1); 132 | } 133 | } 134 | 135 | -------------------------------------------------------------------------------- /front/ASD/UnaryOp.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Token; 4 | import mid.MidCodeList; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class UnaryOp implements ASDNode{ 9 | private Token token; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | public UnaryOp(Token token) { 12 | this.token = token; 13 | } 14 | 15 | @Override 16 | public void printTestInfo() { 17 | System.out.println(""); 18 | } 19 | 20 | @Override 21 | public void linkWithSymbolTable() { 22 | } 23 | 24 | @Override 25 | public ArrayList getChild() { 26 | return asdNodes; 27 | } 28 | 29 | @Override 30 | public String gen_mid(MidCodeList midCodeList) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return this.token.toString(); 37 | } 38 | 39 | public String getType() { 40 | return this.token.getTokenClass(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /front/ASD/VarDecl.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import mid.MidCodeList; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class VarDecl implements ASDNode{ 8 | private BType bType; 9 | private ArrayList varDefs; 10 | private final ArrayList asdNodes = new ArrayList<>(); 11 | 12 | public VarDecl(BType bType, ArrayList varDefs) { 13 | this.bType = bType; 14 | this.varDefs = varDefs; 15 | asdNodes.addAll(varDefs); 16 | } 17 | @Override 18 | public void printTestInfo() { 19 | System.out.println("INTTK int"); 20 | boolean tag = false; 21 | for (VarDef varDef: varDefs) { 22 | if (tag) { 23 | System.out.println("COMMA ,"); 24 | } 25 | varDef.printTestInfo(); 26 | tag = true; 27 | } 28 | System.out.println("SEMICN ;"); 29 | System.out.println(""); 30 | } 31 | 32 | @Override 33 | public void linkWithSymbolTable() { 34 | } 35 | 36 | @Override 37 | public ArrayList getChild() { 38 | return asdNodes; 39 | } 40 | 41 | @Override 42 | public String gen_mid(MidCodeList midCodeList) { 43 | for (VarDef varDef: varDefs) { 44 | varDef.gen_mid(midCodeList); 45 | } 46 | return ""; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /front/ASD/VarDef.java: -------------------------------------------------------------------------------- 1 | package front.ASD; 2 | 3 | import front.Error; 4 | import mid.MidCode; 5 | import mid.MidCodeList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class VarDef implements ASDNode { 10 | public Indent indent; 11 | private ArrayList constExps; 12 | private InitVal initVal; 13 | private final ArrayList asdNodes = new ArrayList<>(); 14 | 15 | public VarDef(Indent indent, ArrayList constExps) { 16 | this.indent = indent; 17 | this.constExps = constExps; 18 | this.initVal = null; 19 | asdNodes.add(indent); 20 | asdNodes.addAll(constExps); 21 | } 22 | 23 | public VarDef(Indent indent, ArrayList constExps, InitVal initVal) { 24 | this.indent = indent; 25 | this.constExps = constExps; 26 | this.initVal = initVal; 27 | asdNodes.add(indent); 28 | asdNodes.addAll(constExps); 29 | asdNodes.add(initVal); 30 | } 31 | 32 | @Override 33 | public void printTestInfo() { 34 | indent.printTestInfo(); 35 | for (ConstExp constExp : constExps) { 36 | System.out.println("LBRACK ["); 37 | constExp.printTestInfo(); 38 | System.out.println("RBRACK ]"); 39 | } 40 | if (initVal != null) { 41 | System.out.println("ASSIGN ="); 42 | initVal.printTestInfo(); 43 | } 44 | System.out.println(""); 45 | } 46 | 47 | @Override 48 | public void linkWithSymbolTable() { 49 | } 50 | 51 | public String getName() { 52 | return this.indent.getName(); 53 | } 54 | 55 | @Override 56 | public ArrayList getChild() { 57 | return asdNodes; 58 | } 59 | 60 | @Override 61 | public String gen_mid(MidCodeList midCodeList) { 62 | // 变量名@ 63 | String name = indent.getName() + "@" + midCodeList.node2symItem.get(indent).get_loc(); 64 | if (constExps.size() == 0) { // not-Array 65 | if (initVal != null) { 66 | String value = initVal.gen_mid(midCodeList); 67 | midCodeList.add(MidCode.Op.VAR_DEF, name, value, "#VACANT"); 68 | } else { 69 | midCodeList.add(MidCode.Op.VAR_DEF, name, "#VACANT", "#VACANT"); 70 | } 71 | } else { 72 | if (initVal != null) { 73 | String value = initVal.gen_mid(midCodeList); 74 | assert value.equals("#ARRAY"); 75 | ArrayList initValues = new ArrayList<>(); 76 | initVal.getInitValue(initValues, midCodeList); 77 | int index = 0; 78 | for (String res : initValues) { 79 | midCodeList.add(MidCode.Op.ARR_SAVE, name + "[" + index + "]", res, "#VACANT"); 80 | index += 1; 81 | } 82 | } else { 83 | midCodeList.add(MidCode.Op.VAR_DEF, name, "#VACANT", "#VACANT"); 84 | } 85 | } 86 | return ""; 87 | } 88 | 89 | public Integer[] getType() { 90 | return new Integer[]{1, 2}; 91 | } 92 | 93 | public InitVal getInitVal() { 94 | return this.initVal; 95 | } 96 | 97 | public Indent getIndent() { 98 | return this.indent; 99 | } 100 | 101 | public int getDimension() { 102 | return this.constExps.size(); 103 | } 104 | 105 | public ArrayList getArrayShape() throws Error { 106 | ArrayList shape = new ArrayList<>(); 107 | for (ConstExp exp : constExps) { 108 | shape.add(exp.getValue()); 109 | } 110 | return shape; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /front/Compiler.java: -------------------------------------------------------------------------------- 1 | package front; 2 | 3 | import front.ASD.CompUnit; 4 | import front.LexicalAnalyser; 5 | import front.Parser; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | import java.io.PrintStream; 13 | 14 | public class Compiler { 15 | public static int debugging = 0; 16 | private static final String inputFilePath = "testfile.txt"; 17 | private static final String output1FilePath = "output1.txt"; 18 | private static final String outputFilePath = "output.txt"; 19 | public static boolean branch_opt = false; 20 | 21 | private static String readFile() throws IOException { 22 | InputStream is = new FileInputStream(inputFilePath); 23 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 24 | StringBuilder buffer = new StringBuilder(); 25 | String line = reader.readLine(); 26 | while (line != null) { 27 | buffer.append(line).append("\n"); 28 | line = reader.readLine(); 29 | } 30 | reader.close(); 31 | is.close(); 32 | return buffer.toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /front/Error.java: -------------------------------------------------------------------------------- 1 | package front; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Error extends Exception{ 6 | public Type errorType; 7 | public int lineNumber; 8 | public enum Type { 9 | other_error, 10 | illegal_sym, name_redefine, undefined_name, func_arg_cnt_mismatch, 11 | func_arg_type_mismatch, void_return, non_void_non_return, changeConst, 12 | miss_semi, miss_parent, miss_brace, printf_num_miss_match, misused_BC, 13 | } 14 | 15 | public final HashMap encode = new HashMap(){{ 16 | put(Type.illegal_sym, "a"); 17 | put(Type.name_redefine, "b"); 18 | put(Type.undefined_name, "c"); 19 | put(Type.func_arg_cnt_mismatch, "d"); 20 | put(Type.func_arg_type_mismatch, "e"); 21 | put(Type.void_return, "f"); 22 | put(Type.non_void_non_return, "g"); 23 | put(Type.changeConst, "h"); 24 | put(Type.miss_semi, "i"); 25 | put(Type.miss_parent, "j"); 26 | put(Type.miss_brace, "k"); 27 | put(Type.printf_num_miss_match, "l"); 28 | put(Type.misused_BC, "m"); 29 | }}; 30 | 31 | public Error(Type type, int lineNumber) { 32 | this.errorType = type; 33 | this.lineNumber = lineNumber; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return lineNumber + " " + encode.get(errorType); 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | if (!(obj instanceof Error)) { 44 | return false; 45 | } 46 | Error error = (Error) obj; 47 | return error == this || (error.toString().equals(this.toString())); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /front/ErrorRecorder.java: -------------------------------------------------------------------------------- 1 | package front; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintStream; 5 | import java.util.ArrayList; 6 | import java.util.Comparator; 7 | 8 | public class ErrorRecorder { 9 | private static ArrayList errors = new ArrayList<>(); 10 | 11 | public static void recordError(Error error) { 12 | errors.add(error); 13 | } 14 | 15 | public static void PrintErrorRecord() { 16 | PrintStream out = System.out; 17 | try { 18 | PrintStream os = new PrintStream("error.txt"); 19 | System.setOut(os); 20 | } catch (IOException ignored) { 21 | } 22 | errors.sort(Comparator.comparingInt(o -> o.lineNumber)); 23 | ArrayList printedErrors = new ArrayList<>(); 24 | for (Error error: errors) { 25 | boolean tag = true; 26 | for (Error printedError: printedErrors) { 27 | if (printedError.equals(error)) { 28 | tag = false; 29 | break; 30 | } 31 | } 32 | if(tag && !error.toString().equals("-1 null")) System.out.println(error.toString()); 33 | printedErrors.add(error); 34 | 35 | } 36 | System.setOut(out); 37 | } 38 | 39 | public static boolean withoutError() { 40 | return errors.isEmpty(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /front/LexicalAnalyser.java: -------------------------------------------------------------------------------- 1 | package front; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | public class LexicalAnalyser { 7 | 8 | private final ArrayList tokens; 9 | private StringBuilder token; 10 | private String programCode; 11 | private int index; 12 | private int formatCharNum; 13 | private int lineNum; 14 | public static HashMap reserveMap = new HashMap() {{ 15 | put("main", "MAINTK"); 16 | put("const", "CONSTTK"); 17 | put("int", "INTTK"); 18 | put("break", "BREAKTK"); 19 | put("continue", "CONTINUETK"); 20 | put("if", "IFTK"); 21 | put("else", "ELSETK"); 22 | put("while", "WHILETK"); 23 | put("getint", "GETINTTK"); 24 | put("printf", "PRINTFTK"); 25 | put("return", "RETURNTK"); 26 | put("void", "VOIDTK"); 27 | }}; 28 | 29 | public LexicalAnalyser() { 30 | tokens = new ArrayList<>(); 31 | formatCharNum = 0; 32 | } 33 | 34 | 35 | public void error() { 36 | if (Compiler.debugging == 2) System.out.println("error when doing lexical analysis at line Number" + lineNum); 37 | } 38 | 39 | public ArrayList getTokenList() { 40 | return tokens; 41 | } 42 | 43 | public void analyze(String programCode) { 44 | index = 0; 45 | lineNum = 1; 46 | this.programCode = programCode; 47 | while (index < programCode.length()) { 48 | token = new StringBuilder(); 49 | String tokenClass = getToken(); 50 | if (Token.decode.containsValue(tokenClass)) { 51 | if (tokenClass.equals("STRCON")) { 52 | tokens.add(new Token(tokenClass, token.toString(), lineNum, formatCharNum)); 53 | this.formatCharNum = 0; 54 | } else { 55 | tokens.add(new Token(tokenClass, token.toString(), lineNum)); 56 | } 57 | } 58 | } 59 | } 60 | 61 | public String getToken() { 62 | String tokenClass = ""; 63 | while (isSpace() || isNewLine() || isTab()) { 64 | index += 1; 65 | } 66 | if (index >= programCode.length()) { 67 | return "false"; 68 | } 69 | if (isLetter()) { 70 | while (isLetter() || isDigit()) { // words Branch 71 | token.append(programCode.charAt(index)); 72 | index += 1; 73 | } 74 | tokenClass = reserveMap.getOrDefault(token.toString(), "IDENFR"); 75 | 76 | } else if (isDigit()) { // digit Branch 77 | while (isDigit()) { 78 | token.append(programCode.charAt(index)); 79 | index += 1; 80 | } 81 | if (token.toString().length() > 1 && token.toString().charAt(0) == '0') { 82 | error(); 83 | } 84 | tokenClass = "INTCON"; 85 | } else if (isEqs()) { // op_div Branch 86 | token.append(programCode.charAt(index)); // two character analysis. 87 | index += 1; 88 | if (isEqs()) { 89 | token.append(programCode.charAt(index)); 90 | index += 1; 91 | tokenClass = "EQL"; 92 | } else { 93 | tokenClass = "ASSIGN"; 94 | } 95 | } else if (isVLine()) { 96 | token.append(programCode.charAt(index)); 97 | index += 1; 98 | if (isVLine()) { 99 | token.append(programCode.charAt(index)); 100 | index += 1; 101 | tokenClass = "OR"; 102 | } else { 103 | error(); 104 | } 105 | } else if (isAnd()) { 106 | token.append(programCode.charAt(index)); 107 | index += 1; 108 | if (isAnd()) { 109 | token.append(programCode.charAt(index)); 110 | index += 1; 111 | tokenClass = "AND"; 112 | } else { 113 | error(); 114 | } 115 | } else if (isLABrace()) { 116 | token.append(programCode.charAt(index)); 117 | index += 1; 118 | if (isEqs()) { 119 | token.append(programCode.charAt(index)); 120 | index += 1; 121 | tokenClass = "LEQ"; 122 | } else { 123 | tokenClass = "LSS"; 124 | } 125 | } else if (isRABrace()) { 126 | token.append(programCode.charAt(index)); 127 | index += 1; 128 | if (isEqs()) { 129 | token.append(programCode.charAt(index)); 130 | index += 1; 131 | tokenClass = "GEQ"; 132 | } else { 133 | tokenClass = "GRE"; 134 | } 135 | } else if (isExc()) { 136 | token.append(programCode.charAt(index)); 137 | index += 1; 138 | if (isEqs()) { 139 | token.append(programCode.charAt(index)); 140 | index += 1; 141 | tokenClass = "NEQ"; 142 | } else { 143 | tokenClass = "NOT"; 144 | } 145 | } else if (isAdd()) { 146 | tokenClass = "PLUS"; 147 | token.append(programCode.charAt(index)); 148 | index += 1; 149 | } else if (isMinus()) { 150 | tokenClass = "MINU"; 151 | token.append(programCode.charAt(index)); 152 | index += 1; 153 | } else if (isStar()) { 154 | tokenClass = "MULT"; 155 | token.append(programCode.charAt(index)); 156 | index += 1; 157 | } else if (isPercent()) { 158 | tokenClass = "MOD"; 159 | token.append(programCode.charAt(index)); 160 | index += 1; 161 | } else if (isSemi()) { 162 | tokenClass = "SEMICN"; 163 | token.append(programCode.charAt(index)); 164 | index += 1; 165 | } else if (isComma()) { 166 | tokenClass = "COMMA"; 167 | token.append(programCode.charAt(index)); 168 | index += 1; 169 | } else if (isLParent()) { 170 | tokenClass = "LPARENT"; 171 | token.append(programCode.charAt(index)); 172 | index += 1; 173 | } else if (isRParent()) { 174 | tokenClass = "RPARENT"; 175 | token.append(programCode.charAt(index)); 176 | index += 1; 177 | } else if (isLBrack()) { 178 | tokenClass = "LBRACK"; 179 | token.append(programCode.charAt(index)); 180 | index += 1; 181 | } else if (isRBrack()) { 182 | tokenClass = "RBRACK"; 183 | token.append(programCode.charAt(index)); 184 | index += 1; 185 | } else if (isLBrace()) { 186 | tokenClass = "LBRACE"; 187 | token.append(programCode.charAt(index)); 188 | index += 1; 189 | } else if (isRBrace()) { 190 | tokenClass = "RBRACE"; 191 | token.append(programCode.charAt(index)); 192 | index += 1; 193 | } else if (isDQmark()) { 194 | token.append(programCode.charAt(index)); 195 | index += 1; 196 | this.formatCharNum = 0; 197 | while (!isDQmark()) { 198 | char a = programCode.charAt(index); 199 | if (a == '%' && programCode.charAt(index + 1) == 'd') { 200 | this.formatCharNum += 1; 201 | } else if (!(a==32 || a==33 || (40<=a && a<=126))) { 202 | ErrorRecorder.recordError(new Error(Error.Type.illegal_sym, lineNum)); 203 | } 204 | token.append(programCode.charAt(index)); 205 | index += 1; 206 | } 207 | token.append(programCode.charAt(index)); 208 | index += 1; 209 | tokenClass = "STRCON"; 210 | } else if (isDiv()) { 211 | index += 1; 212 | if (isDiv()) { 213 | while (!isNewLine()) { 214 | index += 1; 215 | } 216 | index += 1; 217 | return "annotation"; 218 | } else if (isStar()) { 219 | do { 220 | do { 221 | index += 1; 222 | isNewLine(); 223 | if (index >= programCode.length()) { 224 | error(); 225 | return "failed"; 226 | } 227 | } while (anoStar()); 228 | do { 229 | index += 1; 230 | isNewLine(); 231 | if (isDiv()) { 232 | index += 1; 233 | return "annotation"; 234 | } 235 | } while (isStar()); 236 | if (index >= programCode.length()) { 237 | error(); 238 | return "failed"; 239 | } 240 | } while (anoStar()); 241 | if (index == programCode.length()) { //reach the end without `*/` match the end of annotation. 242 | error(); 243 | } 244 | } else { 245 | token.append(programCode.charAt(index-1)); 246 | tokenClass = "DIV"; 247 | } 248 | } else { 249 | error(); 250 | return "failed"; 251 | } 252 | return tokenClass; 253 | } 254 | 255 | 256 | public String result() { 257 | StringBuilder ans = new StringBuilder(); 258 | for (Token token : tokens) { 259 | ans.append(token.toString()).append("\n"); 260 | } 261 | return ans.toString(); 262 | } 263 | 264 | public boolean isSpace() { 265 | return index < programCode.length() && programCode.charAt(index) == ' '; 266 | } 267 | 268 | public boolean isNewLine() { 269 | if (index < programCode.length() && programCode.charAt(index) == '\n'){ 270 | lineNum += 1; 271 | return true; 272 | } 273 | return false; 274 | } 275 | 276 | public boolean isTab() { 277 | return index < programCode.length() && programCode.charAt(index) == '\t'; 278 | } 279 | 280 | public boolean isLetter() { 281 | return index < programCode.length() && 282 | (Character.isLowerCase(programCode.charAt(index)) 283 | || Character.isUpperCase(programCode.charAt(index)) 284 | || programCode.charAt(index) == '_'); 285 | } 286 | 287 | public boolean isDigit() { 288 | return index < programCode.length() && Character.isDigit(programCode.charAt(index)); 289 | } 290 | 291 | public boolean isSemi() { 292 | return index < programCode.length() && programCode.charAt(index) == ';'; 293 | } 294 | 295 | public boolean isComma() { 296 | return index < programCode.length() && programCode.charAt(index) == ','; 297 | } 298 | 299 | public boolean isLBrace() { 300 | return index < programCode.length() && programCode.charAt(index) == '{'; 301 | } 302 | 303 | public boolean isRBrace() { 304 | return index < programCode.length() && programCode.charAt(index) == '}'; 305 | } 306 | 307 | public boolean isLBrack() { 308 | return index < programCode.length() && programCode.charAt(index) == '['; 309 | } 310 | 311 | public boolean isRBrack() { 312 | return index < programCode.length() && programCode.charAt(index) == ']'; 313 | } 314 | 315 | public boolean isLParent() { 316 | return index < programCode.length() && programCode.charAt(index) == '('; 317 | } 318 | 319 | public boolean isRParent() { 320 | return index < programCode.length() && programCode.charAt(index) == ')'; 321 | } 322 | 323 | public boolean isEqs() { 324 | return index < programCode.length() && programCode.charAt(index) == '='; 325 | } 326 | 327 | public boolean isAdd() { 328 | return index < programCode.length() && programCode.charAt(index) == '+'; 329 | } 330 | 331 | public boolean isMinus() { 332 | return index < programCode.length() && programCode.charAt(index) == '-'; 333 | } 334 | 335 | public boolean isStar() { 336 | return index < programCode.length() && programCode.charAt(index) == '*'; 337 | } 338 | 339 | public boolean anoStar() { 340 | return programCode.charAt(index) != '*'; 341 | } 342 | 343 | public boolean isPercent() { 344 | return index < programCode.length() && programCode.charAt(index) == '%'; 345 | } 346 | 347 | public boolean isLABrace() { 348 | return index < programCode.length() && programCode.charAt(index) == '<'; 349 | } 350 | 351 | public boolean isRABrace() { 352 | return index < programCode.length() && programCode.charAt(index) == '>'; 353 | } 354 | 355 | public boolean isVLine() { 356 | return index < programCode.length() && programCode.charAt(index) == '|'; 357 | } 358 | 359 | public boolean isAnd() {return index < programCode.length() && programCode.charAt(index) == '&'; } 360 | 361 | public boolean isExc() { 362 | return index < programCode.length() && programCode.charAt(index) == '!'; 363 | } 364 | 365 | public boolean isDQmark() { 366 | return index < programCode.length() && programCode.charAt(index) == '"'; 367 | } 368 | 369 | public boolean isDiv() { 370 | return index < programCode.length() && programCode.charAt(index) == '/'; 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /front/Token.java: -------------------------------------------------------------------------------- 1 | package front; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class Token { 7 | private final String tokenClass; // TokenClass Symbol 8 | //private final int codeVal; // encode value 0-37 9 | private final String originStr; // original string 10 | private final int intValue; // value(only `INTCON` have) 11 | private final int lineNum; 12 | private int formatCharNum; 13 | 14 | public static Map decode = new HashMap() {{ 15 | put(0, "IDENFR"); 16 | put(1, "MAINTK"); 17 | put(2, "CONSTTK"); 18 | put(3, "INTTK"); 19 | put(4, "BREAKTK"); 20 | put(5, "CONTINUETK"); 21 | put(6, "IFTK"); 22 | put(7, "ELSETK"); 23 | put(8, "WHILETK"); 24 | put(9, "GETINTTK"); 25 | put(10, "PRINTFTK"); 26 | put(11, "RETURNTK"); 27 | put(12, "VOIDTK"); 28 | put(13, "NOT"); 29 | put(14, "AND"); 30 | put(15, "OR"); 31 | put(16, "PLUS"); 32 | put(17, "MINU"); 33 | put(18, "MULT"); 34 | put(19, "DIV"); 35 | put(20, "MOD"); 36 | put(21, "LSS"); 37 | put(22, "LEQ"); 38 | put(23, "GRE"); 39 | put(24, "GEQ"); 40 | put(25, "EQL"); 41 | put(26, "NEQ"); 42 | put(27, "ASSIGN"); 43 | put(28, "SEMICN"); 44 | put(29, "COMMA"); 45 | put(30, "LPARENT"); 46 | put(31, "RPARENT"); 47 | put(32, "LBRACK"); 48 | put(33, "RBRACK"); 49 | put(34, "LBRACE"); 50 | put(35, "RBRACE"); 51 | put(36, "INTCON"); 52 | put(37, "STRCON"); 53 | }}; 54 | 55 | public Token(String tokenClass, String originStr, int lineNum) { 56 | this.tokenClass = tokenClass; 57 | this.originStr = originStr; 58 | this.lineNum = lineNum; 59 | if (tokenClass.equals("INTCON")) { 60 | this.intValue = Integer.parseInt(originStr); 61 | } else { 62 | this.intValue = 0; 63 | } 64 | this.formatCharNum = 0; 65 | } 66 | 67 | public Token(String tokenClass, String originStr, int lineNum, int formatCharNum) { 68 | this.tokenClass = tokenClass; 69 | this.originStr = originStr; 70 | this.lineNum = lineNum; 71 | if (tokenClass.equals("INTCON")) { 72 | this.intValue = Integer.parseInt(originStr); 73 | } else { 74 | this.intValue = 0; 75 | } 76 | this.formatCharNum = formatCharNum; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return this.tokenClass + " " + this.originStr; 82 | } 83 | 84 | 85 | public String getTokenClass() { 86 | return this.tokenClass; 87 | } 88 | 89 | public String getName() { 90 | return this.originStr; 91 | } 92 | 93 | public int getLineNum() { 94 | return this.lineNum; 95 | } 96 | 97 | public int getFormatCharNum() { 98 | return this.formatCharNum; 99 | } 100 | 101 | public int getInitValue() { 102 | return this.intValue; 103 | } 104 | 105 | public String getString() { 106 | return this.originStr.replaceAll("\"", ""); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /mid/Block.java: -------------------------------------------------------------------------------- 1 | package mid; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.regex.Pattern; 7 | 8 | public class Block { 9 | public int bno; 10 | public ArrayList midCodes; 11 | public ArrayList precursors = new ArrayList<>(); 12 | public ArrayList successors = new ArrayList<>(); 13 | public HashSet use; 14 | public HashSet def; 15 | public HashSet in = new HashSet<>(); 16 | public HashSet out = new HashSet<>(); 17 | public HashSet gen; 18 | public HashSet kill; 19 | public HashSet in_arrive = new HashSet<>(); 20 | public HashSet out_arrive = new HashSet<>(); 21 | 22 | 23 | public Block(int bno, ArrayList midCodes) { 24 | this.bno = bno; 25 | this.midCodes = midCodes; 26 | compute_use_def(); 27 | compute_gen_kill(); 28 | } 29 | 30 | private void compute_use_def() { 31 | use = new HashSet<>(); 32 | def = new HashSet<>(); 33 | for (MidCode midCode : midCodes) { 34 | String cur_def = midCode.get_def(); 35 | ArrayList cur_use = midCode.get_use(); 36 | for (String use : cur_use) { 37 | if (!def.contains(use) && use != null) { 38 | this.use.add(use); 39 | } 40 | } 41 | if (!use.contains(cur_def) && cur_def != null) { 42 | def.add(cur_def); 43 | } 44 | } 45 | } 46 | 47 | public void compute_gen_kill() { 48 | kill = new HashSet<>(); 49 | gen = new HashSet<>(); 50 | for (int i = midCodes.size() - 1; i >= 0; i--) { 51 | MidCode midCode = midCodes.get(i); 52 | if (midCode.d_index != null) { 53 | HashSet tmp = new HashSet<>(midCode.get_gen()); 54 | tmp.removeAll(kill); 55 | gen.addAll(tmp); 56 | kill.addAll(midCode.get_kill()); 57 | } 58 | } 59 | } 60 | 61 | public HashSet get_use() { 62 | return this.use; 63 | } 64 | 65 | public HashSet get_def() { 66 | return this.def; 67 | } 68 | 69 | public void remove_redundant_code() { 70 | HashSet un_defined_var = new HashSet<>(out); 71 | for (int i = midCodes.size() - 1; i >= 0; i--) { 72 | MidCode cur_code = midCodes.get(i); 73 | if (cur_code.get_def() != null && !un_defined_var.contains(cur_code.get_def())) { 74 | // System.out.println("========remove_redundant_code==========="); 75 | // System.out.println(cur_code.toString()); 76 | // System.out.println("========================================"); 77 | if (cur_code.instr == MidCode.Op.GETINT) { 78 | cur_code.instr = MidCode.Op.EMPTY_INPUT; 79 | } else { 80 | cur_code.instr = MidCode.Op.EMPTY; 81 | } 82 | } else { 83 | if (cur_code.get_def() != null) { 84 | un_defined_var.remove(cur_code.get_def()); 85 | } 86 | un_defined_var.addAll(cur_code.get_use()); 87 | } 88 | } 89 | } 90 | 91 | public void const_broad_cast() { 92 | HashMap const_val_table = new HashMap<>(); 93 | for (MidCode cur_code : midCodes) { 94 | boolean can_broadcast = false; 95 | HashMap var2const = new HashMap<>(); 96 | for (String use_var : cur_code.get_use()) { 97 | if (const_val_table.containsKey(use_var)) { 98 | // System.out.println("===============const_broadcast============="); 99 | // System.out.println(cur_code + " " + use_var + "->" + const_val_table.get(use_var)); 100 | // System.out.println("==========================================="); 101 | can_broadcast = true; 102 | var2const.put(use_var, const_val_table.get(use_var)); 103 | } 104 | } 105 | if (can_broadcast) { 106 | cur_code.refact(var2const); 107 | } 108 | String def_var = cur_code.get_def(); 109 | if (def_var != null && (cur_code.instr == MidCode.Op.VAR_DEF || cur_code.instr == MidCode.Op.ASSIGN) && begins_num(cur_code.operand2)) { 110 | const_val_table.put(def_var, cur_code.operand2); 111 | } else if (def_var != null) { 112 | const_val_table.remove(def_var); 113 | } 114 | } 115 | } 116 | 117 | public void const_broad_cast_by_arrival() { 118 | for (MidCode cur_code : midCodes) { 119 | HashMap name2value = new HashMap<>(); 120 | for (String use_var : cur_code.get_use()) { 121 | ArrayList define_point = new ArrayList<>(); 122 | for (Integer def_index : in_arrive) { 123 | if (DataFlower.d_index2code.get(def_index).get_def() != null && DataFlower.d_index2code.get(def_index).get_def().equals(use_var)) { 124 | define_point.add(def_index); 125 | } 126 | } 127 | if (define_point.size() == 1) { // only when define point - (only across block) 128 | HashSet block_in_def = new HashSet<>(); 129 | boolean define_in_block = false; 130 | for (MidCode cur_bloc_code : midCodes) { 131 | if (cur_bloc_code.equals(cur_code)) { 132 | if (block_in_def.contains(use_var)) { 133 | define_in_block = true; 134 | } 135 | break; 136 | } else { 137 | if (cur_bloc_code.d_index != null) { 138 | block_in_def.add(cur_bloc_code.get_def()); 139 | } 140 | } 141 | } 142 | if (!define_in_block) { 143 | MidCode define_code = DataFlower.d_index2code.get(define_point.get(0)); 144 | if ((define_code.instr == MidCode.Op.VAR_DEF || define_code.instr == MidCode.Op.ASSIGN) && begins_num(define_code.operand2)) { 145 | name2value.put(use_var, define_code.operand2); 146 | // System.out.println("===============const_broadcast_across_base_block============="); 147 | // System.out.println(cur_code + " " + use_var + "->" + define_code.operand2); 148 | // System.out.println("==========================================="); 149 | } 150 | } 151 | } 152 | } 153 | if (!name2value.isEmpty()) { 154 | cur_code.refact(name2value); 155 | } 156 | } 157 | } 158 | 159 | public static final Pattern IS_DIGIT = Pattern.compile("[0-9]*"); 160 | 161 | public static boolean begins_num(String operand) { 162 | return IS_DIGIT.matcher(operand).matches() || operand.charAt(0) == '+' || operand.charAt(0) == '-'; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /mid/DataFlower.java: -------------------------------------------------------------------------------- 1 | package mid; 2 | 3 | import SymTable.FuncFormVar; 4 | import SymTable.SymItem; 5 | 6 | import java.io.IOException; 7 | import java.io.PrintStream; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | 12 | import static mid.MidCode.Op.ENTER_WHILE; 13 | import static mid.MidCode.Op.EXIT_BLOCK; 14 | import static mid.MidCode.Op.EXIT_WHILE; 15 | import static mid.MidCode.Op.FUNC; 16 | import static mid.MidCode.Op.NEW_BLOCK; 17 | import static mid.MidCode.Op.SIGNAL_ARR_ADDR; 18 | 19 | public class DataFlower { 20 | 21 | public static ArrayList blocks = new ArrayList<>(); 22 | 23 | public static final int START = 0; 24 | public static final int EXIT = -1; 25 | 26 | public static HashMap bno2block = new HashMap<>(); 27 | 28 | public static HashMap> var_define_points = new HashMap<>(); 29 | 30 | public static HashMap d_index2code = new HashMap<>(); 31 | 32 | public static void define_point_ranking(MidCodeList midCodeList) { 33 | int d_index = 0; 34 | for (MidCode midCode : midCodeList.midCodes) { 35 | String def = midCode.get_def(); 36 | if (def != null && def.charAt(0) != '#') { 37 | midCode.d_index = d_index; 38 | d_index2code.put(d_index, midCode); 39 | d_index += 1; 40 | if (var_define_points.containsKey(def)) { 41 | var_define_points.get(def).add(midCode.d_index); 42 | } else { 43 | var_define_points.put(def, new HashSet<>()); 44 | } 45 | } 46 | } 47 | } 48 | 49 | public static final HashSet HELP_INSTR = new HashSet() {{ 50 | add(SIGNAL_ARR_ADDR); 51 | add(NEW_BLOCK); 52 | add(EXIT_BLOCK); 53 | add(ENTER_WHILE); 54 | add(EXIT_WHILE); 55 | }}; 56 | 57 | public static void divide_base_block(MidCodeList midCodeList) { 58 | remove_redundant_label(midCodeList); 59 | HashMap allocated_bno = new HashMap<>(); 60 | int cur_bno = 0; 61 | for (MidCode midCode : midCodeList.midCodes) { 62 | if (!HELP_INSTR.contains(midCode.instr)) { 63 | if (midCode.instr == MidCode.Op.JUMP || midCode.instr == MidCode.Op.JUMP_IF || midCode.instr == MidCode.Op.RETURN) { 64 | allocated_bno.put(midCode, cur_bno); 65 | cur_bno += 1; 66 | } else if (midCode.instr == MidCode.Op.LABEL || midCode.instr == MidCode.Op.FUNC) { 67 | cur_bno += 1; 68 | allocated_bno.put(midCode, cur_bno); 69 | } else { 70 | allocated_bno.put(midCode, cur_bno); 71 | 72 | } 73 | } 74 | } 75 | 76 | int bno = 0; 77 | ArrayList block_seq = new ArrayList<>(); 78 | for (MidCode midCode : midCodeList.midCodes) { 79 | if (allocated_bno.containsKey(midCode)) { 80 | if (allocated_bno.get(midCode) != bno) { 81 | bno = allocated_bno.get(midCode); 82 | Block block = new Block(allocated_bno.get(midCode), block_seq); 83 | blocks.add(block); 84 | bno2block.put(bno, block); 85 | block_seq = new ArrayList<>(); 86 | } 87 | block_seq.add(midCode); 88 | } 89 | } 90 | 91 | regulate_block(); 92 | link_base_block(); 93 | compute_in_out(); 94 | compute_in_out_arrive(); 95 | } 96 | 97 | public static void link_base_block() { 98 | HashMap label2block = new HashMap<>(); 99 | for (Block block : blocks) { 100 | if (!block.midCodes.isEmpty() && (block.midCodes.get(0).instr == MidCode.Op.LABEL || block.midCodes.get(0).instr == MidCode.Op.FUNC)) { 101 | if (block.midCodes.get(0).instr == MidCode.Op.LABEL) { 102 | label2block.put(block.midCodes.get(0).result, block); 103 | } else { 104 | label2block.put(block.midCodes.get(0).operand2, block); 105 | } 106 | } 107 | } 108 | for (int i = 0; i < blocks.size(); i++) { 109 | Block block = blocks.get(i); 110 | Block nextBlock = null; 111 | if (i < blocks.size() - 1) { 112 | nextBlock = blocks.get(i + 1); 113 | } 114 | if (!block.midCodes.isEmpty()) { 115 | MidCode lastCode = block.midCodes.get(block.midCodes.size() - 1); 116 | if (lastCode.instr == MidCode.Op.JUMP) { 117 | block.successors.add(label2block.get(lastCode.result).bno); 118 | label2block.get(lastCode.result).precursors.add(block.bno); 119 | } else if (lastCode.instr == MidCode.Op.JUMP_IF) { 120 | block.successors.add(label2block.get(lastCode.result).bno); 121 | label2block.get(lastCode.result).precursors.add(block.bno); 122 | if (nextBlock != null) { 123 | block.successors.add(nextBlock.bno); 124 | nextBlock.precursors.add(block.bno); 125 | } 126 | } else if (lastCode.instr == MidCode.Op.CALL) { 127 | block.successors.add(EXIT); 128 | label2block.get(lastCode.operand1).precursors.add(0); 129 | } else if (lastCode.instr == MidCode.Op.RETURN || nextBlock == null) { 130 | block.successors.add(EXIT); 131 | } else { 132 | block.successors.add(nextBlock.bno); 133 | nextBlock.precursors.add(block.bno); 134 | } 135 | 136 | } 137 | } 138 | } 139 | 140 | public static void regulate_block() { 141 | ArrayList new_blocks = new ArrayList<>(); 142 | for (Block block : blocks) { 143 | if (!block.midCodes.isEmpty()) { 144 | new_blocks.add(block); 145 | } 146 | } 147 | if (new_blocks.get(0).midCodes.get(0).instr != MidCode.Op.FUNC) { // global_var_define 148 | new_blocks.remove(0); 149 | } 150 | blocks = new_blocks; 151 | } 152 | 153 | private static void remove_redundant_label(MidCodeList midCodeList) { 154 | ArrayList new_midCodes = new ArrayList<>(); 155 | ArrayList exist_jump_labels = new ArrayList<>(); 156 | for (MidCode midCode : midCodeList.midCodes) { 157 | if (midCode.instr == MidCode.Op.JUMP || midCode.instr == MidCode.Op.JUMP_IF) { 158 | exist_jump_labels.add(midCode.result); 159 | } 160 | } 161 | 162 | for (MidCode midCode : midCodeList.midCodes) { 163 | if (midCode.instr == MidCode.Op.LABEL && !exist_jump_labels.contains(midCode.result)) { 164 | continue; 165 | } 166 | new_midCodes.add(midCode); 167 | } 168 | midCodeList.midCodes = new_midCodes; 169 | } 170 | 171 | public static void compute_in_out() { 172 | boolean modified; 173 | do { 174 | modified = false; 175 | for (int i = blocks.size() - 1; i >= 0; i--) { 176 | Block block = blocks.get(i); 177 | for (int successor_bno : block.successors) { 178 | if (successor_bno != EXIT) block.out.addAll(bno2block.get(successor_bno).in); 179 | } 180 | HashSet new_in = new HashSet<>(block.use); 181 | HashSet out_minus_def = new HashSet<>(block.out); 182 | out_minus_def.removeAll(block.def); 183 | new_in.addAll(out_minus_def); 184 | if (modified_s(block.in, new_in)) { 185 | modified = true; 186 | block.in = new_in; 187 | } 188 | } 189 | } while (modified); 190 | } 191 | 192 | public static void compute_in_out_arrive() { 193 | boolean modified; 194 | do { 195 | modified = false; 196 | for (Block block : blocks) { 197 | for (int precursor_bno : block.precursors) { 198 | if (precursor_bno != START) block.in_arrive.addAll(bno2block.get(precursor_bno).out_arrive); 199 | } 200 | HashSet new_out = new HashSet(block.gen); 201 | HashSet in_minus_kill = new HashSet(block.in_arrive); 202 | in_minus_kill.removeAll(block.kill); 203 | new_out.addAll(in_minus_kill); 204 | if (modified_i(block.out_arrive, new_out)) { 205 | modified = true; 206 | block.out_arrive = new_out; 207 | } 208 | } 209 | } while (modified); 210 | } 211 | 212 | private static boolean modified_s(HashSet l1, HashSet l2) { 213 | HashSet remains1 = new HashSet<>(l1); 214 | remains1.removeAll(l2); 215 | HashSet remains2 = new HashSet<>(l2); 216 | remains2.removeAll(l1); 217 | return !(remains1.isEmpty() && remains2.isEmpty()); 218 | } 219 | 220 | private static boolean modified_i(HashSet l1, HashSet l2) { 221 | HashSet remains1 = new HashSet<>(l1); 222 | remains1.removeAll(l2); 223 | HashSet remains2 = new HashSet<>(l2); 224 | remains2.removeAll(l1); 225 | return !(remains1.isEmpty() && remains2.isEmpty()); 226 | } 227 | 228 | 229 | public static void remove_redundant() { 230 | for (Block block : blocks) { 231 | block.remove_redundant_code(); 232 | } 233 | } 234 | 235 | public static void const_broadcast() { 236 | for (Block block : blocks) { 237 | block.const_broad_cast(); 238 | block.const_broad_cast_by_arrival(); 239 | } 240 | } 241 | 242 | 243 | public static void printBlockInfo(String filename) { 244 | PrintStream out = System.out; 245 | try { 246 | PrintStream os = new PrintStream(filename); 247 | System.setOut(os); 248 | } catch (IOException ignored) { 249 | } 250 | for (Block block : blocks) { 251 | System.out.println("================================================="); 252 | System.out.println("current_bno: " + block.bno); 253 | System.out.println("precursor_bnos: " + block.precursors); 254 | System.out.println("successor_bnos: " + block.successors); 255 | System.out.println("use: " + block.get_use()); 256 | System.out.println("def: " + block.get_def()); 257 | System.out.println("in: " + block.in); 258 | System.out.println("out: " + block.out); 259 | System.out.println("#################################################"); 260 | for (MidCode midCode : block.midCodes) { 261 | System.out.println(midCode); 262 | } 263 | System.out.println("================================================="); 264 | System.out.println(); 265 | } 266 | System.setOut(out); 267 | } 268 | 269 | public static void refresh(MidCodeList midCodeList) { 270 | blocks = new ArrayList<>(); 271 | bno2block = new HashMap<>(); 272 | var_define_points = new HashMap<>(); 273 | d_index2code = new HashMap<>(); 274 | for (MidCode midCode: midCodeList.midCodes) { 275 | midCode.d_index = null; 276 | } 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /mid/MidCode.java: -------------------------------------------------------------------------------- 1 | package mid; 2 | 3 | import com.sun.org.apache.bcel.internal.generic.CASTORE; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.regex.Pattern; 9 | 10 | public class MidCode { 11 | 12 | public enum Op { 13 | ASSIGN, ADD, SUB, MUL, DIV, MOD, PRINT, NOT, 14 | GETINT, FUNC, END_FUNC, PREPARE_CALL, CALL, 15 | PUSH_PARA, RETURN, VAR_DEF, CONST_DEF, 16 | ARR_SAVE, ARR_LOAD, PUSH_PARA_ARR, 17 | JUMP_IF, JUMP, LABEL, SET, 18 | 19 | // help_type 20 | SIGNAL_ARR_ADDR, NEW_BLOCK, EXIT_BLOCK, WHILE_BIND, EMPTY, EMPTY_INPUT, ENTER_WHILE, 21 | EXIT_WHILE, FUNC_FORM_VAR_DEF 22 | } 23 | 24 | public final HashMap toString = new HashMap() {{ 25 | put(Op.ASSIGN, "ASSIGN"); 26 | put(Op.ADD, "ADD"); 27 | put(Op.SUB, "SUB"); 28 | put(Op.MUL, "MUL"); 29 | put(Op.DIV, "DIV"); 30 | put(Op.MOD, "MOD"); 31 | put(Op.PRINT, "PRINT"); 32 | put(Op.NOT, "NOT"); 33 | put(Op.GETINT, "GETINT"); 34 | put(Op.FUNC, "FUNC"); 35 | put(Op.END_FUNC, "END_FUNC"); 36 | put(Op.PREPARE_CALL, "PREPARE_CALL"); 37 | put(Op.CALL, "CALL"); 38 | put(Op.PUSH_PARA, "PUSH_PARA"); 39 | put(Op.RETURN, "RETURN"); 40 | put(Op.VAR_DEF, "VAR_DEF"); 41 | put(Op.CONST_DEF, "CONST_DEF"); 42 | put(Op.NEW_BLOCK, "NEW_BLOCK"); 43 | put(Op.EXIT_BLOCK, "EXIT_BLOCK"); 44 | put(Op.PUSH_PARA_ARR, "PUSH_PARA_ARR"); 45 | put(Op.JUMP_IF, "JUMP_IF"); 46 | put(Op.JUMP, "JUMP"); 47 | put(Op.LABEL, "LABEL"); 48 | put(Op.SET, "SET"); 49 | }}; 50 | 51 | public Op instr; 52 | 53 | public String operand1; 54 | 55 | public String operand2; 56 | 57 | public String result; 58 | 59 | /* for arrive_data_flow */ 60 | public Integer d_index = null; 61 | 62 | public String define; 63 | 64 | public ArrayList use; 65 | 66 | 67 | public MidCode(Op instr, String operand1, String operand2, String result) { 68 | this.instr = instr; 69 | this.operand1 = operand1; 70 | this.operand2 = operand2; 71 | this.result = result; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | if (instr == Op.EMPTY) { 77 | return "_E_M_P_T_Y_"; 78 | } 79 | if (instr == Op.FUNC_FORM_VAR_DEF) { 80 | return "FUNC_FORM_VAR_DEF " + this.operand1; 81 | } 82 | if (instr == Op.EMPTY_INPUT) { 83 | return "EMPTY_INPUT"; 84 | } 85 | if (instr == Op.LABEL) { 86 | return result + ":"; 87 | } 88 | if (instr == Op.JUMP) { 89 | return "JUMP" + " " + result; 90 | } 91 | if (instr == Op.JUMP_IF) { 92 | return "JUMP_IF" + " " + operand1.split(" ")[0] + " " + operand2 + " " + operand1.split(" ")[1] + " " + result; 93 | } 94 | if (instr == Op.SET) { 95 | return "SET " + result + " := " + operand1.split(" ")[0] + " " + operand2 + " " + operand1.split(" ")[1]; 96 | } 97 | if (instr == Op.GETINT) { 98 | return operand1 + " = " + "input()"; 99 | } 100 | if (instr == Op.VAR_DEF || instr == Op.CONST_DEF) { 101 | return "var " + operand1 + (operand2.equals("#VACANT") ? "" : "= " + operand2); 102 | } 103 | if (instr == Op.FUNC || instr == Op.END_FUNC) { 104 | return "#############" + toString.get(instr) + " " + operand1 + " " + operand2 + "############"; 105 | } 106 | if (instr == Op.ASSIGN || instr == Op.ARR_SAVE || instr == Op.ARR_LOAD) { 107 | return operand1 + " = " + operand2; 108 | } 109 | if (!result.equals("#VACANT")) { 110 | return result + " = " + operand1 + " " + toString.get(instr) + " " + operand2; 111 | } 112 | if (operand1.equals("#VACANT") && operand2.equals("#VACANT")) { 113 | return toString.get(instr); 114 | } 115 | if (operand2.equals("#VACANT")) { 116 | return toString.get(instr) + " " + operand1; 117 | } 118 | return toString.get(instr) + " " + operand1 + " " + operand2; 119 | } 120 | 121 | public static boolean is_arith(MidCode.Op op) { 122 | return op == Op.ADD || op == Op.SUB || op == Op.MUL || op == Op.DIV; 123 | } 124 | 125 | public String get_def() { 126 | switch (this.instr) { 127 | case ASSIGN: 128 | case VAR_DEF: 129 | case GETINT: 130 | case ARR_LOAD: 131 | case FUNC_FORM_VAR_DEF: 132 | this.define = (!isVar(operand1)) ? null : this.operand1; 133 | return this.define; 134 | case ADD: 135 | case SUB: 136 | case MUL: 137 | case DIV: 138 | case MOD: 139 | case SET: 140 | this.define = (!isVar(result)) ? null : this.result; 141 | return this.define; 142 | default: 143 | return null; 144 | } 145 | } 146 | 147 | public ArrayList get_use() { 148 | ArrayList used_vars = new ArrayList<>(); 149 | switch (this.instr) { 150 | case ASSIGN: 151 | case VAR_DEF: 152 | if (isVar(operand2)) { 153 | used_vars.add(operand2); 154 | } 155 | break; 156 | case ADD: 157 | case SUB: 158 | case MUL: 159 | case DIV: 160 | case MOD: 161 | if (isVar(operand1)) { 162 | used_vars.add(operand1); 163 | } 164 | if (isVar(operand2)) { 165 | used_vars.add(operand2); 166 | } 167 | break; 168 | case PRINT: 169 | case PUSH_PARA: 170 | case RETURN: 171 | if (isVar(operand1)) { 172 | used_vars.add(operand1); 173 | } 174 | break; 175 | case ARR_SAVE: 176 | String rank_r = this.operand1.split("\\[")[1].substring(0, operand1.split("\\[")[1].length() - 1); 177 | if (isVar(rank_r)) { 178 | used_vars.add(rank_r); 179 | } 180 | if (isVar(operand2)) { 181 | used_vars.add(operand2); 182 | } 183 | break; 184 | case ARR_LOAD: 185 | String rank_l = this.operand2.split("\\[")[1].substring(0, operand2.split("\\[")[1].length() - 1); 186 | if (isVar(rank_l)) { 187 | used_vars.add(rank_l); 188 | } 189 | break; 190 | case SET: 191 | case JUMP_IF: 192 | String num1 = this.operand1.split(" ")[0]; 193 | String num2 = this.operand1.split(" ")[1]; 194 | if (isVar(num1)) { 195 | used_vars.add(num1); 196 | } 197 | if (isVar(num2)) { 198 | used_vars.add(num2); 199 | } 200 | break; 201 | } 202 | this.use = used_vars; 203 | return used_vars; 204 | } 205 | 206 | public void refact(HashMap var2const) { 207 | switch (this.instr) { 208 | case SET: 209 | case JUMP_IF: 210 | String num1 = this.operand1.split(" ")[0]; 211 | String num2 = this.operand1.split(" ")[1]; 212 | for (HashMap.Entry pair: var2const.entrySet()) { 213 | if (num1.equals(pair.getKey())) { 214 | num1 = pair.getValue(); 215 | } 216 | if (num2.equals(pair.getKey())) { 217 | num2 = pair.getValue(); 218 | } 219 | } 220 | this.operand1 = num1 + " " + num2; 221 | return; 222 | case ARR_SAVE: 223 | String rank_r = this.operand1.split("\\[")[1].substring(0, operand1.split("\\[")[1].length() - 1); 224 | for (HashMap.Entry pair: var2const.entrySet()) { 225 | if (rank_r.equals(pair.getKey())) { 226 | this.operand1 = this.operand1.split("\\[")[0] + "[" + pair.getValue() + "]"; 227 | } 228 | if (operand2.equals(pair.getKey())) { 229 | operand2 = pair.getValue(); 230 | } 231 | } 232 | return; 233 | case ARR_LOAD: 234 | String rank_l = this.operand2.split("\\[")[1].substring(0, operand2.split("\\[")[1].length() - 1); 235 | for (HashMap.Entry pair: var2const.entrySet()) { 236 | if (rank_l.equals(pair.getKey())) { 237 | this.operand2 = this.operand2.split("\\[")[0] + "[" + pair.getValue() + "]"; 238 | } 239 | } 240 | return; 241 | default: 242 | for (HashMap.Entry pair: var2const.entrySet()) { 243 | if (operand1.equals(pair.getKey())) { 244 | operand1 = pair.getValue(); 245 | } 246 | if (operand2.equals(pair.getKey())) { 247 | operand2 = pair.getValue(); 248 | } 249 | } 250 | } 251 | } 252 | 253 | public HashSet get_gen() { 254 | HashSet gen = new HashSet<>(); 255 | gen.add(this.d_index); 256 | return gen; 257 | } 258 | 259 | public HashSet get_kill() { 260 | if (this.get_def() != null) { 261 | HashSet kill = new HashSet<>(DataFlower.var_define_points.get(this.get_def())); 262 | kill.remove(this.d_index); 263 | return kill; 264 | } 265 | return new HashSet<>(); 266 | } 267 | 268 | public static final Pattern IS_DIGIT = Pattern.compile("[0-9]*"); 269 | public static boolean begins_num(String operand) { 270 | return IS_DIGIT.matcher(operand).matches() || operand.charAt(0) == '+' || operand.charAt(0) == '-'; 271 | } 272 | 273 | public static boolean isVar(String operand) { 274 | if (operand.split("@").length == 2 && operand.split("@")[1].equals("<0,0>")) { // global_var 275 | return false; 276 | } 277 | return ((operand.charAt(0) != '#' || operand.startsWith("#T")) && !begins_num(operand) && !operand.equals("%RTX")); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /mid/MidCodeList.java: -------------------------------------------------------------------------------- 1 | package mid; 2 | 3 | import SymTable.FuncFormVar; 4 | import SymTable.SymItem; 5 | import SymTable.SymbolTable; 6 | import SymTable.Var; 7 | import com.sun.org.apache.xpath.internal.operations.Div; 8 | import front.ASD.ASDNode; 9 | import front.ASD.ConstInitVal; 10 | import front.ASD.InitVal; 11 | import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; 12 | 13 | import java.io.IOException; 14 | import java.io.PrintStream; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.HashMap; 18 | import java.util.Stack; 19 | import java.util.regex.Pattern; 20 | 21 | import static mid.MidCode.Op.ADD; 22 | import static mid.MidCode.Op.ASSIGN; 23 | import static mid.MidCode.Op.EMPTY; 24 | import static mid.MidCode.Op.EMPTY_INPUT; 25 | import static mid.MidCode.Op.EXIT_BLOCK; 26 | import static mid.MidCode.Op.FUNC; 27 | import static mid.MidCode.Op.FUNC_FORM_VAR_DEF; 28 | import static mid.MidCode.Op.JUMP; 29 | import static mid.MidCode.Op.JUMP_IF; 30 | import static mid.MidCode.Op.LABEL; 31 | import static mid.MidCode.Op.NEW_BLOCK; 32 | import static mid.MidCode.Op.SET; 33 | 34 | public class MidCodeList { 35 | public ArrayList midCodes = new ArrayList<>(); 36 | public int tmpIndex; 37 | public int label_cnt; 38 | public ArrayList strCons; 39 | public int[] block_location; 40 | public final int[] block_num = new int[100]; 41 | public HashMap node2symItem; 42 | 43 | public final Stack begin_tables = new Stack<>(); 44 | public final Stack end_tables = new Stack<>(); 45 | 46 | public HashMap> curFuncTables; 47 | 48 | public MidCodeList(HashMap node2symItem, HashMap> curFuncTables) { 49 | this.node2symItem = node2symItem; 50 | this.curFuncTables = curFuncTables; 51 | this.midCodes = new ArrayList<>(); 52 | this.tmpIndex = 0; 53 | this.strCons = new ArrayList<>(); 54 | this.label_cnt = 0; 55 | block_location = new int[]{0, 0}; 56 | for (int i = 0; i < 100; i += 1) { 57 | block_num[i] = 0; 58 | } 59 | } 60 | 61 | public String add(MidCode.Op instr, String operand1, String operand2, String r) { 62 | if (instr.equals(MidCode.Op.WHILE_BIND)) { 63 | begin_tables.push(operand1); 64 | end_tables.push(operand2); 65 | return null; 66 | } 67 | if (instr.equals(MidCode.Op.PUSH_PARA) && midCodes.get(midCodes.size() - 1).instr.equals(MidCode.Op.SIGNAL_ARR_ADDR)) { 68 | midCodes.remove(midCodes.size() - 1); 69 | instr = MidCode.Op.PUSH_PARA_ARR; 70 | } else if (!instr.equals(MidCode.Op.PRINT)) { 71 | if (operand2.contains("[") && !instr.equals(MidCode.Op.ARR_LOAD)) { //array var must be load into temple var. 72 | operand2 = this.add(MidCode.Op.ARR_LOAD, "#AUTO", operand2, "#VACANT"); 73 | } 74 | if (operand1.contains("[") && !instr.equals(MidCode.Op.ARR_SAVE)) { 75 | if (instr.equals(MidCode.Op.JUMP_IF) || instr.equals(MidCode.Op.SET)) { 76 | String op1 = operand1.split(" ")[0]; 77 | String op2 = operand1.split(" ")[1]; 78 | if (op1.contains("[")) { 79 | op1 = this.add(MidCode.Op.ARR_LOAD, "#AUTO", op1, "#VACANT"); 80 | } 81 | if (op2.contains("[")) { 82 | op2 = this.add(MidCode.Op.ARR_LOAD, "#AUTO", op2, "#VACANT"); 83 | } 84 | operand1 = op1 + " " + op2; 85 | } else if (instr.equals(MidCode.Op.ASSIGN) || instr.equals(MidCode.Op.GETINT)) { 86 | if (instr.equals(MidCode.Op.ASSIGN)) { 87 | operand2 = this.add(MidCode.Op.ASSIGN, "#AUTO", operand1, "#VACANT"); 88 | } else { 89 | operand2 = this.add(MidCode.Op.GETINT, "#AUTO", "#VACANT", "#VACANT"); 90 | } 91 | instr = MidCode.Op.ARR_SAVE; 92 | } else { 93 | operand1 = this.add(MidCode.Op.ARR_LOAD, "#AUTO", operand1, "#VACANT"); 94 | } 95 | } 96 | } else { 97 | if (operand1.contains("[") && !operand2.equals("#STRCONS")) { //array var must be load into temple var. 98 | operand1 = this.add(MidCode.Op.ARR_LOAD, "#AUTO", operand1, "#VACANT"); 99 | } 100 | } 101 | if (instr.equals(MidCode.Op.NEW_BLOCK)) { 102 | block_location[0] += 1; 103 | block_num[block_location[0]] += 1; 104 | block_location[1] = block_num[block_location[0]] - 1; 105 | operand1 = Arrays.toString(block_location); 106 | } else if (instr.equals((MidCode.Op.EXIT_BLOCK))) { 107 | operand1 = Arrays.toString(block_location); 108 | block_location[0] = block_location[0] - 1; 109 | block_location[1] = block_num[block_location[0]] - 1; 110 | } 111 | String result = r; 112 | if (result.equals("#AUTO")) { 113 | result = "#T" + tmpIndex; 114 | tmpIndex += 1; 115 | } 116 | if (result.equals("#AUTO_LABEL")) { 117 | result = "label_" + label_cnt; 118 | label_cnt += 1; 119 | } 120 | if (operand1.equals("#AUTO")) { 121 | operand1 = "#T" + tmpIndex; 122 | result = operand1; 123 | tmpIndex += 1; 124 | } 125 | if (operand2.equals("#STRCONS")) { 126 | strCons.add(operand1); 127 | operand2 = "#VACANT"; 128 | operand1 = "#str" + Integer.toString(strCons.size() - 1); 129 | } 130 | midCodes.add(new MidCode(instr, operand1, operand2, result)); 131 | if (instr.equals(FUNC)) { 132 | for (SymItem symItem: curFuncTables.get(operand2)) { 133 | if (symItem instanceof FuncFormVar && ((FuncFormVar) symItem).getDimension() == 0) { 134 | this.add(FUNC_FORM_VAR_DEF, symItem.getUniqueName(), "#VACANT", "#VACANT"); 135 | } 136 | } 137 | } 138 | return result; 139 | } 140 | 141 | public void printCode(String fileName) { 142 | PrintStream out = System.out; 143 | try { 144 | PrintStream os = new PrintStream(fileName); 145 | System.setOut(os); 146 | } catch (IOException ignored) { 147 | ignored.printStackTrace(); 148 | } 149 | int i = 0; 150 | for (String strCon : strCons) { 151 | System.out.println("str" + i + ": " + "\"" + strCon + "\""); 152 | i += 1; 153 | } 154 | for (MidCode midCode : midCodes) { 155 | System.out.println(midCode.toString()); 156 | } 157 | System.setOut(out); 158 | } 159 | 160 | public void remove_useless_code() { 161 | ArrayList new_midCodes = new ArrayList<>(); 162 | for (MidCode midCode: this.midCodes) { 163 | if (midCode.instr == NEW_BLOCK || midCode.instr == EXIT_BLOCK) { 164 | } else { 165 | new_midCodes.add(midCode); 166 | } 167 | } 168 | this.midCodes = new_midCodes; 169 | } 170 | 171 | public void addTmp(HashMap> funcTable, SymbolTable global_table) { 172 | String name = ""; 173 | int end_addr = 4; 174 | ArrayList currentFuncTable = null; 175 | for (MidCode midCode : midCodes) { 176 | if (midCode.instr.equals(MidCode.Op.FUNC)) { 177 | name = midCode.operand2; 178 | currentFuncTable = funcTable.get(name); 179 | if (currentFuncTable.isEmpty()) { 180 | end_addr = 4; 181 | } else { 182 | end_addr = currentFuncTable.get(currentFuncTable.size() - 1).getAddr() + currentFuncTable.get(currentFuncTable.size() - 1).getSize(); 183 | if (end_addr == 0) { // special debug--funcFormVar[-1][...] 184 | end_addr = 4; 185 | } 186 | } 187 | } else if (midCode.instr.equals(MidCode.Op.END_FUNC)) { 188 | name = ""; 189 | } else if (midCode.result.charAt(0) == '#' && midCode.result.charAt(1) == 'T') { 190 | Var var = new Var(midCode.result, false, (InitVal) null, 0, new ArrayList(), "#inFunc"); 191 | end_addr = var.set_addr(end_addr); 192 | if (currentFuncTable != null) { 193 | currentFuncTable.add(var); 194 | } else { 195 | global_table.symItems.add(var); 196 | } 197 | } 198 | } 199 | } 200 | 201 | public String alloc_label() { 202 | String result = "label_" + label_cnt; 203 | label_cnt += 1; 204 | return result; 205 | } 206 | 207 | public void remove_redundant_assign() { 208 | ArrayList new_midCodes = new ArrayList<>(); 209 | for (int i = 0; i < midCodes.size() - 1; i += 1) { 210 | MidCode c1 = midCodes.get(i); 211 | MidCode c2 = midCodes.get(i + 1); 212 | if (c2.instr.equals(MidCode.Op.ASSIGN) && 213 | c1.result.charAt(0) == '#' && c1.result.equals(c2.operand2) && MidCode.is_arith(c1.instr)) { 214 | new_midCodes.add(new MidCode(c1.instr, c1.operand1, c1.operand2, c2.operand1)); 215 | i += 1; 216 | } else if (c1.instr == MidCode.Op.ASSIGN && c1.operand1.charAt(0) == '#' && c1.operand1.equals(c2.operand1) 217 | && MidCode.is_arith(c2.instr)) { 218 | new_midCodes.add(new MidCode(c2.instr, c1.operand2, c2.operand2, c2.result)); 219 | i += 1; 220 | } else if (c1.instr == MidCode.Op.ASSIGN && c1.operand1.charAt(0) == '#' && c1.operand1.equals(c2.operand2) && 221 | MidCode.is_arith(c2.instr)) { 222 | new_midCodes.add(new MidCode(c2.instr, c2.operand1, c1.operand2, c2.result)); 223 | i += 1; 224 | } else if (i == midCodes.size() - 2) { 225 | new_midCodes.add(c1); 226 | new_midCodes.add(c2); 227 | } else { 228 | new_midCodes.add(c1); 229 | } 230 | } 231 | midCodes = new_midCodes; 232 | } 233 | 234 | public void swap_facter() { 235 | ArrayList new_midCode = new ArrayList<>(); 236 | for (MidCode midCode : midCodes) { 237 | if (MidCode.is_arith(midCode.instr) && midCode.instr != MidCode.Op.DIV && begins_num(midCode.operand1) && !begins_num(midCode.operand2)) { 238 | new_midCode.add(new MidCode(midCode.instr, midCode.operand2, midCode.operand1, midCode.result)); 239 | } else { 240 | new_midCode.add(midCode); 241 | } 242 | } 243 | midCodes = new_midCode; 244 | } 245 | 246 | public void arith_to_assign() { 247 | ArrayList new_midCode = new ArrayList<>(); 248 | for (MidCode midCode : midCodes) { 249 | if (midCode.instr == MidCode.Op.MUL && midCode.operand1.equals("1")) { 250 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand2, "#VACANT")); 251 | } else if (midCode.instr == MidCode.Op.MUL && midCode.operand2.equals("1")) { 252 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand1, "#VACANT")); 253 | } else if (midCode.instr == MidCode.Op.DIV && midCode.operand2.equals("1")) { 254 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand1, "#VACANT")); 255 | } else if (midCode.instr == MidCode.Op.MOD && (midCode.operand1.equals("1") || midCode.operand2.equals("1"))) { 256 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, "0", "#VACANT")); 257 | } else if (midCode.instr == ADD && midCode.operand1.equals("0")) { 258 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand2, "#VACANT")); 259 | } else if (midCode.instr == ADD && midCode.operand2.equals("0")) { 260 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand1, "#VACANT")); 261 | } else if (midCode.instr == MidCode.Op.SUB && midCode.operand2.equals("0")) { 262 | new_midCode.add(new MidCode(MidCode.Op.ASSIGN, midCode.result, midCode.operand1, "#VACANT")); 263 | } else { 264 | new_midCode.add(midCode); 265 | } 266 | } 267 | midCodes = new_midCode; 268 | } 269 | 270 | public void remove_redundant_tmp() { 271 | boolean modified; 272 | do { 273 | modified = false; 274 | ArrayList new_midCodes = new ArrayList<>(); 275 | for (int i = 0; i < midCodes.size() - 1; i += 1) { 276 | MidCode c1 = midCodes.get(i); 277 | MidCode c2 = midCodes.get(i + 1); 278 | if (c1.instr != MidCode.Op.ASSIGN && c2.instr != MidCode.Op.ASSIGN && !c2.result.equals("#VACANT") 279 | && !begins_num(c2.result) && !begins_num(c1.result) && !begins_num(c2.operand1) && c2.result.charAt(0) == '#' 280 | && c2.operand1.charAt(0) == '#' && c1.result.equals(c2.operand1) && begins_num(c1.operand2) && begins_num(c2.operand2)) { 281 | if (c1.instr == c2.instr) { 282 | if (c1.instr == MidCode.Op.ADD || c1.instr == MidCode.Op.SUB) { 283 | new_midCodes.add(new MidCode(c1.instr, c1.operand1, Integer.toString(Integer.parseInt(c1.operand2) + Integer.parseInt(c2.operand2)), c2.result)); 284 | modified = true; 285 | i++; 286 | } else if (c1.instr == MidCode.Op.MUL || c1.instr == MidCode.Op.DIV) { 287 | new_midCodes.add(new MidCode(c1.instr, c1.operand1, Integer.toString(Integer.parseInt(c1.operand2) * Integer.parseInt(c2.operand2)), c2.result)); 288 | modified = true; 289 | i++; 290 | } else { 291 | new_midCodes.add(c1); 292 | } 293 | } else if ((c1.instr == MidCode.Op.ADD && c2.instr == MidCode.Op.SUB) || (c1.instr == MidCode.Op.SUB && c2.instr == MidCode.Op.ADD)) { 294 | new_midCodes.add(new MidCode(c1.instr, c1.operand1, Integer.toString(Integer.parseInt(c1.operand2) - Integer.parseInt(c2.operand2)), c2.result)); 295 | modified = true; 296 | i++; 297 | } else { 298 | new_midCodes.add(c1); 299 | } 300 | } else if (c1.instr == ASSIGN && c2.instr == ASSIGN && c1.operand1.equals(c2.operand2) && c2.operand2.charAt(0) == '#') { 301 | new_midCodes.add(new MidCode(ASSIGN, c2.operand1, c1.operand2, "#VACANT")); 302 | modified = true; 303 | i++; 304 | } else if (c1.instr == ASSIGN && c1.operand1.equals(c1.operand2)) { 305 | modified = true; 306 | } else if (i == midCodes.size() - 2) { 307 | new_midCodes.add(c1); 308 | new_midCodes.add(c2); 309 | } else { 310 | new_midCodes.add(c1); 311 | } 312 | } 313 | midCodes = new_midCodes; 314 | } while (modified); 315 | } 316 | 317 | public void remove_redundant_arith() { 318 | ArrayList new_midCode = new ArrayList<>(); 319 | for (MidCode midCode : midCodes) { 320 | if (begins_num(midCode.operand1) && begins_num(midCode.operand2)) { 321 | Integer res; 322 | int left = Integer.parseInt(midCode.operand1); 323 | int right = Integer.parseInt(midCode.operand2); 324 | switch (midCode.instr) { 325 | case ADD: 326 | res = left + right; 327 | break; 328 | case SUB: 329 | res = left - right; 330 | break; 331 | case MUL: 332 | res = left * right; 333 | break; 334 | case DIV: 335 | res = left / right; 336 | break; 337 | case MOD: 338 | res = left % right; 339 | break; 340 | default: 341 | res = null; 342 | } 343 | if (res != null) { 344 | midCode.instr = ASSIGN; 345 | midCode.operand1 = midCode.result; 346 | midCode.operand2 = res.toString(); 347 | } 348 | } 349 | } 350 | return; 351 | } 352 | 353 | public void remove_redundant_jump() { 354 | ArrayList new_midCode = new ArrayList<>(); 355 | for (int i = 0; i < midCodes.size(); i += 1) { 356 | boolean can_remove = false; 357 | if (midCodes.get(i).instr.equals(JUMP)) { 358 | int k = i + 1; 359 | while (k < midCodes.size() && midCodes.get(k).instr.equals(LABEL)) { 360 | if (midCodes.get(k).result.equals(midCodes.get(i).result)) { 361 | can_remove = true; 362 | break; 363 | } 364 | k += 1; 365 | } 366 | } 367 | if (!can_remove) { 368 | new_midCode.add(midCodes.get(i)); 369 | } 370 | } 371 | midCodes = new_midCode; 372 | } 373 | 374 | public void remove_redundant_compare() { 375 | ArrayList new_midCode = new ArrayList<>(); 376 | for (MidCode midCode : midCodes) { 377 | if (midCode.instr == JUMP_IF && compare_is_const(midCode.operand1)) { 378 | if (compare_is_true(midCode.operand1, midCode.operand2)) { 379 | new_midCode.add(new MidCode(JUMP, "#VACANT", "#VACANT", midCode.result)); 380 | } // else remove branch_instr 381 | } else if (midCode.instr == SET && compare_is_const(midCode.operand1)) { 382 | if (compare_is_true(midCode.operand1, midCode.operand2)) { 383 | new_midCode.add(new MidCode(ASSIGN, midCode.result, "1", "#VACANT")); 384 | } else { 385 | new_midCode.add(new MidCode(ASSIGN, midCode.result, "0", "#VACANT")); 386 | } 387 | } else { 388 | new_midCode.add(midCode); 389 | } 390 | } 391 | midCodes = new_midCode; 392 | } 393 | 394 | private boolean compare_is_true(String operand1, String operand2) { 395 | int left = Integer.parseInt(operand1.split(" ")[0]); 396 | int right = Integer.parseInt(operand1.split(" ")[1]); 397 | return operand2.equals("<") ? left < right : 398 | operand2.equals(">") ? left > right : 399 | operand2.equals("<=") ? left <= right : 400 | operand2.equals(">=") ? left >= right : 401 | operand2.equals("!=") ? left != right : operand2.equals("==") && left == right; 402 | } 403 | 404 | private boolean compare_is_const(String operand) { 405 | return begins_num(operand.split(" ")[0]) && begins_num(operand.split(" ")[1]); 406 | } 407 | 408 | 409 | public static final Pattern IS_DIGIT = Pattern.compile("[0-9]*"); 410 | 411 | public static boolean begins_num(String operand) { 412 | return IS_DIGIT.matcher(operand).matches() || operand.charAt(0) == '+' || operand.charAt(0) == '-'; 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /mid/VarConfliction.java: -------------------------------------------------------------------------------- 1 | package mid; 2 | 3 | import com.sun.org.apache.bcel.internal.generic.NEW; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | import java.util.Map; 10 | 11 | public class VarConfliction { 12 | 13 | public static final int LOOP_FACTOR = 30; 14 | public static final HashMap> funcVars = new HashMap<>(); 15 | public static final HashMap var_weight = new HashMap<>(); 16 | public static final HashMap d_index2Block = new HashMap<>(); 17 | public static final HashMap midCode2Bno = new HashMap<>(); 18 | 19 | public static final ArrayList blocks = DataFlower.blocks; 20 | 21 | public static final HashMap> var_define_points = DataFlower.var_define_points; 22 | 23 | public static final HashMap> block_used_vars = new HashMap>(){{ 24 | for (Block block: blocks) { 25 | HashSet used_vars = new HashSet<>(); 26 | for (MidCode midCode: block.midCodes) { 27 | used_vars.addAll(midCode.get_use()); 28 | if (midCode.d_index != null) { 29 | d_index2Block.put(midCode.d_index, block); 30 | } 31 | midCode2Bno.put(midCode, block.bno); 32 | } 33 | put(block.bno, used_vars); 34 | } 35 | }}; 36 | 37 | public static void get_func_vars(MidCodeList midCodeList) { 38 | int weight = 1; 39 | String currentFuncName = null; 40 | HashSet currentFuncVars = new HashSet<>(); 41 | for (MidCode midCode: midCodeList.midCodes) { 42 | if (midCode.instr == MidCode.Op.ENTER_WHILE) { 43 | weight = weight * LOOP_FACTOR; 44 | } else if (midCode.instr == MidCode.Op.EXIT_WHILE) { 45 | weight = weight / LOOP_FACTOR; 46 | } else if (midCode.instr == MidCode.Op.FUNC) { 47 | currentFuncName = midCode.operand2; 48 | currentFuncVars = new HashSet<>(); 49 | } else if (midCode.instr == MidCode.Op.END_FUNC) { 50 | currentFuncVars.removeIf(x->x.startsWith("#T")); 51 | funcVars.put(currentFuncName, currentFuncVars); 52 | } 53 | if (midCode.get_def() != null) { 54 | currentFuncVars.add(midCode.get_def()); 55 | if (var_weight.containsKey(midCode.get_def())) { 56 | var_weight.replace(midCode.get_def(), var_weight.get(midCode.get_def()) + weight); 57 | } else { 58 | var_weight.put(midCode.get_def(), weight); 59 | } 60 | } 61 | for (String use_var: midCode.get_use()) { 62 | currentFuncVars.add(use_var); 63 | if (var_weight.containsKey(use_var)) { 64 | var_weight.replace(use_var, var_weight.get(use_var) + weight); 65 | } else { 66 | var_weight.put(use_var, weight); 67 | } 68 | } 69 | } 70 | } 71 | 72 | public static HashSet use_chain(Integer d_index, String VarName) { 73 | HashSet use_chain = new HashSet<>(); 74 | use_chain.add(d_index2Block.get(d_index).bno); 75 | for (Block block: blocks) { 76 | if (block.in_arrive.contains(d_index) && block_used_vars.get(block.bno).contains(VarName)) { 77 | use_chain.add(block.bno); 78 | } 79 | } 80 | return use_chain; 81 | } 82 | 83 | public static void gen_conflict_() { 84 | for (Map.Entry> pair: funcVars.entrySet()) { 85 | for (String var_name: pair.getValue()) { 86 | ArrayList> use_chains = new ArrayList<>(); 87 | for (Integer d_index: var_define_points.get(var_name)) { 88 | use_chains.add(use_chain(d_index, var_name)); 89 | } 90 | HashSet> net = new HashSet<>(); 91 | for (int i = 0; i < use_chains.size(); i++) { 92 | HashSet use_chain = use_chains.get(i); 93 | if (i == 0) { 94 | net.add(use_chain); 95 | } 96 | for (HashSet net_sub_chain: net) { 97 | if (have_common(net_sub_chain, use_chain)) { 98 | net_sub_chain.addAll(use_chain); 99 | } 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | public static boolean have_common(HashSet s1, HashSet s2) { 107 | for (Integer i: s1) { 108 | if (s2.contains(i)) { 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunzeY/SysCompiler/662344a2a05b849fb4fbb1770e37a93a36c96879/stack.png --------------------------------------------------------------------------------