Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 128 additions & 67 deletions Server/src/main/java/net/simon987/server/assembly/Assembler.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,88 +138,149 @@ private static boolean isLineEmpty(String line) {
private static byte[] parseDWInstruction(String line, HashMap<String, Character> labels, int currentLine)
throws InvalidOperandException {

if (!line.trim().toUpperCase().startsWith("DW")){
return null;
}

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos);

//System.out.println(line);
try {

if (line.length() >= 2 && line.substring(0, 2).toUpperCase().equals("DW")) {
//Special thanks to https://stackoverflow.com/questions/1757065/
String[] values = line.substring(2).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);

try {
for (String value : values) {

//Special thanks to https://stackoverflow.com/questions/1757065/
String[] values = line.substring(2).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);

for (String value : values) {

value = value.trim();

String[] valueTokens = value.split("\\s+");

//Handle DUP operator
if (valueTokens.length == 2 && valueTokens[1].toUpperCase().contains("DUP(")) {
out.write(parseDUPOperator16(valueTokens, labels, currentLine));
} else if (value.startsWith("\"") && value.endsWith("\"")) {
//Handle string

//Unescape the string
String string = value.substring(1, value.length() - 1);

try {
string = StringEscapeUtils.unescapeJava(string);
} catch (IllegalArgumentException e) {
throw new InvalidOperandException(
"Invalid string operand \"" + string + "\": " + e.getMessage(),
currentLine);
}

out.write(string.getBytes(StandardCharsets.UTF_16BE));
} else if (labels != null && labels.containsKey(value)) {
//Handle label
out.writeChar(labels.get(value));

} else {
//Handle integer value
try {
out.writeChar(Integer.decode(value));

} catch (NumberFormatException e) {
//Handle assumed label
if (labels == null) {

// Write placeholder word
out.writeChar(0);

} else {

//Integer.decode failed, try binary
if (value.startsWith("0b")) {
try {
out.writeChar(Integer.parseInt(value.substring(2), 2));
} catch (NumberFormatException e2) {
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);
}
} else {
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);

}
}
}
}
}
value = value.trim();

String[] valueTokens = value.split("\\s+");

} catch (IOException e) {
e.printStackTrace();
//Handle DUP operator
if (isDup(valueTokens)) {
out.write(parseDUPOperator16(valueTokens, labels, currentLine));
}
else if (isValidString(value)) {
handleStringOperand(value, out, currentLine);
}
else if (isValidLabel(value, labels)) {
//Handle label
out.writeChar(labels.get(value));
}
else {
handleIntegerOperand(value, out, labels, currentLine);
}
}

} else {
return null;
} catch (IOException e) {
e.printStackTrace();
}

return bos.toByteArray();

}


/**
* Checks if the given value tokens represent a DUP operator.
*
* @param valueTokens Tokens from the operand string
* @return true if DUP(...) syntax is detected, false otherwise
*/
private static boolean isDup(String[] valueTokens){
return valueTokens.length == 2 && valueTokens[1].toUpperCase().contains("DUP(");
}


/**
* Checks if the given value is a valid string operand.
* A valid string starts and ends with quotation marks.
*
* @param value The operand string
* @return true if the operand is a quoted string, false otherwise
*/
private static boolean isValidString(String value){
return value.startsWith("\"") && value.endsWith("\"");
}

/**
* Checks if the given value matches a known label.
*
* @param value The operand string
* @param labels Map of label definitions (may be null if not available)
* @return true if the operand exists in the labels map, false otherwise
*/
private static boolean isValidLabel(String value, HashMap<String, Character> labels){
return labels != null && labels.containsKey(value);
}

/**
* Handles a string operand by unescaping and writing its UTF-16BE bytes
* to the output stream.
*
* @param value The quoted string operand
* @param out Output stream to write to
* @param currentLine Current line number (for error reporting)
* @throws IllegalArgumentException if the string contains invalid escape sequences
*/
private static void handleStringOperand(String value, DataOutputStream out, int currentLine) throws IllegalArgumentException, InvalidOperandException, IOException{

//Unescape the string
String string = value.substring(1, value.length() - 1);

try {
string = StringEscapeUtils.unescapeJava(string);
} catch (IllegalArgumentException e) {
throw new InvalidOperandException(
"Invalid string operand \"" + string + "\": " + e.getMessage(),
currentLine);
}

out.write(string.getBytes(StandardCharsets.UTF_16BE));

}

/**
* Handles integer operands, including decimal, hexadecimal, binary,
* placeholders for unresolved labels, and throws an error on invalid operands.
*
* @param value The operand string
* @param out Output stream to write to
* @param labels Map of label definitions (may be null if not available)
* @param currentLine Current line number (for error reporting)
* @throws InvalidOperandException if the operand cannot be parsed as a valid integer
*/
private static void handleIntegerOperand(String value, DataOutputStream out, HashMap<String, Character> labels, int currentLine) throws InvalidOperandException, IOException {

//Handle integer value
try {
out.writeChar(Integer.decode(value));

} catch (NumberFormatException e) {
//Handle assumed label

if (labels == null) {
out.writeChar(0);// Write placeholder word
return;
}

//Integer.decode failed, try binary
if (value.startsWith("0b")) {
try {
out.writeChar(Integer.parseInt(value.substring(2), 2));
} catch (NumberFormatException e2) {
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);
}
return;
}

throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);


}
}


/**
* Parse the DW instruction (Define word). Handles DUP operator
*
Expand Down