From 1c6981c7eda05593ad3ba7177005869088ec45dd Mon Sep 17 00:00:00 2001 From: sourav Date: Mon, 25 Aug 2025 11:03:02 +0530 Subject: [PATCH] extracted helper methods for DW instruction parsing --- .../simon987/server/assembly/Assembler.java | 191 ++++++++++++------ 1 file changed, 126 insertions(+), 65 deletions(-) diff --git a/Server/src/main/java/net/simon987/server/assembly/Assembler.java b/Server/src/main/java/net/simon987/server/assembly/Assembler.java index c5088f6..58de2ff 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -138,88 +138,149 @@ public class Assembler { private static byte[] parseDWInstruction(String line, HashMap 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); + value = value.trim(); - for (String value : values) { + String[] valueTokens = value.split("\\s+"); - 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); - - } - } - } - } + //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); } - - } catch (IOException e) { - e.printStackTrace(); } - } 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 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 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 *