package eu.tankernn.assembly.compiler; import java.util.ArrayList; import java.util.List; public class LineParser { public static class OPCodes { public static final byte NOP = 0x0, LDA = 0x1, ADD = 0x2, SUB = 0x3, AND = 0x4, OR = 0x5, NOT_B = 0x6, STO = 0x7, OUT = 0x8, JMP = 0x9, HLT = 0xA; } String line; int lineIndex; ArrayList list = new ArrayList(); String[] instruction; int pos = 0; public LineParser(String line, int lineIndex) { this.line = line; this.lineIndex = lineIndex; instruction = line.split("\\s+"); } public Byte[] parse() throws SyntaxErrorException { // Comment if (line.startsWith(";")) { return null; } // Add a label if (instruction[0].endsWith(":")) { Assemble.addLabel(instruction[0].substring(0, instruction[0].length() - 2)); pos++; } // Add a literal byte if (instruction[pos].startsWith("$")) try { byte b = parseToByte(instruction[pos]); list.add(b); return listToByteArray(list); } catch (NumberFormatException ex) { } String command = instruction[pos].toUpperCase(); switch (command) { case "NOP": addWithoutAddress(OPCodes.NOP); break; case "LDA": addWithAddress(OPCodes.LDA); break; case "ADD": addWithAddress(OPCodes.ADD); break; case "SUB": addWithAddress(OPCodes.SUB); break; case "AND": addWithAddress(OPCodes.AND); break; case "OR": addWithAddress(OPCodes.OR); break; case "NOT": case "NOTB": addWithAddress(OPCodes.NOT_B); break; case "STO": addWithoutAddress(OPCodes.STO); break; case "OUT": addWithoutAddress(OPCodes.OUT); break; case "JMP": pos++; switch (instruction[pos]) { case "": } addWithoutAddress(OPCodes.JMP); break; case "HLT": addWithoutAddress(OPCodes.HLT); break; default: throw new SyntaxErrorException("Commmand not found: " + command + " At line: " + lineIndex); } return listToByteArray(list); } private static Byte[] listToByteArray(List list) { return list.toArray(new Byte[list.size()]); } /** * Converts a string representation of a byte value into a byte. * * @param s * A string with the format $base:value * @return The byte value represented by the string */ private Byte parseToByte(String s) { String[] sArr = instruction[pos].replace("$", "").split(":"); byte b = (byte) Integer.parseInt(sArr[1], Integer.parseInt(sArr[0])); return Assemble.bigEndianData ? reverseByte(b) : b; } private byte reverseByte(byte x) { int intSize = 8; byte y = 0; for (int position = intSize - 1; position > 0; position--) { y += ((x & 1) << position); x >>= 1; } return y; } private void addWithAddress(byte OPCode) throws SyntaxErrorException { pos++; byte address; try { address = parseToByte(instruction[pos]); } catch (IndexOutOfBoundsException ex) { throw new SyntaxErrorException("Missing address." + " At line: " + lineIndex); } list.add((byte) ((OPCode << 0x4) | address)); } private void addWithoutAddress(byte OPCode) { list.add((byte) ((OPCode << 0x4))); } }