| @@ -3,6 +3,7 @@ import interpreter.InterpreterException; | |||||
| import parser.Parser; | import parser.Parser; | ||||
| import parser.SyntaxException; | import parser.SyntaxException; | ||||
| import program.Program; | import program.Program; | ||||
| import printer.ProgramPrinter; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
| @@ -14,12 +15,20 @@ public class Main { | |||||
| public static void main(String[] args) { | public static void main(String[] args) { | ||||
| if (args.length == 0) { | if (args.length == 0) { | ||||
| System.err.println("No file given"); | System.err.println("No file given"); | ||||
| } else if (args.length > 1) { | |||||
| System.err.println("Too many arguments"); | |||||
| } else { | } else { | ||||
| try { | try { | ||||
| String code = readFile(args[0]); | 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) { | } catch (IOException e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| @@ -31,6 +40,17 @@ public class Main { | |||||
| return new String(encoded, StandardCharsets.UTF_8); | 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) { | private static void run(String code) { | ||||
| try { | try { | ||||
| Parser parser = new Parser(code); | Parser parser = new Parser(code); | ||||
| @@ -28,12 +28,6 @@ public class Addition extends Expression { | |||||
| this.rightHandSide = rightHandSide; | this.rightHandSide = rightHandSide; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return "(" + leftHandSide + " + " + rightHandSide + ")"; | |||||
| } | |||||
| /*!- Generated equals implementation */ | /*!- Generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -17,12 +17,6 @@ public class Identifier extends Expression { | |||||
| this.name = name; | this.name = name; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return name; | |||||
| } | |||||
| /*!- generated equals implementation */ | /*!- generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -22,12 +22,6 @@ public class Int extends Expression { | |||||
| this.value = value; | this.value = value; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return Integer.toString(value); | |||||
| } | |||||
| /*!- generated equals implementation */ | /*!- generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -28,12 +28,6 @@ public class Subtraction extends Expression { | |||||
| this.rightHandSide = rightHandSide; | this.rightHandSide = rightHandSide; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return "(" + leftHandSide + " - " + rightHandSide + ")"; | |||||
| } | |||||
| /*!- generated equals implementation */ | /*!- generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -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<String> { | |||||
| 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); | |||||
| } | |||||
| } | |||||
| @@ -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<String> { | |||||
| 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); | |||||
| } | |||||
| } | |||||
| @@ -32,12 +32,6 @@ public class Assignment extends Program { | |||||
| this.expression = expression; | this.expression = expression; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return identifier + " := " + expression; | |||||
| } | |||||
| /*!- generated equals method */ | /*!- generated equals method */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -19,12 +19,6 @@ public class Composition extends Program { | |||||
| this.second = second; | this.second = second; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return first + " ; " + second; | |||||
| } | |||||
| /*!- generated equals implementation */ | /*!- generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -36,10 +36,4 @@ public class Conditional extends Program { | |||||
| return elseCase.equals(that.elseCase); | return elseCase.equals(that.elseCase); | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return "if (" + condition + ") then { " + thenCase + " } else { " + elseCase + " }"; | |||||
| } | |||||
| } | } | ||||
| @@ -21,12 +21,6 @@ public class Loop extends Program { | |||||
| this.program = program; | this.program = program; | ||||
| } | } | ||||
| /*!- String serialization */ | |||||
| @Override | |||||
| public String toString() { | |||||
| return "while (" + condition + ") { " + program + " }"; | |||||
| } | |||||
| /*!- generated equals implementation */ | /*!- generated equals implementation */ | ||||
| @Override | @Override | ||||
| public boolean equals(Object o) { | public boolean equals(Object o) { | ||||
| @@ -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)); | |||||
| } | |||||
| } | |||||
| @@ -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)); | |||||
| } | |||||
| } | |||||