From a97704def85a55f2b482c724abc121df718a5f5e Mon Sep 17 00:00:00 2001 From: Nicola Pfister Date: Thu, 6 Oct 2016 16:32:59 +0200 Subject: [PATCH] adapted tests --- src/JohnnyScript.java | 113 ++++++++++++++++++++++--------------- test/JohnnyScriptTest.java | 41 +++++--------- test/RamCodeTest.java | 40 +++++++++---- 3 files changed, 113 insertions(+), 81 deletions(-) diff --git a/src/JohnnyScript.java b/src/JohnnyScript.java index 8c030b0..ad326b7 100644 --- a/src/JohnnyScript.java +++ b/src/JohnnyScript.java @@ -14,60 +14,86 @@ public class JohnnyScript { private static final String OUTPUT_EXTENSION = ".ram"; private static final String LINE_COMMENT_DELIMITER = "//"; + private static final String JUMP_POINT_DELIMITER = ":"; + private static final String VARIABLE_DELIMITER = "#"; public static void main(String[] args) throws IOException { Path source = getFilename(args); List code = Files.readAllLines(source); - writeOutFile(source.getFileName().toString(), compileCode(code)); + try { + writeOutFile(source.getFileName().toString(), compileCode(code)); + } catch (Exception e) { + throw new CompilerHaltException("Compiler halted due to erroneous code!\n", e); + } } /** - * Generates the ram code consisting from 1000 lines of compiled JohnnyScript and "000" for empty lines + * Generates ram code using RamCode object * - * @param sourceLines {@link java.util.List} of String objects containing lines of JohnnyScript code + * @param sourceLines {@link List} of String objects containing lines of JohnnyScript code * @return compiled numeric code for .ram file */ - private static List compileCode(List sourceLines) { - List compiled = new ArrayList<>(); - - for (int i = 0; i <= 999; i++) { - if (i < sourceLines.size()) { - try { - String compiledLine = compile(sourceLines.get(i)); - if (compiledLine != null) { - compiled.add(compiledLine); - } else { - sourceLines.remove(i); // Remove comment line from source - i--; // Reduce index to continue at next line without skipping - } - } catch (InvalidScriptException e) { - throw new CompilerHaltException("Invalid code at line " + i, e); + private static List compileCode(List sourceLines) throws InvalidScriptException, DuplicateVariableException, VariableNotInitializedException, DuplicateJumpPointException { + RamCode code = new RamCode(); + int lineNumber = 0; + for (String line:sourceLines) { + line = decomment(line); + if (line == null) { + continue; + } + if (line.contains(VARIABLE_DELIMITER)) { + String[] parts = line.split(VARIABLE_DELIMITER + "| "); + if (parts[0].length() == 0) { + // variable declaration (# at start of line) + if(parts.length != 3) { + throw new InvalidScriptException("Syntax error at line " + lineNumber + ": " + line + " (variable declaration: #varname [int])"); + } else code.addVar(parts[1],Integer.valueOf(parts[2])); + } else { + // reference to variable + if(parts.length != 3) { + throw new InvalidScriptException("Syntax error at line " + lineNumber + ": " + line + " (variable declaration: #varname [int])"); + } else code.addCodeWithVar(encode(parts[0], false),parts[2]); } - } else compiled.add("000"); + } else { + if (line.contains(JUMP_POINT_DELIMITER)) { + String jpName = line.replace(":", ""); + code.addJumpPoint(jpName); + } else { + String[] parts = line.split(" "); + if(Codes.valueOf(parts[0].toUpperCase()).codeOrdinal == Codes.JMP.codeOrdinal) { + code.addJump(parts[1]); + } else code.addCode(encode(line, true)); + } + + } + lineNumber++; + } - return compiled; + try { + return code.getCode(); + } catch (InvalidJumpsException e) { + throw new CompilerHaltException("Compiler halted due to erroneous code!\n", e); + } } /** - * Handles compiling of specific lines depending on the type of code. + * Removes comments from line and trims excess whitespace * * @param line Line of JohnnyScript code * @return compiled line of .ram code or null if line is a comment - * @throws InvalidScriptException on invalid JohnnyScript code */ - private static String compile(String line) throws InvalidScriptException { + private static String decomment(String line) { if (line.contains(LINE_COMMENT_DELIMITER)) { /* Separate code from comment */ int commentStart = line.indexOf(LINE_COMMENT_DELIMITER); String nonComment = line.substring(0, commentStart); if (!nonComment.equals("")) - return encode(nonComment); + return nonComment.trim(); else return null; - } else - return encode(line); + } else return line.trim(); } /** @@ -77,17 +103,19 @@ private static String compile(String line) throws InvalidScriptException { * @return numeric line for instruction * @throws InvalidScriptException on invalid JohnnyScript code */ - private static String encode(String line) throws InvalidScriptException { - String[] parts = line.trim().split(" "); - if (parts.length > 2) throw new InvalidScriptException("InvalidJohnnyScript (too many parts): " + line); + private static String encode(String line, boolean appendLow) throws InvalidScriptException { + String[] parts = line.split(" "); + if (parts.length > 2) throw new InvalidScriptException("Syntax error (too many parts): " + line); if (parts.length == 1) { - return String.format("%03d", Integer.parseInt(parts[0])); + String output = Codes.valueOf(parts[0].toUpperCase()).getCode(); + if (appendLow) output = output + "000"; + return output; + } else { + String code = parts[0].toUpperCase(); + String hi = Codes.valueOf(code).getCode(); + String lo = String.format("%03d", Integer.parseInt(parts[1])); + return hi + lo; } - // else there are two parts - String code = parts[0].toUpperCase(); - String lo = String.format("%03d", Integer.parseInt(parts[1])); - String hi = Codes.valueOf(code).getCode(); - return hi + lo; } @@ -160,7 +188,6 @@ public String getCode() { class RamCode { private static final int MAX_LINES = 999; - private static final String JUMP_POINT_DELIMITER = ":"; private static int writeIndex; @@ -191,16 +218,12 @@ void addVar(String name, int value) throws DuplicateVariableException { } } - void addCodeWithVar(String input) throws VariableNotInitializedException { - assert input.contains("#"); - String[] parts = input.split("#"); - assert parts.length == 2; - String var = parts[1]; + void addCodeWithVar(String commandOrdinal, String var) throws VariableNotInitializedException { if (!variables.containsKey(var)) { throw new VariableNotInitializedException("Variable has not been initialized: " + var); } else { int line = varLoc.get(var); - code.add(parts[0].trim() + String.format("%03d", line)); + code.add(commandOrdinal + String.format("%03d", line)); } } @@ -232,7 +255,7 @@ private List initializeZeros(List code) { return code; } - List getCode() throws InvalidJumpsException { + List getCode() throws InvalidJumpsException { List output = new ArrayList<>(); initializeZeros(output); @@ -248,7 +271,7 @@ List getCode() throws InvalidJumpsException { for (String loc : code ) { - output.add(writeIndex, loc); + output.set(writeIndex, loc); writeIndex++; } @@ -261,7 +284,7 @@ List getCode() throws InvalidJumpsException { for (int line:jumpList) { line = 1 + variables.size() + line; assert output.get(line).equals(jpName + ":"); - output.set(line, JohnnyScript.Codes.JMP.codeOrdinal + String.format("%03d", line)); + output.set(line, JohnnyScript.Codes.JMP.codeOrdinal + String.format("%03d", 1+variables.size()+jumpPoints.get(jpName))); } } }); diff --git a/test/JohnnyScriptTest.java b/test/JohnnyScriptTest.java index c4881c5..13172af 100644 --- a/test/JohnnyScriptTest.java +++ b/test/JohnnyScriptTest.java @@ -80,16 +80,13 @@ public void commentLine() throws Exception { List outLines = Files.readAllLines(outputPath); testCode = new ArrayList<>(); + testCode.add("5001"); testCode.add("2000"); testCode.add("2000"); - assertEquals(1000, outLines.size()); for (int i = 0; i < testCode.size(); i++) { assertEquals("Line " + i, testCode.get(i),outLines.get(i)); } - - testZeroLines(testCode.size(), outLines); - } @Test @@ -107,17 +104,25 @@ public void commentInline() throws Exception { List outLines = Files.readAllLines(outputPath); testCode = new ArrayList<>(); + testCode.add("5001"); testCode.add("2000"); testCode.add("2001"); testCode.add("2000"); - assertEquals(1000, outLines.size()); for (int i = 0; i < testCode.size(); i++) { assertEquals("Line " + i, testCode.get(i),outLines.get(i)); } - testZeroLines(testCode.size(), outLines); + } + @Test + public void testMaxLines() throws Exception { + List testCode = new ArrayList<>(); + Files.write(inputPath, testCode); + + JohnnyScript.main(new String[]{validFile}); + List outLines = Files.readAllLines(outputPath); + assertEquals(1000, outLines.size()); } @Test @@ -137,10 +142,6 @@ public void testSave() throws Exception { exhTest("SAVE"); } @Test - public void testJmp() throws Exception { - exhTest("JMP"); - } - @Test public void testTst() throws Exception { exhTest("TST"); } @@ -161,23 +162,12 @@ public void testHlt() throws Exception { exhTest("HLT"); } - /** - * Checks if lines after code are correctly filled with "000" - * @param i start index of "000" lines - * @param testCode code to test - */ - private void testZeroLines(int i, List testCode) { - for (;i < 1000; i++) { - assertEquals("000",testCode.get(i)); - } - } - /** * Tests conversion of all possible addresses for a code * @param code Code to test */ private void exhTest(String code) throws Exception { - for (int i = 0; i < 1000; i++) { + for (int i = 0; i < 999; i++) { List testCode = new ArrayList<>(); testCode.add(code + " " + i); Files.write(inputPath, testCode); @@ -189,12 +179,11 @@ private void exhTest(String code) throws Exception { testCode = new ArrayList<>(); testCode.add(JohnnyScript.Codes.valueOf(code).getCode()+ String.format("%03d",i)); - assertEquals(1000, outLines.size()); - for (int j = 0; j < testCode.size(); j++) { + assertEquals("Line " + 0, "5001",outLines.get(0)); + + for (int j = 1; j < testCode.size(); j++) { assertEquals("Line " + j, testCode.get(j),outLines.get(j)); } - - testZeroLines(testCode.size(),outLines); } } } \ No newline at end of file diff --git a/test/RamCodeTest.java b/test/RamCodeTest.java index c320934..16a6a70 100644 --- a/test/RamCodeTest.java +++ b/test/RamCodeTest.java @@ -53,7 +53,7 @@ public void testAddVar() throws Exception { @Test(expected = VariableNotInitializedException.class) public void testAddVarRefWithoutInit() throws Exception { RamCode code = new RamCode(); - code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal+" #tst"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "tst"); } @Test(expected = DuplicateVariableException.class) @@ -67,7 +67,7 @@ public void testAddDuplicateVar() throws Exception { public void testAddVarRef() throws Exception { RamCode code = new RamCode(); code.addVar("tst",5); - code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal+" #tst"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "tst"); List codeList = code.getCode(); @@ -105,7 +105,7 @@ public void testAddJumpBeforeJumpPoint() throws Exception { List codeList = code.getCode(); assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "001",codeList.get(0)); - assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "001",codeList.get(1)); + assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "002",codeList.get(1)); for (int i = 2; i < 1000; i++) { assertEquals("000",codeList.get(i)); @@ -131,16 +131,36 @@ public void testInvalidJump() throws Exception { public void testProgram() throws Exception { RamCode code = new RamCode(); code.addVar("z3", 0); - code.addCodeWithVar(JohnnyScript.Codes.NULL.codeOrdinal + "#z3"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.NULL.codeOrdinal),"z3"); code.addJumpPoint("start"); - code.addCodeWithVar(JohnnyScript.Codes.TAKE.codeOrdinal + "#z3"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.TAKE.codeOrdinal), "z3"); code.addVar("z1", 5); - code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal + "#z1"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "z1"); code.addVar("z2", 3); - code.addCodeWithVar(JohnnyScript.Codes.SAVE.codeOrdinal + "#z2"); - code.addCodeWithVar(JohnnyScript.Codes.DEC.codeOrdinal + "#z1"); - code.addCodeWithVar(JohnnyScript.Codes.TST.codeOrdinal + "#z1"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.SAVE.codeOrdinal), "z2"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.DEC.codeOrdinal), "z1"); + code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.TST.codeOrdinal), "z1"); code.addJump("start"); - code.addCode(JohnnyScript.Codes.HLT.codeOrdinal + "0"); + code.addCode(JohnnyScript.Codes.HLT.codeOrdinal + "000"); + + List codeList = code.getCode(); + + assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "004",codeList.get(0)); //jump to first program line + assertEquals("000",codeList.get(1)); //z3 + assertEquals("005",codeList.get(2)); //z1 + assertEquals("003",codeList.get(3)); //z2 + assertEquals(JohnnyScript.Codes.NULL.codeOrdinal + "001",codeList.get(4)); + assertEquals(JohnnyScript.Codes.TAKE.codeOrdinal + "001",codeList.get(5)); // jump point start set to here + assertEquals(JohnnyScript.Codes.ADD.codeOrdinal + "002",codeList.get(6)); + assertEquals(JohnnyScript.Codes.SAVE.codeOrdinal + "003",codeList.get(7)); + assertEquals(JohnnyScript.Codes.DEC.codeOrdinal + "002",codeList.get(8)); + assertEquals(JohnnyScript.Codes.TST.codeOrdinal + "002",codeList.get(9)); + assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "005",codeList.get(10)); + assertEquals(JohnnyScript.Codes.HLT.codeOrdinal + "000",codeList.get(11)); + + + for (int i = 12; i < 1000; i++) { + assertEquals("000",codeList.get(i)); + } } } \ No newline at end of file