From 173e3dee3690df4a562cea4255b9721206caa9b9 Mon Sep 17 00:00:00 2001 From: Kraemerd <Dominic_Daniel.Kraemer@Student.Reutlingen-University.de> Date: Mon, 9 Jan 2023 16:17:49 +0100 Subject: [PATCH] advanced the project structure & implemented the lexer test class --- expressions.txt | 2 +- src/Exceptions/LexerException.java | 7 +++ src/{ => Exceptions}/ParserException.java | 2 + src/{ => main}/ASTPrinter.java | 2 + src/{ => main}/Application.java | 53 +++++++++++++------- src/{ => main}/Evaluator.java | 3 ++ src/{ => main}/Lexer.java | 16 ++++-- src/{ => main}/Parser.java | 8 +++ src/{ => main}/SwingFunctionPlotter.java | 2 + src/{ => main}/Visitor.java | 2 + src/test/LexerTest.java | 59 +++++++++++++++++++++++ src/test/ParserTest.java | 4 ++ 12 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 src/Exceptions/LexerException.java rename src/{ => Exceptions}/ParserException.java (85%) rename src/{ => main}/ASTPrinter.java (98%) rename src/{ => main}/Application.java (51%) rename src/{ => main}/Evaluator.java (97%) rename src/{ => main}/Lexer.java (90%) rename src/{ => main}/Parser.java (98%) rename src/{ => main}/SwingFunctionPlotter.java (98%) rename src/{ => main}/Visitor.java (94%) create mode 100644 src/test/LexerTest.java create mode 100644 src/test/ParserTest.java diff --git a/expressions.txt b/expressions.txt index 956089d..74f9b71 100644 --- a/expressions.txt +++ b/expressions.txt @@ -1,2 +1,2 @@ 1+(x^2)-(3*x) -2*x+0.5*(x^2)-1 \ No newline at end of file +2*x+0.5*(x^2+4)-1 \ No newline at end of file diff --git a/src/Exceptions/LexerException.java b/src/Exceptions/LexerException.java new file mode 100644 index 0000000..28ac422 --- /dev/null +++ b/src/Exceptions/LexerException.java @@ -0,0 +1,7 @@ +package Exceptions; + +public class LexerException extends Exception { + public LexerException(String message) { + super(message); + } +} diff --git a/src/ParserException.java b/src/Exceptions/ParserException.java similarity index 85% rename from src/ParserException.java rename to src/Exceptions/ParserException.java index ef36000..d3e5195 100644 --- a/src/ParserException.java +++ b/src/Exceptions/ParserException.java @@ -1,3 +1,5 @@ +package Exceptions; + public class ParserException extends Exception{ public ParserException(String message) { super(message); diff --git a/src/ASTPrinter.java b/src/main/ASTPrinter.java similarity index 98% rename from src/ASTPrinter.java rename to src/main/ASTPrinter.java index 8983653..10669f2 100644 --- a/src/ASTPrinter.java +++ b/src/main/ASTPrinter.java @@ -1,3 +1,5 @@ +package main; + public class ASTPrinter implements Visitor<String>{ @Override public String visit(final Parser.BinaryOperation binaryOP) { diff --git a/src/Application.java b/src/main/Application.java similarity index 51% rename from src/Application.java rename to src/main/Application.java index b25cd9f..f65d712 100644 --- a/src/Application.java +++ b/src/main/Application.java @@ -1,4 +1,10 @@ +package main; + +import Exceptions.LexerException; +import Exceptions.ParserException; + import java.io.BufferedReader; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.LinkedList; @@ -6,34 +12,47 @@ import java.util.List; public class Application { public static void main(String[] args) { + //A list that will contain a String for each line of the "expressions.txt" file List<String> expressions = new LinkedList<>(); - //Reads the file "expressions.txt" and adds its values to a list + //Reads the file "expressions.txt" and adds its values to the list expressions BufferedReader reader; - String dataPath = "expressions.txt"; + String datapath = "expressions.txt"; try { System.out.println("Reading the file...\n"); - reader = new BufferedReader(new FileReader(dataPath)); - String line = reader.readLine(); - while(line != null) { - expressions.add(line); - line = reader.readLine(); + reader = new BufferedReader(new FileReader(datapath)); + String currentLine = reader.readLine(); + while(currentLine !=null) { + expressions.add(currentLine); + currentLine = reader.readLine(); } reader.close(); } - catch (IOException e ) { + catch(IOException e) { e.printStackTrace(); } + //Iterate through every String + for (String expression: expressions) { + System.out.println("Expression: " + expression); + //Usage of the lexer, parser & evaluator + try { + //Create a list of tokens with the lexer + List<Lexer.Token> tokens = Lexer.lex(expression); + System.out.println("Lexer created tokens:"); + //prints out each token to the console + for(Lexer.Token token: tokens) { + System.out.println(token.toString()); + } + } + catch (Exception e) { + e.printStackTrace(); + } + + } + + /* //Iterates through every String and parses them into multiple tokens for (String value: expressions) { - System.out.println(value); - //creates a list of tokens out of the String - List<Lexer.Token> tokens = Lexer.lex(value); - - //prints each token out (with .toString()) - for(Lexer.Token singleToken: tokens) { - System.out.println(singleToken.toString()); - } Parser parser = new Parser(); try { Parser.Expression exp = parser.parse(tokens); @@ -48,6 +67,6 @@ public class Application { System.out.println(e.getMessage()); } System.out.println(); - } + }*/ } } diff --git a/src/Evaluator.java b/src/main/Evaluator.java similarity index 97% rename from src/Evaluator.java rename to src/main/Evaluator.java index b9979c7..7f51f3c 100644 --- a/src/Evaluator.java +++ b/src/main/Evaluator.java @@ -1,3 +1,5 @@ +package main; + public class Evaluator implements Visitor<Double>{ @Override @@ -16,6 +18,7 @@ public class Evaluator implements Visitor<Double>{ result -= rOperand; break; case '*': + rOperand *= rOperand; result *= rOperand; break; case '/': diff --git a/src/Lexer.java b/src/main/Lexer.java similarity index 90% rename from src/Lexer.java rename to src/main/Lexer.java index c380695..d84a782 100644 --- a/src/Lexer.java +++ b/src/main/Lexer.java @@ -1,3 +1,7 @@ +package main; + +import Exceptions.LexerException; + import java.util.LinkedList; import java.util.List; @@ -9,7 +13,7 @@ public class Lexer { } //tokens with a TokenType that represents their type and a String with the actual data - //has for both values a getter method and overrides toString with it's fitting values + //has for both values a getter method and overrides toString with its fitting values public static class Token { protected TokenType type; protected String data; @@ -33,15 +37,19 @@ public class Lexer { } //creates a list of tokens from a given String - public static List<Token> lex(String input) { + public static List<Token> lex(String input) throws Exception{ + if(input.isEmpty()) { + throw new LexerException("SyntaxError: lexer received empty String"); + } + //the list that will be returned at the end List<Token> result = new LinkedList<Token>(); //for-loop that iterates through each character of the String for(int index=0; index < input.length();) { char current = input.charAt(index); - //checks if a character is a digit, then creates a token with one or multiple numbers - //with TokenType=NUMBER + //checks if a character is a digit, then creates a token with one or multiple + //numbers with TokenType=NUMBER if(Character.isDigit(current)) { int endIndex = index; if(endIndex<input.length()) { diff --git a/src/Parser.java b/src/main/Parser.java similarity index 98% rename from src/Parser.java rename to src/main/Parser.java index 527d628..ca46fc9 100644 --- a/src/Parser.java +++ b/src/main/Parser.java @@ -1,3 +1,7 @@ +package main; + +import Exceptions.ParserException; + import java.util.LinkedList; import java.util.List; @@ -21,6 +25,10 @@ public class Parser { public <T> T accept(Visitor<T> visitor) { return visitor.visit(this); } + + public <T> T accept(Visitor<T> vistor, String operator) { + return vistor.visit(this); + } } public class Variable extends Expression { diff --git a/src/SwingFunctionPlotter.java b/src/main/SwingFunctionPlotter.java similarity index 98% rename from src/SwingFunctionPlotter.java rename to src/main/SwingFunctionPlotter.java index 110dc61..d433aee 100644 --- a/src/SwingFunctionPlotter.java +++ b/src/main/SwingFunctionPlotter.java @@ -1,3 +1,5 @@ +package main; + import com.mindfusion.charting.FunctionSeries; import com.mindfusion.charting.swing.LineChart; diff --git a/src/Visitor.java b/src/main/Visitor.java similarity index 94% rename from src/Visitor.java rename to src/main/Visitor.java index 4e925c9..88d87ae 100644 --- a/src/Visitor.java +++ b/src/main/Visitor.java @@ -1,3 +1,5 @@ +package main; + public interface Visitor<T>{ public T visit(final Parser.BinaryOperation binOp); public T visit(final Parser.Variable variable); diff --git a/src/test/LexerTest.java b/src/test/LexerTest.java new file mode 100644 index 0000000..54356a6 --- /dev/null +++ b/src/test/LexerTest.java @@ -0,0 +1,59 @@ +package test; + +import org.junit.Test; +import main.*; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class LexerTest { + + @Test + void disassembleFirstStringWithLexer() { + String s = "3+x*(2^4)"; + List<Lexer.Token> tokens = new LinkedList<>(); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"3")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"+")); + tokens.add(new Lexer.Token(Lexer.TokenType.VARIABLE,"x")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"*")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"(")); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"2")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"^")); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"4")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,")")); + try { + assertEquals(Lexer.lex(s),tokens); + } + catch(Exception e) { + e.printStackTrace(); + } + } + + @Test + void disassembleSecondStringWithLexer() { + String s = "1 + (x^2 )- (3*x)"; + List<Lexer.Token> tokens = new LinkedList<>(); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"1")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"+")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"(")); + tokens.add(new Lexer.Token(Lexer.TokenType.VARIABLE,"x")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"^")); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"2")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,")")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"-")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"(")); + tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"3")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"*")); + tokens.add(new Lexer.Token(Lexer.TokenType.VARIABLE,"x")); + tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,")")); + try { + assertEquals(Lexer.lex(s),tokens); + } + catch(Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/test/ParserTest.java b/src/test/ParserTest.java new file mode 100644 index 0000000..0be7f64 --- /dev/null +++ b/src/test/ParserTest.java @@ -0,0 +1,4 @@ +package test; + +public class ParserTest { +} -- GitLab