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