mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-09-08 08:06:56 +00:00
extracted helper methods for DW instruction parsing
This commit is contained in:
parent
ac374f5b52
commit
1c6981c7ed
@ -138,88 +138,149 @@ public class Assembler {
|
|||||||
private static byte[] parseDWInstruction(String line, HashMap<String, Character> labels, int currentLine)
|
private static byte[] parseDWInstruction(String line, HashMap<String, Character> labels, int currentLine)
|
||||||
throws InvalidOperandException {
|
throws InvalidOperandException {
|
||||||
|
|
||||||
|
if (!line.trim().toUpperCase().startsWith("DW")){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream out = new DataOutputStream(bos);
|
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/
|
value = value.trim();
|
||||||
String[] values = line.substring(2).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
|
|
||||||
|
|
||||||
for (String value : values) {
|
String[] valueTokens = value.split("\\s+");
|
||||||
|
|
||||||
value = value.trim();
|
//Handle DUP operator
|
||||||
|
if (isDup(valueTokens)) {
|
||||||
String[] valueTokens = value.split("\\s+");
|
out.write(parseDUPOperator16(valueTokens, labels, currentLine));
|
||||||
|
}
|
||||||
//Handle DUP operator
|
else if (isValidString(value)) {
|
||||||
if (valueTokens.length == 2 && valueTokens[1].toUpperCase().contains("DUP(")) {
|
handleStringOperand(value, out, currentLine);
|
||||||
out.write(parseDUPOperator16(valueTokens, labels, currentLine));
|
}
|
||||||
} else if (value.startsWith("\"") && value.endsWith("\"")) {
|
else if (isValidLabel(value, labels)) {
|
||||||
//Handle string
|
//Handle label
|
||||||
|
out.writeChar(labels.get(value));
|
||||||
//Unescape the string
|
}
|
||||||
String string = value.substring(1, value.length() - 1);
|
else {
|
||||||
|
handleIntegerOperand(value, out, labels, currentLine);
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} catch (IOException e) {
|
||||||
return null;
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return bos.toByteArray();
|
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
|
* Parse the DW instruction (Define word). Handles DUP operator
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user