static public ushort ToByteCode(string instruction) { instruction = instruction.ToUpper(); string[] parts = instruction.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 0) { throw new Exception("An empty string is not valid syntax"); } //check for numbers ushort potentialNumber; if (ushort.TryParse(parts[0], out potentialNumber)) { return(potentialNumber); } else if (parts[0] == "DAT") { return(Mnemonic.ToByteCode(parts[1]));//DAT is followed either by an instruction or a number } else if (parts[0] == "IN") { if (parts.Length > 1) { throw new Exception("Unexpected arguments for IN instruction"); } else { return(901); } } else if (parts[0] == "OUT") { if (parts.Length > 1) { throw new Exception("Unexpected arguments for OUT instruction"); } else { return(902); } } else if (parts[0] == "HLT") { if (parts.Length > 1) { throw new Exception("Unexpected arguments for HLT instruction"); } else { return(0); } } else { if (parts.Length < 2) { throw new Exception("Argument expected for " + parts[0] + " instruction"); } if (parts.Length > 2) { throw new Exception("Unexpected second argument for " + parts[0] + " instruction"); } ushort address; try { address = ushort.Parse(parts[1]); } catch (Exception) { throw new Exception("Argument is invalid"); } if (address > 99) { throw new Exception("Argument is out of bounds!"); } //otherwise we should be ready to parse an instruction with a parameter switch (parts[0]) { case "ADD": return((ushort)(100 + address)); case "SUB": return((ushort)(200 + address)); case "STO": return((ushort)(300 + address)); case "LDA": return((ushort)(500 + address)); case "BR": return((ushort)(600 + address)); case "BRZ": return((ushort)(700 + address)); case "BRP": return((ushort)(800 + address)); default: throw new Exception("Invalid opcode " + parts[0]); } } }