From d40810fb5be6bfe41a5640b7a0b1f07097d6e788 Mon Sep 17 00:00:00 2001
From: Kraemerd <Dominic_Daniel.Kraemer@Student.Reutlingen-University.de>
Date: Tue, 10 Jan 2023 04:40:27 +0100
Subject: [PATCH] applied final changes to the project

---
 expressions.txt                    | 14 +++---
 src/main/ASTPrinter.java           |  2 +-
 src/main/Application.java          | 11 +++++
 src/main/Evaluator.java            | 73 ++++++++++++++++++++++++++----
 src/main/Parser.java               |  1 +
 src/main/SwingFunctionPlotter.java |  4 +-
 src/test/EvaluatorTest.java        | 52 +++++++++++++++++++--
 7 files changed, 135 insertions(+), 22 deletions(-)

diff --git a/expressions.txt b/expressions.txt
index 7177c93..9f8b2ee 100644
--- a/expressions.txt
+++ b/expressions.txt
@@ -1,8 +1,6 @@
-1+1
-2*4+x
-2*5+2
-2+5*2
-2*(5+2)
-20*(5^2)
-(x^2)+50*x+2
-5*(2-5)+(4+2)+x
\ No newline at end of file
+x
+x^2
+(x^2)-40
+(x*40)-(x*20)
+(2*x)+(0.5*x^2)-1
+1 + (x^2) - (3*x)
\ No newline at end of file
diff --git a/src/main/ASTPrinter.java b/src/main/ASTPrinter.java
index 83ae465..4a16546 100644
--- a/src/main/ASTPrinter.java
+++ b/src/main/ASTPrinter.java
@@ -3,7 +3,7 @@ package main;
 /**
  * <h1>ASTPrinter</h1>
  * The ASTPrinter class creates a String out of an AST(represented through an Expression object)
- * It prints it in a form the Evaluator & SwingFunctionPlotter class can work with it, it isn't primarily designed
+ * It prints it in a form the SwingFunctionPlotter class can work with it, it isn't primarily designed
  * for returning a String that is perfect for human readability (e.g. Pow(x,3) would be printed instead of x^3)
  *
  * @version 1.0
diff --git a/src/main/Application.java b/src/main/Application.java
index 510bf3e..e180d50 100644
--- a/src/main/Application.java
+++ b/src/main/Application.java
@@ -68,6 +68,17 @@ public class Application {
                 ASTPrinter printer = new ASTPrinter();
                 System.out.println("Printing: '" + printer.visit(ast) + "'");
                 stringsForPlotter.add(printer.visit(ast));
+
+                //Prints the Value of the Expression
+                System.out.println("Evaluating:");
+                Evaluator eval = new Evaluator();
+                //Calculates the expression with values from -20 to 20
+                for(index=-20;index<=20; index++) {
+                    System.out.print("[" + index + "]" + eval.visit(ast,index) + " ");
+                    if(index%5==0 && index!=-20) {
+                        System.out.println();
+                    }
+                }
                 System.out.println("\n");
             }
             catch (Exception e) {
diff --git a/src/main/Evaluator.java b/src/main/Evaluator.java
index 9b1fb5e..bf534b9 100644
--- a/src/main/Evaluator.java
+++ b/src/main/Evaluator.java
@@ -2,19 +2,76 @@ package main;
 
 /**
  * <h1>Evaluator</h1>
- *
+ * This class calculates the value of an expression, using the visitor pattern.
+ * It visits every element of a given expression and combines them with the matching
+ * arithmetical operator.
  * @version 1.0
  * @since 09.01.2023
+ * @see #visit(Parser.Expression, int)
  */
-public class Evaluator {
+public class Evaluator implements Visitor<Double> {
 
-    public double calculate(String expression, int variableValue) {
-        int index = 0;
-        while(index<expression.length())
-            if(Character.isLetter(expression.charAt(index))) {
-                expression.replaceAll(expression.substring(index, index+2),"XXX");
+    private double value;
+
+    @Override
+    public Double visit(final Parser.BinaryOperation expression) {
+        double result = expression.leftExpression.accept(this);
+        double rOperand = expression.rightExpression.accept(this);
+        switch (expression.operator) {
+            case "+":
+                result += rOperand;
+                break;
+            case "-":
+                result -= rOperand;
+                break;
+            case "*":
+                result *= rOperand;
+                break;
+            case "/":
+                if (rOperand!=0) {
+                    result /= rOperand;
+                }
+                else {
+                    throw new ArithmeticException("ArithmeticError: division by zero detected");
+                }
+                result /= rOperand;
+                break;
+            case "^":
+                for(double index=1.0; index<rOperand; index++) {
+                    result *= result;
+                }
+                break;
+            default:
+                throw new RuntimeException("SemanticError: unknown operand found in AST: "
+                + expression.operator);
         }
-        return 0.0;
+        return result;
+    }
+
+    @Override
+    public Double visit(final Parser.Variable variable) {
+        return value;
     }
 
+
+    @Override
+    public Double visit(final Parser.Decimal decimal) {
+        return Double.parseDouble(decimal.beforeDot.digits + "." + decimal.afterDot.digits);
+    }
+
+    @Override
+    public Double visit(final Parser.Number number) {
+        return Double.parseDouble(number.digits);
+    }
+
+    /**
+     * This method is used for visiting every element of an expression
+     * @param ast The expression in a form of an AST(Abstract Syntax Tree)
+     * @param value The int value which will be used for the variables
+     * @return The final value of the expression
+     */
+    public double visit(final Parser.Expression ast, int value) {
+        this.value = value;
+        return ast.accept(this);
+    }
 }
diff --git a/src/main/Parser.java b/src/main/Parser.java
index 892bc36..8b44edd 100644
--- a/src/main/Parser.java
+++ b/src/main/Parser.java
@@ -206,6 +206,7 @@ public class Parser {
             capsuled = false;
             index = tokensInBracket+1;
         }
+
         //Checks if the operator of this BinaryOperation is permitted
         parseOperator(ts.get(index).getData());
         List<Lexer.Token> leftList = new LinkedList<>();
diff --git a/src/main/SwingFunctionPlotter.java b/src/main/SwingFunctionPlotter.java
index cd805de..63ec6b1 100644
--- a/src/main/SwingFunctionPlotter.java
+++ b/src/main/SwingFunctionPlotter.java
@@ -50,7 +50,7 @@ public class SwingFunctionPlotter extends JFrame {
 
         //Keeps track of the current shown function
         final int[] index = {0};
-        getContentPane().add(initializeChart(function.get(0),2), BorderLayout.CENTER);
+        getContentPane().add(initializeChart(function.get(0),0), BorderLayout.CENTER);
 
         //KeyListener that listens to every KeyInput of the user
         addKeyListener(new KeyAdapter() {
@@ -97,7 +97,7 @@ public class SwingFunctionPlotter extends JFrame {
         FunctionSeries series1;
         try {
             series1 = new FunctionSeries(function,1000, -20, 20);
-            series1.setTitle("Function: " + function + "[" + index + "]");
+            series1.setTitle("Function " + (index+1) + ": " + function);
             lineChart.getSeries().add(series1);
         }
         catch(Exception e) {
diff --git a/src/test/EvaluatorTest.java b/src/test/EvaluatorTest.java
index 8379942..c88f48a 100644
--- a/src/test/EvaluatorTest.java
+++ b/src/test/EvaluatorTest.java
@@ -1,13 +1,59 @@
 package test;
 
 import main.Evaluator;
-import org.junit.Test;
+import main.Lexer;
+import main.Parser;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class EvaluatorTest {
 
     @Test
-    public void testFirstExpression() {
-        var Evaluator = new Evaluator();
+    public void testWithString1() {
+        String s = "1 + (x^2) - (3*x)";
+        var parser = new Parser();
+        var evaluator = new Evaluator();
+        try {
+            var tokens = Lexer.lex(s);
+            var ast = parser.parse(tokens);
+            var value = evaluator.visit(ast, 5);
+            assertEquals(value,11);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testWithString2() {
+        String s = "(2*x)+(0.5*x^2)-1";
+        var parser = new Parser();
+        var evaluator = new Evaluator();
+        try {
+            var tokens = Lexer.lex(s);
+            var ast = parser.parse(tokens);
+            var value = evaluator.visit(ast, 8);
+            assertEquals(value,47);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
+    @Test
+    public void testWithString3() {
+        String s = "(x^2)-40";
+        var parser = new Parser();
+        var evaluator = new Evaluator();
+        try {
+            var tokens = Lexer.lex(s);
+            var ast = parser.parse(tokens);
+            var value = evaluator.visit(ast, 4);
+            assertEquals(value,-24);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 }
-- 
GitLab