Simple Language Compiler Code

import javax.swing.*;
import java.util.*;
import java.io.*;
/**
* Compiler for Simple Machine Language. Run through the Run class. All Compiler errors are returned here.
* The compiler can take any characters other than numbers as variables. This means that "alpha", "lol", "iamsocoaaaa", "1337squad", and "ah$"
* are legal variables names, but "3" and "54" are not.
*
* @author (Paul Park)
* @version (8/24/2011)
*/
public class Compiler
{
private ArrayList smlCodes;
private ArrayList simpleCodes;
private Map symbolTab;
private Map lineAddress;
private Map lineResolve;
private Map addressLine;
private Map addressAdjust;
private int instIndex;
private int dataIndex;
private int currLine;
private int ifAdjust; // Adjustment for if statements

public Compiler(ArrayList contents)
{
smlCodes = new ArrayList();
simpleCodes = contents;
symbolTab = new TreeMap();
lineAddress = new TreeMap();
lineResolve = new TreeMap();
addressLine = new TreeMap();
addressAdjust = new TreeMap();
instIndex = 0;
dataIndex = 99;
ifAdjust = 0;
int track = 0;
while(track < 100)
{
smlCodes.add("0");
track++;
}
}

public void process() throws IOException
{
// WRITE FILE
// Have the user enter the name of the file to be created or overwritten
String filename = JOptionPane.showInputDialog("Enter the name of the output SML file");

Iterator iter = simpleCodes.iterator();

//Zeroth Pass
// ADD ALL THE CONSTANTS
while (iter.hasNext())
{
processCheck();
String get = iter.next();
constantCheck(get);
}
//

iter = simpleCodes.iterator();

//First Pass
while (iter.hasNext())
{
processCheck();
String get = iter.next();
readLine(get);
}

//Open the file and associate it with a file variable
PrintWriter outfile = new PrintWriter(new FileWriter(new File(filename)));

//Second Pass
Iterator smlIter = smlCodes.iterator();
int track = 0;
boolean keepGoing = true;
while(smlIter.hasNext())
{
String get = smlIter.next();
if (get.equals("0"))
{
track++;
outfile.println(get);
}
else
{
String command = get.substring(0, 2);
//Unresolved Check SECOND PASS
if (get.substring(2, 4).equals("XX"))
{
int lineNum = addressLine.get(track);
currLine = lineNum;
int lineToResolve = lineResolve.get(lineNum);
int resolvedAddress = -1;
try
{
resolvedAddress = lineAddress.get(lineToResolve);
}
catch(Exception e)
{
throw new IllegalArgumentException("ERROR: Invalid Goto Line Number");
}
if (addressAdjust.containsKey(resolvedAddress))
{
resolvedAddress = resolvedAddress - addressAdjust.get(resolvedAddress);
}

String addressStr = String.valueOf(resolvedAddress);
if (resolvedAddress < 10)
{
addressStr = "0"+addressStr;
}
get = command + addressStr;
lineAddress.put(lineNum, track - ifAdjust);
addressLine.put(track - ifAdjust, lineNum);
}
track++;
outfile.println(get);
}
}

// close the file
outfile.close();
}

public void readLine(String line)
{
/**
* Following errors are monitored in this method:
*
* Invalid Line Number
* Invalid Operator
* Duplicate Line
* Invalid Command
* Line Order Error
* Print without Variable
* Print with Undeclared Variable
* Print literal
* Input Literal
* Goto No Line Num
* Goto Invalid Line Num
* Invalid Operand
* No Relational Op
* Let with Nondeclared Right
* Let with Literal Left and Right
* Let not enough Operations and operands
*/

String[] strings = line.split(" ");
int lineNum = -1;
try
{
lineNum = Integer.parseInt(strings[0]);
}
catch (Exception e)
{
throw new IllegalArgumentException("ERROR: Line number is invalid.");
}

if (lineAddress.get(lineNum) != null)
{
throw new IllegalArgumentException("ERROR: Duplicate Line Number");
}

if (lineNum < currLine) // currLine is actually the last line in this context.
{
throw new IllegalArgumentException("ERROR: Line Number Out of Order");
}
currLine = lineNum;
String keyword = strings[1];

if (keyword.equals("end"))
{
String smlCode = "4300";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
return;
}

if (keyword.equals("rem"))
{
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
return;
}

if (strings.length < 3)
{
throw new NullPointerException("ERROR: No Input! (Did you forget a variable or line number after the command?)");
}
String input = strings[2];

int i = 3;
while (i < strings.length)
{
input += " " + strings[i];
i++;
}

if (keyword.equals("input"))
{
String data = "";
int size = dataIndex;
boolean inputExists = false;
try
{
int dataInt = symbolTab.get(input);
data = String.valueOf(dataInt);
size = dataInt;
inputExists = true;
}
catch(Exception e)
{
data = String.valueOf(dataIndex);
}

if (dataIndex < 10)
{
data = "0"+data;
}
if (isInt(input))
{
throw new IllegalArgumentException("ERROR: Input Literal");
}
String smlCode = "10"+data;
smlCodes.set(instIndex, smlCode);
symbolTab.put(input, size);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
if (!inputExists)
dataIndex--;
instIndex++;
return;
}
if (keyword.equals("print"))
{
int indexRef = -1;

if (isInt(input))
{
throw new IllegalArgumentException("ERROR: Print Literal");
}

try
{
indexRef = symbolTab.get(input);
}
catch(Exception e)
{
throw new NullPointerException("ERROR: Undeclared Variable: " + input);
}
String data = String.valueOf(indexRef);
if (indexRef < 10)
{
data = "0"+data;
}
String smlCode = "11"+data;
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
instIndex++;
return;
}
if (keyword.equals("goto"))
{
//Placeholder for unresolved addresses
String smlCode = "40"+"XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, Integer.parseInt(input));
instIndex++;
return;
}
if (keyword.equals("if"))
{
String[] inputs = input.split(" ");
String first = inputs[0];
String operator = inputs[1];
String second = inputs[2];
int gotoLine = Integer.parseInt(inputs[4]);
String smlCode = "";

try
{
int check = symbolTab.get(first);
}
catch(Exception e)
{
throw new IllegalArgumentException("ERROR: Nonexistent Variable Used in Goto Command");
}

try
{
int check = symbolTab.get(second);
}
catch(Exception e)
{
throw new IllegalArgumentException("ERROR: Nonexistent Variable Used in Goto Command");
}

int indFir = symbolTab.get(first);
String firStr = String.valueOf(indFir);

if (indFir < 10)
{
firStr = "0"+firStr;
}
int indSec = symbolTab.get(second);
String secStr = String.valueOf(indSec);

if (indSec < 10)
{
secStr = "0"+secStr;
}

if (operator.equals(">"))
{

smlCode = "20" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
smlCode = "31" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
// Destination
String instStr = String.valueOf(instIndex + 3);
if (instIndex + 3 < 10)
instStr = "0"+instStr;
smlCode = "41" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
instStr = String.valueOf(instIndex + 2);
if (instIndex + 2 < 10)
instStr = "0"+instStr;
smlCode = "42" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "40"+"XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 4);
instIndex++;
}
else if (operator.equals("<"))
{
smlCode = "20" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
smlCode = "31" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
// Destination
String instStr = String.valueOf(instIndex + 3);
if (instIndex + 3 < 10)
instStr = "0"+instStr;
smlCode = "41" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
instStr = String.valueOf(instIndex + 2);
if (instIndex + 2 < 10)
instStr = "0"+instStr;
smlCode = "42" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "40"+"XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 4);
instIndex++;
}
else if (operator.equals(">="))
{
smlCode = "20" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
smlCode = "31" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
// Destination
String instStr = String.valueOf(instIndex + 2);
if (instIndex + 2 < 10)
instStr = "0"+instStr;
smlCode = "41" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "40"+"XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 3);
instIndex++;
}
else if (operator.equals("<="))
{
smlCode = "20" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
smlCode = "31" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
// Destination
String instStr = String.valueOf(instIndex + 2);
if (instIndex + 2 < 10)
instStr = "0"+instStr;
smlCode = "41" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "40"+"XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 3);
instIndex++;
}
else if (operator.equals("=="))
{
smlCode = "20" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "31" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "42"+"XX";
smlCodes.set(instIndex, smlCode);

lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 2);

instIndex++;
}
else if (operator.equals("!="))
{
smlCode = "20" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
smlCode = "31" + secStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
// Destination
String instStr = String.valueOf(instIndex + 2);
if (instIndex + 2 < 10)
instStr = "0"+instStr;
smlCode = "42" + instStr;
smlCodes.set(instIndex, smlCode);
instIndex++;

smlCode = "40XX";
smlCodes.set(instIndex, smlCode);
lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
lineResolve.put(lineNum, gotoLine);
addressAdjust.put(instIndex, 3);
instIndex++;
}
else
{
throw new IllegalArgumentException("ERROR: Invalid or Missing Operator");
}
return;
}
if (keyword.equals("let"))
{
//Save off the address of the left-hand side variable
int varStorage = 0;

lineAddress.put(lineNum, instIndex);
addressLine.put(instIndex, lineNum);
String[] preInputs = input.split(" ");
// INPUT ADJUSTMENT. GET RID OF THE LEFT HAND SIDE VARIABLE AND THE EQUAL SIGN
int preSize = preInputs.length - 2;
String[] inputs = new String[preSize];
i = 0;
while (i < inputs.length)
{
inputs[i] = preInputs[i + 2];
i++;
}
// UPDATE input variable with this new one.
input = inputs[0];
i = 1;
while (i < inputs.length)
{
input += " " + inputs[i];
i++;
}
i = 0;

if (isInt(strings[2]))
{
throw new IllegalArgumentException("ERROR: Literal on the Left Side of the Equation during Let Command");
}

if (symbolTab.get(strings[2]) == null)
{
String data = String.valueOf(dataIndex);
if (dataIndex < 10)
{
data = "0"+data;
}
symbolTab.put(strings[2], dataIndex);
varStorage = dataIndex;
}
else
{
varStorage = symbolTab.get(strings[2]);
}

String varStorStr = "";
if (varStorage < 10)
{
varStorStr = "0"+String.valueOf(varStorage);
}
else
{
varStorStr = String.valueOf(varStorage);
}

String postFix = convertToPostFix(input);
LinkedList stack = new LinkedList();
String[] postFixes = postFix.split(" ");
for (int maxSize = 0; maxSize < postFixes.length; maxSize++)
{
stack.add(postFixes[maxSize]);
}
while (!stack.isEmpty())
{
String temp = stack.removeFirst();
if (getOperatorPrecedence(temp) == -1)
{
try
{
int check = symbolTab.get(temp);
}
catch(Exception e)
{
throw new NullPointerException("ERROR: Nondeclared Argument on the Right Side of the Equation during Let Command");
}
int dataIn = symbolTab.get(temp);
String dataStr = "";
if (dataIn < 10)
{
dataStr = "0"+String.valueOf(dataIn);
}
else
{
dataStr = String.valueOf(dataIn);
}
String smlCode = "20" + dataStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
String data = String.valueOf(dataIndex);
if (dataIndex < 10)
{
data = "0"+data;
}
smlCode = "21" + data;
smlCodes.set(instIndex, smlCode);
instIndex++;
dataIndex--;
}
else
{
int numberFir = dataIndex+2;
String firStr = String.valueOf(numberFir);
if (numberFir < 10)
{
firStr = "0"+firStr;
}
int numberSec = dataIndex+1;
String secStr = String.valueOf(numberSec);
if (numberSec < 10)
{
secStr = "0"+secStr;
}
String smlCode = "20" + firStr;
smlCodes.set(instIndex, smlCode);
instIndex++;
switch (getOperatorPrecedence(temp))
{
case 3:
smlCode = "33" + secStr;
break;
case 2:
smlCode = "32" + secStr;
break;
case 1:
smlCode = "30" + secStr;
break;
case 0:
smlCode = "31" + secStr;
break;
default:
throw new IllegalArgumentException("ERROR: Invalid operator.");
}
smlCodes.set(instIndex, smlCode);
instIndex++;
if (stack.isEmpty())
{
smlCode = "21" + varStorStr;
}
else
{
smlCode = "21" + firStr;
}
smlCodes.set(instIndex, smlCode);
instIndex++;
dataIndex++;
}
}
return;
}
// IF WE GET HERE, THEN IT'S BAD!!!! INVALID COMMAND
throw new IllegalArgumentException("ERROR: Invalid Command.");

}

public static String convertToPostFix(String infix)
{
LinkedList queue = new LinkedList();
LinkedList stack = new LinkedList();
Stack process = new Stack();
String[] values = infix.split(" ");
int i = 0;
int size = values.length;
while (i < size)
{
stack.add(values[i]);
i++;
}

// The following int variable checks for Let not enough operations error
// A value of 1 means that the last mathematical unit was an operator.
// A value of 0 means that the last mathematical unit was a number or a variable.
int lastOp = -1;

while (!stack.isEmpty())
{
String temp = stack.removeFirst();
int opPrec = getOperatorPrecedence(temp);
int currOp;
if (opPrec == -1) // Is not an operator
currOp = 0;
else
currOp = 1;

if (stack.isEmpty())
{
if (currOp == 1)
{
throw new IllegalArgumentException("ERROR: Not enough operands during Let command.");
}
}

if (currOp == lastOp)
throw new IllegalArgumentException("ERROR: Missing an operator (or a variable or a number) between two variables or numbers (or operators) during Let command.");

lastOp = currOp;

if (temp.equals("*") || temp.equals("+") || temp.equals("-") || temp.equals("/"))
{
boolean continueLoop = true;
while (continueLoop && !process.isEmpty())
{
String tempOp = process.pop();
int tempOpPrec = getOperatorPrecedence(tempOp);
int currentPrec = getOperatorPrecedence(temp);
if (tempOpPrec > currentPrec)
{
queue.add(tempOp);
}
else
continueLoop = false;
}
process.add(temp);
}
else if (temp.equals("("))
{
process.add(temp);
}
else if (temp.equals(")"))
{
boolean keepGoing = true;
while (keepGoing)
{
String operator = process.pop();
queue.add(operator);
if (process.isEmpty())
keepGoing = false;
else if (process.peek() != "(")
keepGoing = false;
}
}
else
{
queue.add(temp);
}

}

while (!process.empty())
{
String temp = process.pop();
queue.add(temp);
}

String returnValue = "";

while (!queue.isEmpty())
{
String get = queue.removeFirst();
returnValue += get + " ";
}

return returnValue;

}

public static int getOperatorPrecedence(String input)
{
switch (input.charAt(0))
{
case '*': return 3;
case '/': return 2;
case '+': return 1;
case '-': return 0;
}
return -1;
}

public static boolean isInt(String i)
{
try
{
Integer.parseInt(i);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}

public int getErrorLine()
{
return currLine;
}

public void processCheck()
{
if (instIndex > 99 || dataIndex < 0)
throw new IllegalArgumentException("ERROR: Out of memory");
}

public void constantCheck(String line)
{
String[] strings = line.split(" ");
String keyword = strings[1];

if (keyword.equals("let"))
{
String input = strings[2];
int i = 3;
while (i < strings.length)
{
input += " " + strings[i];
i++;
}
i = 2;
String[] inputs = input.split(" ");
//TWO DIGIT CONSTANTS
while (i < inputs.length)
{
if (isInt(inputs[i]))
{
int number = Integer.parseInt(inputs[i]);
String smlCode = "00";
if (number < 10)
{
smlCode += "0"+inputs[i];
}
else
{
smlCode += inputs[i];
}
symbolTab.put(inputs[i], dataIndex);
smlCodes.set(dataIndex, smlCode);
dataIndex--;
}
i++;
}
}
}

}