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

fixed a bug in lexer.java, implemented whole parser(except brackets)

parent 2533b452
No related branches found
No related tags found
1 merge request!7Dominicsbranch
1 + xy^2 - (31 * x)y x+2/5223+y+44+4+2^12/222
1 + x^2 - (3 * x) \ No newline at end of file
2x + 0,5x^2 - 1
\ No newline at end of file
...@@ -2,36 +2,50 @@ import java.io.BufferedReader; ...@@ -2,36 +2,50 @@ import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList;
import java.util.List; import java.util.List;
public class Application { public class Application {
public static void main(String[] args) { public static void main(String[] args) {
//LinkedList<String> expressions = new LinkedList<>()
//LinkedList<String> expressions = new List<>();
List<String> expressions = new LinkedList<>();
//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:"); 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) {
System.out.println(line); expressions.add(line);
line = reader.readLine(); line = reader.readLine();
} }
System.out.println();
reader.close(); reader.close();
} }
catch (IOException e ) { catch (IOException e ) {
e.printStackTrace(); e.printStackTrace();
} }
//List with a fitting String to be parsed into multiple tokens
List<String> test = Arrays.asList("1 + xy^2 - (31 * x)y"); //Iterates through every String and parses them into multiple tokens
//Iterates through every String for (String value: expressions) {
for (String value: test) { System.out.println(value);
//creates a list of tokens out of the String //creates a list of tokens out of the String
List<Lexer.Token> tokens = Lexer.lex(value); List<Lexer.Token> tokens = Lexer.lex(value);
//prints each token out (with .toString()) //prints each token out (with .toString())
for(Lexer.Token singleToken: tokens) { for(Lexer.Token singleToken: tokens) {
System.out.println(singleToken.toString()); System.out.println(singleToken.toString());
} }
Parser parser = new Parser();
try {
parser.parse(tokens);
System.out.println();
}
catch (ParserException e) {
System.out.println(e.getMessage());
}
System.out.println();
} }
} }
} }
...@@ -47,6 +47,9 @@ public class Lexer { ...@@ -47,6 +47,9 @@ public class Lexer {
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()) {
break;
}
} }
} }
Token token = new Token(TokenType.NUMBER, input.substring(index,endIndex)); Token token = new Token(TokenType.NUMBER, input.substring(index,endIndex));
......
...@@ -10,13 +10,17 @@ public class Parser { ...@@ -10,13 +10,17 @@ public class Parser {
private class BinaryOperation extends Expression { private class BinaryOperation extends Expression {
Expression leftExpression; Expression leftExpression;
char operator; String operator;
Expression rightExpression; Expression rightExpression;
public BinaryOperation(Expression leftExpression, String operator, Expression rightExpression) {
this.leftExpression = leftExpression;
this.operator = operator;
this.rightExpression = rightExpression;
}
} }
private class Variable extends Expression { private class Variable extends Expression {
String variableName; String variableName;
public Variable(String i) { public Variable(String i) {
this.variableName = i; this.variableName = i;
} }
...@@ -27,9 +31,9 @@ public class Parser { ...@@ -27,9 +31,9 @@ public class Parser {
} }
private class Number extends Value { private class Number extends Value {
public String original; public String digits;
public Number(String i) { public Number(String i) {
this.original = i; this.digits = i;
} }
} }
...@@ -54,9 +58,8 @@ public class Parser { ...@@ -54,9 +58,8 @@ public class Parser {
Expression ast = parseExpression(ts); Expression ast = parseExpression(ts);
if(!ts.isEmpty()) { if(!ts.isEmpty()) {
throw new ParserException("SyntaxError: " + ts.size() + " Token(s) left"); throw new ParserException("RuntimeError: " + ts.size() + " token(s) left");
} }
return ast; return ast;
} }
...@@ -64,145 +67,111 @@ public class Parser { ...@@ -64,145 +67,111 @@ public class Parser {
//parses a list of tokens into an expression //parses a list of tokens into an expression
private Expression parseExpression(List<Lexer.Token> ts) throws ParserException { private Expression parseExpression(List<Lexer.Token> ts) throws ParserException {
if(ts.isEmpty()) { if(ts.isEmpty()) {
throw new ParserException("empty token list"); throw new ParserException("SyntaxError: empty token list");
}
Expression ast;
ast = parseBinaryOperation(ts);
if(ast==null) {
ast = parseVariable(ts);
if(ast==null) {
ast = parseValue(ts);
}
if(ast==null) {
throw new ParserException("SyntaxError: invalid character");
}
} }
return ast;
return null;
//return parseValue(ts).orElseGet(() -> parseVariable(ts).orElseGet(() -> null));
} }
//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("RuntimeException: invalid length for an operator: " + operator); throw new ParserException("SyntaxError: invalid length for an operator: " + operator);
}
parseCharacter(operator, "+-*/^");
return true;
}
//called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...)
//checks if a certain string can be found in a string of allowed character
//if yes: return true
//if not: a ParserException is thrown
private Boolean parseCharacter(String data, String allowedCharacters) throws ParserException {
if(!allowedCharacters.contains(data)) {
throw new ParserException("SyntaxError: Invalid character: " + data);
} }
if(data.isEmpty()) { if(!parseCharacter(operator, "+-*/^")) {
throw new ParserException("RuntimeException: empty String"); throw new ParserException("SyntaxError: invalid operator character: " + operator);
} }
return true; return true;
} }
private Optional<BinaryOperation> parseBinaryOperation(List<Lexer.Token> ts) throws ParserException { private BinaryOperation parseBinaryOperation(List<Lexer.Token> ts) throws ParserException {
if(ts.get(0).getType()!=Lexer.TokenType.SPECIAL) { if(ts.isEmpty()) {
throw new ParserException("SyntaxError: expected bracket, got " + ts.get(0).getData() + " instead"); throw new ParserException("SyntaxError: empty token list");
} }
String lbracket = ts.remove(0).getData(); if(ts.size()==1) {
parseCharacter(lbracket, "("); return null;
int i;
boolean found = false;
//check for bracket
/*
for(i=0; i<ts.size(); i++) {
if(ts.get(0).getType() == Lexer.TokenType.SPECIAL) {
int rightBrackets = 0;
int leftBrackets = 0;
if(parseCharacter(ts.get(0).getData(),"(")) {
leftBrackets += 1;
}
else if(parseCharacter(ts.get(0).getData(),")")) {
rightBrackets += 1;
if(rightBrackets>leftBrackets) {
found = true;
break;
}
}
}
} }
if(!found) { BinaryOperation operation;
throw new ParserException("SyntaxError: no matching bracket was found"); if(ts.get(1).getType()!= Lexer.TokenType.SPECIAL) {
throw new ParserException("SyntaxError: unexpected operator: " + ts.get(1).getData());
} }
*/
List<Lexer.Token> leftList = new LinkedList<>(); List<Lexer.Token> leftList = new LinkedList<>();
//check for operator leftList.add(ts.remove(0));
for(i=0; i<ts.size(); i++) {
leftList.add(ts.remove(i));
if(parseOperator(ts.get(i).getData())) {
break;
}
}
ts.remove(0);
if(ts.size()==0) {
throw new ParserException("SyntaxError: could not find a matching operator");
}
Expression leftExpression = parseExpression(leftList); Expression leftExpression = parseExpression(leftList);
String operator = ts.remove(0).getData();
parseOperator(operator);
Expression rightExpression = parseExpression(ts); Expression rightExpression = parseExpression(ts);
return null; return new BinaryOperation(leftExpression, operator, rightExpression);
} }
private Optional<Variable> parseVariable(List<Lexer.Token> ts) throws ParserException { private Variable parseVariable(List<Lexer.Token> ts) throws ParserException {
if (ts.isEmpty()) { if (ts.isEmpty()) {
throw new ParserException("RuntimeException: empty token list"); throw new ParserException("SyntaxError: empty token list");
} }
if (ts.get(0).getType() != Lexer.TokenType.VARIABLE) { if (ts.get(0).getType() != Lexer.TokenType.VARIABLE) {
return Optional.empty(); return null;
} }
String data = ts.remove(0).getData(); String data = ts.remove(0).getData();
if (data.isEmpty()) { if (data.isEmpty()) {
throw new ParserException("RuntimException: empty token"); throw new ParserException("SyntaxError: empty token");
} }
parseCharacter(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); if(!parseCharacter(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) {
return Optional.of(new Variable(data)); throw new ParserException("Invalid variable character: " + data);
}
return new Variable(data);
} }
//called by method parseException(...) //called by method parseException(...)
//parses a list of tokens into a value //parses a token/list of tokens into a value
private Optional<Value> parseValue(List<Lexer.Token> ts) throws ParserException { private Value parseValue(List<Lexer.Token> ts) throws ParserException {
if (ts.isEmpty()) { if (ts.isEmpty()) {
throw new ParserException("RuntimeException: empty token list"); throw new ParserException("SyntaxError: empty token list");
} }
if (ts.get(0).getType() != Lexer.TokenType.NUMBER) { if (ts.get(0).getType() != Lexer.TokenType.NUMBER) {
return Optional.empty(); return null;
} }
String data = ts.get(0).getData();
String data = ts.remove(0).getData();
if (data.isEmpty()) { if (data.isEmpty()) {
throw new ParserException("RuntimeException: empty token"); throw new ParserException("SyntaxError: empty token");
} }
if (ts.size()>0) { Value value = null;
if (ts.size()>1) {
//if the next token is of TokenType.SPECIAL, check if it's a comma //if the next token is of TokenType.SPECIAL, check if it's a comma
//if it is, create a decimal //if it is, create a decimal
if(ts.get(0).getType() == Lexer.TokenType.SPECIAL) { if(ts.get(0).getType() == Lexer.TokenType.SPECIAL) {
if(ts.size()>1) { if(parseComma(ts)) {
if(parseComma(ts.get(0).getData())) { value = parseDecimal(ts);
return Optional.of(parseDecimal(ts, data));
}
} }
} }
} }
//if the next token wasn't a comma, create a number if(value==null) {
return Optional.of(parseNumber(data)); 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, String data) throws ParserException { private Decimal parseDecimal(List<Lexer.Token> ts) throws ParserException {
if(ts.size()<1) { String data = ts.remove(0).getData();
throw new ParserException("RuntimeException: empty token list"); if(data.isEmpty()) {
} throw new ParserException("SyntaxError: empty data");
if(ts.get(0).getType() != Lexer.TokenType.SPECIAL) {
throw new ParserException("SyntaxException: expected a comma");
} }
if(ts.get(1).getType() != Lexer.TokenType.NUMBER) { if(ts.size()==0) {
throw new ParserException("SyntaxException: expected a number after a comma"); throw new ParserException("SyntaxError: no tokens left to create Decimal");
} }
Number beforeDot = (Number) parseNumber(data); Number beforeDot = (Number) parseNumber(data);
ts.remove(0); ts.remove(0);
...@@ -231,7 +200,10 @@ public class Parser { ...@@ -231,7 +200,10 @@ public class Parser {
//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=1; index<data.length(); index++) {
parseCharacter(Character.toString(data.charAt(index)), "0123456789"); String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "0123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character);
}
} }
} }
...@@ -239,11 +211,40 @@ public class Parser { ...@@ -239,11 +211,40 @@ public class Parser {
//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=1; index<data.length(); index++) {
parseCharacter(Character.toString(data.charAt(index)),"123456789"); String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character);
}
} }
} }
private Boolean parseComma(String data) throws ParserException { private Boolean parseComma(List<Lexer.Token> ts) throws ParserException {
return true; String data = ts.get(0).getData();
if(parseCharacter(data, ".")) {
if(ts.get(1).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(...)
//checks if a certain string can be found in a string of allowed character
private Boolean parseCharacter(String data, String allowedCharacters) throws ParserException {
if(data.isEmpty()) {
throw new ParserException("RuntimeError: empty String");
}
return (allowedCharacters.contains(data));
} }
} }
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