diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 4dfd0e5..6cb9697 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -3,6 +3,7 @@ import interpreter.InterpreterException; import parser.Parser; import parser.SyntaxException; import program.Program; +import printer.ProgramPrinter; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -14,12 +15,20 @@ public class Main { public static void main(String[] args) { if (args.length == 0) { System.err.println("No file given"); - } else if (args.length > 1) { - System.err.println("Too many arguments"); } else { try { String code = readFile(args[0]); - run(code); + if (args.length == 2) { + if ("--print".equals(args[1])) { + print(code); + } else { + System.err.println("Invalid argument " + args[1]); + } + } else if (args.length == 1) { + run(code); + } else { + System.err.println("Too many arguments"); + } } catch (IOException e) { e.printStackTrace(); } @@ -31,6 +40,17 @@ public class Main { return new String(encoded, StandardCharsets.UTF_8); } + private static void print(String code) { + try { + Parser parser = new Parser(code); + Program program = parser.parse(); + ProgramPrinter printer = new ProgramPrinter(); + System.out.println(printer.print(program)); + } catch (SyntaxException se) { + System.err.println(se); + } + } + private static void run(String code) { try { Parser parser = new Parser(code); diff --git a/src/main/java/expression/Addition.java b/src/main/java/expression/Addition.java index 0cefcd4..d0d4237 100644 --- a/src/main/java/expression/Addition.java +++ b/src/main/java/expression/Addition.java @@ -28,12 +28,6 @@ public class Addition extends Expression { this.rightHandSide = rightHandSide; } - /*!- String serialization */ - @Override - public String toString() { - return "(" + leftHandSide + " + " + rightHandSide + ")"; - } - /*!- Generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/main/java/expression/Identifier.java b/src/main/java/expression/Identifier.java index c175498..7b2f85b 100644 --- a/src/main/java/expression/Identifier.java +++ b/src/main/java/expression/Identifier.java @@ -17,12 +17,6 @@ public class Identifier extends Expression { this.name = name; } - /*!- String serialization */ - @Override - public String toString() { - return name; - } - /*!- generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/main/java/expression/Int.java b/src/main/java/expression/Int.java index 942a014..7f38973 100644 --- a/src/main/java/expression/Int.java +++ b/src/main/java/expression/Int.java @@ -22,12 +22,6 @@ public class Int extends Expression { this.value = value; } - /*!- String serialization */ - @Override - public String toString() { - return Integer.toString(value); - } - /*!- generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/main/java/expression/Subtraction.java b/src/main/java/expression/Subtraction.java index 8de951a..4493577 100644 --- a/src/main/java/expression/Subtraction.java +++ b/src/main/java/expression/Subtraction.java @@ -28,12 +28,6 @@ public class Subtraction extends Expression { this.rightHandSide = rightHandSide; } - /*!- String serialization */ - @Override - public String toString() { - return "(" + leftHandSide + " - " + rightHandSide + ")"; - } - /*!- generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/main/java/printer/ExpressionPrinter.java b/src/main/java/printer/ExpressionPrinter.java new file mode 100644 index 0000000..1801a2a --- /dev/null +++ b/src/main/java/printer/ExpressionPrinter.java @@ -0,0 +1,44 @@ +/*!! Printer */ + +/*! +ExpressionPrinter +================= + +The `ExpressionPrinter` is used for string serialization of a given `Expression`. +*/ + +/*!- Header */ +package printer; + +import expression.*; +import interpreter.Visitor; + +/*! +The `ExpressionPrinter` implements the string serialization with the help of the +[Visitor](${basePath}/src/main/java/interpreter/Visitor.java.html). +*/ +public class ExpressionPrinter extends Visitor { + public String visitAddition(Addition addition) { + return visit(addition.leftHandSide) + " + " + visit(addition.rightHandSide); + } + + public String visitIdentifier(Identifier identifier) { + return identifier.name; + } + + public String visitInt(Int integer) { + return Integer.toString(integer.value); + } + + public String visitSubtraction(Subtraction subtraction) { + return visit(subtraction.leftHandSide) + " - " + visit(subtraction.rightHandSide); + } + + /*! + The `print` function takes an `Expression` instance as an argument and returns + the string serialization of the given expression. + */ + public String print(Expression expression) { + return visit(expression); + } +} diff --git a/src/main/java/printer/ProgramPrinter.java b/src/main/java/printer/ProgramPrinter.java new file mode 100644 index 0000000..33a4ad9 --- /dev/null +++ b/src/main/java/printer/ProgramPrinter.java @@ -0,0 +1,46 @@ +/*!! Printer */ + +/*! +ProgramPrinter +============== + +The `ProgramPrinter` is used for string serialization of a given `Program`. +*/ + +/*!- Header */ +package printer; + +import interpreter.Visitor; +import program.*; + +/*! +The `ProgramPrinter` implements the string serialization with the help of the +[Visitor](${basePath}/src/main/java/interpreter/Visitor.java.html). +*/ +public class ProgramPrinter extends Visitor { + private final ExpressionPrinter printer = new ExpressionPrinter(); + + public String visitAssignment(Assignment assignment) { + return printer.print(assignment.identifier) + " := " + printer.print(assignment.expression); + } + + public String visitComposition(Composition composition) { + return visit(composition.first) + " ; " + visit(composition.second); + } + + public String visitConditional(Conditional conditional) { + return "if (" + printer.print(conditional.condition) + ") then { " + visit(conditional.thenCase) + " } else { " + visit(conditional.elseCase) + " }"; + } + + public String visitLoop(Loop loop) { + return "while (" + printer.print(loop.condition) + ") { " + visit(loop.program) + " }"; + } + + /*! + The `print` function takes a `Program` instance as an argument and returns + the string serialization of the given program. + */ + public String print(Program program) { + return visit(program); + } +} diff --git a/src/main/java/program/Assignment.java b/src/main/java/program/Assignment.java index 81d9915..7b22ee0 100644 --- a/src/main/java/program/Assignment.java +++ b/src/main/java/program/Assignment.java @@ -32,12 +32,6 @@ public class Assignment extends Program { this.expression = expression; } - /*!- String serialization */ - @Override - public String toString() { - return identifier + " := " + expression; - } - /*!- generated equals method */ @Override public boolean equals(Object o) { diff --git a/src/main/java/program/Composition.java b/src/main/java/program/Composition.java index fae9d75..4da49dc 100644 --- a/src/main/java/program/Composition.java +++ b/src/main/java/program/Composition.java @@ -19,12 +19,6 @@ public class Composition extends Program { this.second = second; } - /*!- String serialization */ - @Override - public String toString() { - return first + " ; " + second; - } - /*!- generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/main/java/program/Conditional.java b/src/main/java/program/Conditional.java index edfd477..5ea732e 100644 --- a/src/main/java/program/Conditional.java +++ b/src/main/java/program/Conditional.java @@ -36,10 +36,4 @@ public class Conditional extends Program { return elseCase.equals(that.elseCase); } - - /*!- String serialization */ - @Override - public String toString() { - return "if (" + condition + ") then { " + thenCase + " } else { " + elseCase + " }"; - } } diff --git a/src/main/java/program/Loop.java b/src/main/java/program/Loop.java index e3ae27d..2826a7a 100644 --- a/src/main/java/program/Loop.java +++ b/src/main/java/program/Loop.java @@ -21,12 +21,6 @@ public class Loop extends Program { this.program = program; } - /*!- String serialization */ - @Override - public String toString() { - return "while (" + condition + ") { " + program + " }"; - } - /*!- generated equals implementation */ @Override public boolean equals(Object o) { diff --git a/src/test/java/printer/ExpressionPrinterTest.java b/src/test/java/printer/ExpressionPrinterTest.java new file mode 100644 index 0000000..b457766 --- /dev/null +++ b/src/test/java/printer/ExpressionPrinterTest.java @@ -0,0 +1,43 @@ +package printer; + +import expression.*; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ExpressionPrinterTest { + final String identifierCode = "a"; + final Identifier identifier = new Identifier(identifierCode); + + final String integerCode = "42"; + final Int integer = new Int(42); + + final String additionCode = "a + 42"; + final Addition addition = new Addition(new Identifier("a"), new Int(42)); + + final String subtractionCode = "1 - a"; + final Subtraction subtraction = new Subtraction(new Int(1), new Identifier("a")); + + final ExpressionPrinter printer = new ExpressionPrinter(); + + @Test + public void testVisitAddition() { + assertEquals(additionCode, printer.print(addition)); + } + + @Test + public void testVisitIdentifier() { + assertEquals(identifierCode, printer.print(identifier)); + } + + @Test + public void testVisitInt() { + assertEquals(integerCode, printer.print(integer)); + } + + @Test + public void testVisitSubtraction() { + assertEquals(subtractionCode, printer.print(subtraction)); + } + +} \ No newline at end of file diff --git a/src/test/java/printer/ProgramPrinterTest.java b/src/test/java/printer/ProgramPrinterTest.java new file mode 100644 index 0000000..866c6a8 --- /dev/null +++ b/src/test/java/printer/ProgramPrinterTest.java @@ -0,0 +1,55 @@ +package printer; + +import expression.Addition; +import expression.Identifier; +import expression.Int; +import expression.Subtraction; +import org.junit.Test; +import program.*; + +import static org.junit.Assert.*; + +public class ProgramPrinterTest { + final String loopCode = "while (a) { r := r + b ; a := a - 1 }"; + final Loop loop = new Loop(new Identifier("a"), new Composition(new Assignment(new Identifier("r"), new Addition(new Identifier("r"), new Identifier("b"))), new Assignment(new Identifier("a"), new Subtraction(new Identifier("a"), new Int(1))))); + + final String assignmentCode = "a := 2"; + final Assignment assignment = new Assignment(new Identifier("a"), new Int(2)); + + final String compositionCode = assignmentCode + " ; b := bar"; + final Composition composition = new Composition(assignment, new Assignment(new Identifier("b"), new Identifier("bar"))); + + final String conditionalCode = "if (foo - bar) then { x := 5 } else { x := x }"; + final Conditional conditional = new Conditional(new Subtraction(new Identifier("foo"), new Identifier("bar")), new Assignment(new Identifier("x"), new Int(5)), new Assignment(new Identifier("x"), new Identifier("x"))); + + final String programCode = compositionCode + " ; " + loopCode + " ; " + conditionalCode; + final Program program = new Composition(new Composition(composition, loop), conditional); + + final ProgramPrinter printer = new ProgramPrinter(); + + @Test + public void testVisitAssignment() { + assertEquals(assignmentCode, printer.print(assignment)); + } + + @Test + public void testVisitComposition() { + assertEquals(compositionCode, printer.print(composition)); + } + + @Test + public void testVisitConditional() { + assertEquals(conditionalCode, printer.print(conditional)); + } + + @Test + public void testVisitLoop() { + assertEquals(loopCode, printer.print(loop)); + } + + @Test + public void testVisitProgram() { + assertEquals(programCode, printer.print(program)); + } + +} \ No newline at end of file