Skip to content
Snippets Groups Projects
Commit 6eda657f authored by Dominic Daniel Krämer's avatar Dominic Daniel Krämer
Browse files

Merge branch 'dominicsbranch' into 'main'

Dominicsbranch

See merge request !9
parents acfa97d0 e04b6e92
No related branches found
No related tags found
1 merge request!9Dominicsbranch
40.2+3*x (5*2-(5^2)+3*(201.01-15))
\ No newline at end of file \ No newline at end of file
...@@ -12,10 +12,10 @@ public class Application { ...@@ -12,10 +12,10 @@ public class Application {
List<String> expressions = new LinkedList<>(); 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 a list
BufferedReader reader; BufferedReader reader;
String datapath = "expressions.txt"; String dataPath = "expressions.txt";
try { try {
System.out.println("Reading the file...\n"); System.out.println("Reading the file...\n");
reader = new BufferedReader(new FileReader(datapath)); reader = new BufferedReader(new FileReader(dataPath));
String line = reader.readLine(); String line = reader.readLine();
while(line != null) { while(line != null) {
expressions.add(line); expressions.add(line);
...@@ -39,8 +39,8 @@ public class Application { ...@@ -39,8 +39,8 @@ public class Application {
} }
Parser parser = new Parser(); Parser parser = new Parser();
try { try {
parser.parse(tokens); Parser.Expression exp = parser.parse(tokens);
System.out.println(); System.out.println(exp.toString());
} }
catch (ParserException e) { catch (ParserException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
......
...@@ -43,13 +43,16 @@ public class Lexer { ...@@ -43,13 +43,16 @@ public class Lexer {
//checks if a character is a digit, then creates a token with one or multiple numbers //checks if a character is a digit, then creates a token with one or multiple numbers
//with TokenType=NUMBER //with TokenType=NUMBER
if(Character.isDigit(current)) { if(Character.isDigit(current)) {
int endIndex = index+1; int endIndex = index;
if(endIndex<input.length()) { if(endIndex<input.length()) {
while(Character.isDigit(input.charAt(endIndex)) && endIndex<input.length()) { while(Character.isDigit(input.charAt(endIndex)) && endIndex<input.length()) {
endIndex += 1; endIndex += 1;
if(endIndex==input.length()) { if(endIndex==input.length()) {
break; break;
} }
if(input.charAt(endIndex) == '.') {
endIndex+=1;
}
} }
} }
Token token = new Token(TokenType.NUMBER, input.substring(index,endIndex)); Token token = new Token(TokenType.NUMBER, input.substring(index,endIndex));
......
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional;
public class Parser { public class Parser {
private abstract class Expression { public static class Expression {
@Override
public String toString() {
return "";
}
} }
private class BinaryOperation extends Expression { private class BinaryOperation extends Expression {
Expression leftExpression; Expression leftExpression;
String operator; String operator;
Expression rightExpression; Expression rightExpression;
public BinaryOperation(Expression leftExpression, String operator, Expression rightExpression) { Boolean capsuled;
public BinaryOperation(Expression leftExpression, String operator, Expression rightExpression, Boolean capsuled) {
this.leftExpression = leftExpression; this.leftExpression = leftExpression;
this.operator = operator; this.operator = operator;
this.rightExpression = rightExpression; this.rightExpression = rightExpression;
this.capsuled = capsuled;
}
@Override
public String toString() {
if(capsuled) {
return "("+ leftExpression.toString() + operator + rightExpression.toString() + ")";
}
return leftExpression.toString() + operator + rightExpression.toString();
} }
} }
private class Variable extends Expression { private class Variable extends Expression {
String variableName; String variableName;
public Variable(String i) { public Variable(String i, Boolean capsuled) {
this.variableName = i; this.variableName = i;
} }
@Override
public String toString() {
return variableName;
}
} }
private abstract class Value extends Expression { private abstract class Value extends Expression {
...@@ -35,6 +50,10 @@ public class Parser { ...@@ -35,6 +50,10 @@ public class Parser {
public Number(String i) { public Number(String i) {
this.digits = i; this.digits = i;
} }
@Override
public String toString() {
return digits;
}
} }
private class Decimal extends Value { private class Decimal extends Value {
...@@ -45,6 +64,10 @@ public class Parser { ...@@ -45,6 +64,10 @@ public class Parser {
this.beforeDot = i1; this.beforeDot = i1;
this.afterDot = i2; this.afterDot = i2;
} }
@Override
public String toString() {
return beforeDot.toString() + "." + afterDot.toString();
}
} }
//starting method of the parser //starting method of the parser
...@@ -58,7 +81,7 @@ public class Parser { ...@@ -58,7 +81,7 @@ public class Parser {
Expression ast = parseExpression(ts); Expression ast = parseExpression(ts);
if(!ts.isEmpty()) { if(!ts.isEmpty()) {
throw new ParserException("RuntimeError: " + ts.size() + " token(s) left"); throw new ParserException("SyntaxError: " + ts.size() + " token(s) left");
} }
return ast; return ast;
} }
...@@ -69,22 +92,21 @@ public class Parser { ...@@ -69,22 +92,21 @@ public class Parser {
if(ts.isEmpty()) { if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list"); throw new ParserException("SyntaxError: empty token list");
} }
Expression ast; Expression ast = parseBinaryOperation(ts);
ast = parseBinaryOperation(ts);
if(ast==null) {
ast = parseVariable(ts);
if(ast==null) { if(ast==null) {
ast = parseValue(ts); ast = parseVariable(ts);
} if(ast==null) {
if(ast==null) { ast = parseValue(ts);
throw new ParserException("SyntaxError: invalid character"); }
if(ast==null) {
throw new ParserException("SyntaxError: invalid character");
}
} }
}
return ast; return ast;
} }
//checks if a String only contains an allowed operator with parseCharacter(...) //checks if a String only contains an allowed operator with parseCharacter(...)
private Boolean parseOperator(String operator) throws ParserException { private boolean parseOperator(String operator) throws ParserException {
if(operator.length()>1) { if(operator.length()>1) {
throw new ParserException("SyntaxError: invalid length for an operator: " + operator); throw new ParserException("SyntaxError: invalid length for an operator: " + operator);
} }
...@@ -94,6 +116,35 @@ public class Parser { ...@@ -94,6 +116,35 @@ public class Parser {
return true; return true;
} }
private int parseBrackets(List<Lexer.Token> ts) throws ParserException{
if(parseCharacter(ts.get(0).getData(), "(")) {
int index;
int lBrackets = 0;
int rBrackets = 0;
boolean found = false;
for(index=1; index<ts.size(); index++) {
if(parseCharacter(ts.get(index).getData(), "(")) {
lBrackets += 1;
}
else if(parseCharacter(ts.get(index).getData(), ")")) {
rBrackets += 1;
if(rBrackets>lBrackets) {
found = true;
break;
}
}
}
if(!found) {
throw new ParserException("SyntaxError: brackets never got closed");
}
if(index==1) {
throw new ParserException("SyntaxError: no value inside brackets");
}
return index;
}
return -1;
}
private BinaryOperation parseBinaryOperation(List<Lexer.Token> ts) throws ParserException { private BinaryOperation parseBinaryOperation(List<Lexer.Token> ts) throws ParserException {
if(ts.isEmpty()) { if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list"); throw new ParserException("SyntaxError: empty token list");
...@@ -101,52 +152,32 @@ public class Parser { ...@@ -101,52 +152,32 @@ public class Parser {
if(ts.size()==1) { if(ts.size()==1) {
return null; return null;
} }
int index; int index = 0;
for(index=0; index<ts.size(); index++) { int tokensInBracket = parseBrackets(ts);
if(ts.get(index).getType()== Lexer.TokenType.SPECIAL) { boolean capsuled;
if(!parseCharacter(ts.get(index).getData(), ".")) { if(tokensInBracket+1==ts.size()) {
break; ts.remove(tokensInBracket);
} ts.remove(0);
} capsuled = true;
index = 1;
} }
if(index==ts.size()) { else if (tokensInBracket==-1) {
return null; capsuled = false;
parseOperator(ts.get(1).getData());
index = 1;
}
else {
capsuled = false;
index = tokensInBracket+1;
} }
//0
//1
//2
//3
//4 * => index=4
//5
//6
//7
List<Lexer.Token> leftList = new LinkedList<>(); List<Lexer.Token> leftList = new LinkedList<>();
for(int i=0; i<index; i++) { for(int iterator = 0; iterator<index; iterator++) {
leftList.add(ts.remove(0)); leftList.add(ts.remove(0));
} }
Expression leftExpression = parseExpression(leftList); Expression leftExpression = parseExpression(leftList);
String operator = ts.remove(0).getData(); String operator = ts.remove(0).getData();
parseOperator(operator);
Expression rightExpression = parseExpression(ts);
/*
if(parseCharacter(ts.get(1).getData(), ".")) {
return null;
}
BinaryOperation operation;
if(ts.get(1).getType()!= Lexer.TokenType.SPECIAL) {
throw new ParserException("SyntaxError: unexpected operator: " + ts.get(1).getData());
}
List<Lexer.Token> leftList = new LinkedList<>();
leftList.add(ts.remove(0));
Expression leftExpression = parseExpression(leftList);
String operator = ts.remove(0).getData();
parseOperator(operator);
Expression rightExpression = parseExpression(ts); Expression rightExpression = parseExpression(ts);
return new BinaryOperation(leftExpression, operator, rightExpression, capsuled);
*/
return new BinaryOperation(leftExpression, operator, rightExpression);
} }
private Variable parseVariable(List<Lexer.Token> ts) throws ParserException { private Variable parseVariable(List<Lexer.Token> ts) throws ParserException {
...@@ -165,7 +196,7 @@ public class Parser { ...@@ -165,7 +196,7 @@ public class Parser {
if(!parseCharacter(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) { if(!parseCharacter(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) {
throw new ParserException("Invalid variable character: " + data); throw new ParserException("Invalid variable character: " + data);
} }
return new Variable(data); return new Variable(data, false);
} }
//called by method parseException(...) //called by method parseException(...)
...@@ -177,47 +208,34 @@ public class Parser { ...@@ -177,47 +208,34 @@ public class Parser {
if (ts.get(0).getType() != Lexer.TokenType.NUMBER) { if (ts.get(0).getType() != Lexer.TokenType.NUMBER) {
return null; return null;
} }
String data = ts.get(0).getData(); String data = ts.remove(0).getData();
if (data.isEmpty()) { if (data.isEmpty()) {
throw new ParserException("SyntaxError: empty token"); throw new ParserException("SyntaxError: empty token");
} }
Value value = null; if(data.contains(".")) {
if (ts.size()>1) { return parseDecimal(data);
//if the next token is of TokenType.SPECIAL, check if it's a comma
//if it is, create a decimal
if(ts.get(1).getType() == Lexer.TokenType.SPECIAL) {
if(parseComma(ts)) {
value = parseDecimal(ts);
}
}
} }
if(value==null) { return parseNumber(data, false);
value = parseNumber(ts.remove(0).getData());
}
return value;
} }
//called by method parseValue(...) //called by method parseValue(...)
//parses a decimal of a list of tokens & a string //parses a decimal of a list of tokens & a string
private Decimal parseDecimal(List<Lexer.Token> ts) throws ParserException { private Decimal parseDecimal(String data) throws ParserException {
String data = ts.remove(0).getData();
if(data.isEmpty()) { if(data.isEmpty()) {
throw new ParserException("SyntaxError: empty data"); throw new ParserException("SyntaxError: empty data");
} }
if(ts.size()==0) { int dot = data.indexOf('.');
throw new ParserException("SyntaxError: no tokens left to create Decimal"); String number1 = data.substring(0,dot);
} String number2 = data.substring(dot+1);
Number beforeDot = (Number) parseNumber(data); Number beforeDot = (Number) parseNumber(number1, true);
ts.remove(0); Number afterDot = (Number) parseNumber(number2, false);
data = ts.remove(0).getData();
Number afterDot = (Number) parseNumber(data);
return new Decimal(beforeDot, afterDot); return new Decimal(beforeDot, afterDot);
} }
//called by method parseValue(...) //called by method parseValue(...)
//parses a String into a number //parses a String into a number
private Number parseNumber(String data) throws ParserException{ private Number parseNumber(String data, boolean afterDot) throws ParserException{
if (data.isEmpty()) { if (data.isEmpty()) {
throw new ParserException("RuntimeException: empty token"); throw new ParserException("RuntimeException: empty token");
} }
...@@ -225,16 +243,20 @@ public class Parser { ...@@ -225,16 +243,20 @@ public class Parser {
if (data.startsWith("0") && data.length() == 1) { if (data.startsWith("0") && data.length() == 1) {
return new Number(data); return new Number(data);
} }
if(afterDot) {
parseDigitWithoutZero(data.substring(0,1)); parseDigitWithoutZero(data.substring(0,1));
parseDigit(data.substring(1)); parseDigit(data.substring(1));
}
else {
parseDigit(data);
}
return new Number(data); return new Number(data);
} }
//called by method parseNumber(...) //called by method parseNumber(...)
//checks if a String only contains numbers(including zero) with parseCharacter(...) //checks if a String only contains numbers(including zero) with parseCharacter(...)
private void parseDigit(String data) throws ParserException { private void parseDigit(String data) throws ParserException {
for(int index=1; index<data.length(); index++) { for(int index=0; index<data.length(); index++) {
String character = Character.toString(data.charAt(index)); String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "0123456789")) { if(!parseCharacter(character, "0123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character); throw new ParserException("SyntaxError: unexpected character: " + character);
...@@ -245,7 +267,7 @@ public class Parser { ...@@ -245,7 +267,7 @@ public class Parser {
//called by method parseNumber(...) //called by method parseNumber(...)
//checks if a String only contains numbers(excluding zero) with parseCharacter(...) //checks if a String only contains numbers(excluding zero) with parseCharacter(...)
private void parseDigitWithoutZero(String data) throws ParserException { private void parseDigitWithoutZero(String data) throws ParserException {
for(int index=1; index<data.length(); index++) { for(int index=0; index<data.length(); index++) {
String character = Character.toString(data.charAt(index)); String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "123456789")) { if(!parseCharacter(character, "123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character); throw new ParserException("SyntaxError: unexpected character: " + character);
...@@ -253,30 +275,9 @@ public class Parser { ...@@ -253,30 +275,9 @@ public class Parser {
} }
} }
private Boolean parseComma(List<Lexer.Token> ts) throws ParserException {
String data = ts.get(1).getData();
if(parseCharacter(data, ".")) {
if(ts.get(2).getType()!= Lexer.TokenType.NUMBER) {
throw new ParserException("SyntaxError: no number after comma");
}
return true;
}
return false;
}
private Boolean parseBracket(List<Lexer.Token> ts) throws ParserException {
String data = ts.get(0).getData();
if(parseCharacter(data, "(")) {
return true;
}
else {
return false;
}
}
//called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...) //called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...)
//checks if a certain string can be found in a string of allowed character //checks if a certain string can be found in a string of allowed character
private Boolean parseCharacter(String data, String allowedCharacters) throws ParserException { private boolean parseCharacter(String data, String allowedCharacters) throws ParserException {
if(data.isEmpty()) { if(data.isEmpty()) {
throw new ParserException("RuntimeError: empty String"); throw new ParserException("RuntimeError: empty String");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment