public String reduce(int production) { result = null; if (line == output.length + 1) { Quad[] temp = new Quad[output.length * 2]; System.arraycopy(output, line, temp, 0, line - 1); output = temp; } switch (production) { /* * This reduction signifies an EOF has been reached in the source * file with no errors being thrown by any of the compilers * component parts. At this point the code generator will begin * iterating through the stack and printing the lines of code * generated to an output assembly file, which will be used in micE. */ case 0: output[line] = new Quad(line, "HLT", "", "", ""); line++; try { PrintWriter out = new PrintWriter(outFile); for (int x = 0; x < line; x++) { cLine = x + " " + output[x].op + " "; if (output[x].a1.matches("[-]*[0-9]+")) { cLine += "#" + output[x].a1 + ","; } else if (output[x].a1.matches("TRUE")) { cLine += "#1" + ","; } else if (output[x].a1.matches("FALSE")) { cLine += "#0" + ","; } else { cLine += output[x].a1 + ","; } if (output[x].a2.matches("[-]*[0-9]+")) { cLine += "#" + output[x].a2 + ","; } else { cLine += output[x].a2 + ","; } if (output[x].a3.matches("[-]*[0-9]+")) { cLine += "#" + output[x].a3; } else { cLine += output[x].a3; } out.println(cLine); cLine = ""; } out.close(); } catch (IOException e) { } /* * This case is for when an assignment is made in the * declaration body of the code, which is the only time in the * declaration body where code is generated. */ case 4: op1 = gs.getT(); op3 = gs.getT(); if (op1.matches("[a-z]")) { char c = op1.charAt(0); int ic = (int) c; op1 = String.valueOf(ic); } else if (op1.matches("TRUE")) { op1 = "1"; } else if (op1.matches("FALSE")) { op1 = "0"; } output[line] = new Quad(line, "STO", op1, "", op3); line++; break; /* * This reduction generated two lines of code: one to print * the value of the given identifier, and one to move to a new * line. */ case 24: op1 = gs.getT(); if (sym.getType(op1).matches("CHAR")) { // char c = sym.getValue(op1).charAt(0); // int ic = (int) c; // op1 = String.valueOf(ic); output[line] = new Quad(line, "SYS", "-2", op1, ""); line++; } else { output[line] = new Quad(line, "SYS", "-1", gs.getT(), ""); line++; } output[line] = new Quad(line, "SYS", "0", "", ""); line++; break; /* * This case simply prints the value of an identifier without * moving to a new line */ case 25: op1 = gs.getT(); if (sym.getType(op1).matches("CHAR")) { // char c = sym.getValue(op1).charAt(0); // int ic = (int) c; // op1 = String.valueOf(ic); output[line] = new Quad(line, "SYS", "-2", op1, ""); line++; } else if (sym.getType(op1).matches("VARCHAR2")) { // Deprecated } else { output[line] = new Quad(line, "SYS", "-1", op1, ""); line++; } break; /* * This case simple moves to a new line */ case 26: output[line] = new Quad(line, "SYS", "0", "", ""); line++; break; /* * This case allows the program to read and store user input */ case 27: output[line] = new Quad(line, "SYS", "1", "", gs.getT()); line++; break; /* * This statement back-patches the start code of a conditional * statement for the line to jump to in order to skip the lines * that would be executed if the condition is false. */ case 28: loopBack.pop(); output[needPatch.pop()].a3 = String.valueOf(line); break; /* * This statement back-patches the start code of a looping * statement for the line to jump to in order to skip the lines * that would be executed if the condition is false. */ case 29: output[line] = new Quad(line, "JMP", "", "", String.valueOf(loopBack.pop())); line++; output[needPatch.pop()].a3 = String.valueOf(line); break; /* * This statement handles assignment operations within the body * of the code. */ case 30: // Assignment String vOp1 = ""; op3 = gs.getT(); op1 = gs.getT(); vOp1 = gs.getT(); if (temps > 0) { op1 = "temp" + temps; s = sym.getSymbol(op3); code = s.changeValue(String.valueOf(sum)); if (code != 0) { err.DisplayError(Math.abs(code)); } } else if (op1.matches("[0-9]+")) { s = sym.getSymbol(op3); code = s.changeValue(String.valueOf(op1)); if (code != 0) { err.DisplayError(Math.abs(code)); } } else if (op1.matches("TRUE")) { s = sym.getSymbol(op3); code = s.changeValue(op1); if (code != 0) { err.DisplayError(Math.abs(code)); } op1 = "1"; } else if (op1.matches("FALSE")) { s = sym.getSymbol(op3); code = s.changeValue(op1); if (code != 0) { err.DisplayError(Math.abs(code)); } op1 = "0"; } else { s = sym.getSymbol(op3); code = s.changeValue(sym.getValue(op3)); if (code != 0) { err.DisplayError(Math.abs(code)); } } output[line] = new Quad(line, "STO", op1, "", op3); temps = 0; sum = 0; line++; break; /* * This case manages type casting */ case 34: String tar = gs.getT(); String type = gs.getT(); if (tar.matches("CHAR")) { String temp = tar; tar = type; type = temp; } if (tar.matches("BOOLEAN")) { err.DisplayError(5); } if (type.matches("VARCHAR2") || type.matches("POSITIVE") || type.matches("NUMBER")) { String size = gs.getT(); sym.getSymbol(tar).changeSize(size); } code = sym.getSymbol(tar).changeType(type); if (code != 0) { err.DisplayError(Math.abs(code)); } gs.addT(tar); break; /* * This case generates relational operations, leaving a line of * code to back-patch after the number of lines within the * conditional section have been determined. */ case 37: op1 = gs.getT(); op2 = gs.getT(); if (op2.matches("[>]")) { relop = "JGT"; } else if (op2.matches("[>][=]")) { relop = "JGE"; } else if (op2.matches("[=][=]")) { relop = "JEQ"; } else if (op2.matches("[<][=]")) { relop = "JLE"; } else if (op2.matches("[<]")) { relop = "JLT"; } else if (op2.matches("[<][>]")) { relop = "JNE"; } op3 = gs.getT(); if (op3.matches("TRUE")) { op3 = "1"; } else if (op3.matches("FALSE")) { op3 = "0"; } output[line] = new Quad(line, relop, op1, op3, String.valueOf(line + 3)); loopBack.push(line); line++; output[line] = new Quad(line, "STO", "0", "", "t1"); line++; output[line] = new Quad(line, "JMP", "", "", String.valueOf(line + 2)); line++; output[line] = new Quad(line, "STO", "1", "", "t1"); line++; output[line] = new Quad(line, "JNE", "1", "t1", ""); needPatch.push(line); line++; break; /* * This case handles addition and subtraction operations */ case 39: // First read operators and operand from stack op1 = gs.getT(); op2 = gs.getT(); op3 = gs.getT(); // Check if op1 and op 3 are values or identifiers if (op1.matches("temp[0-9]+")) { i1 = sum; } else if (op1.matches("[a-z][a-z0-9$_#]*")) { i1 = Integer.parseInt(sym.getValue(op1)); } else { i1 = Integer.parseInt(op1); } if (op3.matches("temp[0-9]+")) { i2 = sum; } else if (op3.matches("[a-z][a-z0-9$_#]*")) { i2 = Integer.parseInt(sym.getValue(op3)); } else { i2 = Integer.parseInt(op3); } if (op2.matches("[+]")) { temps++; sum = i1 + i2; result = "temp" + temps; output[line] = new Quad(line, "ADD", op1, op3, result); } else if (op2.matches("[-]")) { temps++; sum = i1 + i2; result = "temp" + temps; output[line] = new Quad(line, "SUB", op1, op3, result); } gs.addT(result); line++; break; /* * This case handles multiplication, division, and modulus * operations */ case 41: op1 = gs.getT(); op2 = gs.getT(); op3 = gs.getT(); // Check if op1 and op 3 are values or identifiers if (op1.matches("temp[0-9]+")) { i1 = sum; } else if (op1.matches("[a-z][a-z0-9$_#]*")) { i1 = Integer.parseInt(sym.getValue(op1)); } else { i1 = Integer.parseInt(op1); } if (op3.matches("temp[0-9]+")) { i2 = sum; } else if (op3.matches("[a-z][a-z0-9$_#]*")) { i2 = Integer.parseInt(sym.getValue(op3)); } else { i2 = Integer.parseInt(op3); } if (op2.matches("[*]")) { temps++; sum = i1 * i2; result = "temp" + temps; output[line] = new Quad(line, "MUL", op1, op3, result); } else if (op2.matches("[/]")) { temps++; sum = i1 / i2; result = "temp" + temps; output[line] = new Quad(line, "DIV", op1, op3, result); } else if (op2.matches("[%]")) { temps++; sum = i1 % i2; result = "temp" + temps; output[line] = new Quad(line, "MOD", op1, op3, result); } gs.addT(result); line++; break; default: // Do nothing break; } return result; }