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

implemented final version of Parser.java and a fitting test class ParserTest.java

parent 7a28a1b0
No related branches found
No related tags found
1 merge request!13Dominicsbranch
2*(4^2)
(4+2)*4
(4+2*(4-2))
((3+2)*(12+2))
1+(x^2.22)-(3*x)
2*x+0.5*(x^2+4)-1
\ No newline at end of file
......@@ -116,11 +116,12 @@ public class Parser {
return ast;
}
//called by parseExpression
//checks if there are multiple tokens left, which indicates that they build up a BinaryOperation
//It splits up the tokens into a left and right expression and with a recursive call of parseExpression
//each part will be determined, until all BinaryOperations consist of finite left and right expressions
//Then a new BinaryOperation will be returned, which saves the left- & right expression and the operator
//between them
private BinaryOperation parseBinaryOperation(List<Lexer.Token> ts) throws ParserException {
if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
......@@ -128,76 +129,111 @@ public class Parser {
if(ts.size()==1) {
return null;
}
int index = 0;
//Index will be determined in the next if/else statement
//It will indicate the position of the operator that separates the left- and right expression
int index;
int tokensInBracket = parseBrackets(ts);
boolean capsuled;
//If the result of parseBrackets(ts)+1 is the same as ts.size the current BinaryOperation is capsuled
if(tokensInBracket+1==ts.size()) {
//removes the tokens with the capsuling brackets
ts.remove(tokensInBracket);
ts.remove(0);
capsuled = true;
index = 1;
//Checks again for brackets
tokensInBracket = parseBrackets(ts);
//If no bracket is following, the operator needs to be at position 1 of ts
if(tokensInBracket==-1) {
index = 1;
}
else {
//If brackets are following, the operator is at position tokensInBracket+1
index = tokensInBracket+1;
}
}
//If tokensInBracket is -1 this expression is not capsuled and the operator needs to be at position 1 of ts
else if (tokensInBracket==-1) {
capsuled = false;
parseOperator(ts.get(1).getData());
index = 1;
}
//If both other cases were not fulfilled an inner expression is capsuled
//Then this BinaryOperation is not capsuled, no brackets need to be removed and the operator is at
//position tokensInBracket+1
else {
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<>();
//Splits the token list ts into a left and right expression
for(int iterator = 0; iterator<index; iterator++) {
leftList.add(ts.remove(0));
}
Expression leftExpression = parseExpression(leftList);
//Operator is now at position 0
String operator = ts.remove(0).getData();
Expression rightExpression = parseExpression(ts);
return new BinaryOperation(leftExpression, operator, rightExpression, capsuled);
}
//checks if a String only contains an allowed operator with parseCharacter(...)
private boolean parseOperator(String operator) throws ParserException {
if(operator.length()>1) {
throw new ParserException("SyntaxError: invalid length for an operator: " + operator);
}
if(!parseCharacter(operator, "+-*/^")) {
throw new ParserException("SyntaxError: invalid operator character: " + operator);
}
return true;
}
//called by parseBinaryOperator
//checks if the first token is a bracket
//If yes: checks if the bracket gets closed correctly and returns the index of the closing bracket
//If no: returns -1
private int parseBrackets(List<Lexer.Token> ts) throws ParserException{
if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
}
if(parseCharacter(ts.get(0).getData(), "(")) {
int index;
int lBrackets = 0;
int rBrackets = 0;
boolean found = false;
//Iterates through every token, until the closing bracket got found
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 more ')' got found then '(' the bracket got closed correctly and the loop can be interrupted
if(rBrackets>lBrackets) {
found = true;
break;
}
}
}
//If no matching closing bracket was found a ParserException will be thrown
if(!found) {
throw new ParserException("SyntaxError: brackets never got closed");
}
//If the closing bracket was placed immediately after the opening bracket a ParserException will be thrown
if(index==1) {
throw new ParserException("SyntaxError: no value inside brackets");
}
//Returns the index of the closing bracket
return index;
}
return -1;
}
//called by parseBinaryOperation
//checks if a String only contains an allowed operator with parseCharacter
//if not: throws a ParserException
private void parseOperator(String operator) throws ParserException {
if(operator.isEmpty()) {
throw new ParserException("RuntimeError: empty String instead of an operator (+, -, *, /, ^");
}
if(operator.length()>1) {
throw new ParserException("SyntaxError: invalid length for an operator: " + operator);
}
if(!parseCharacter(operator, "+-*/^")) {
throw new ParserException("SyntaxError: invalid operator character: " + operator);
}
}
//called by parseExpression
//Checks if a token is a variable:
......@@ -280,7 +316,10 @@ public class Parser {
//If afterDot is false, the first digit is not allowed to be 0
if(!afterDot) {
parseDigitWithoutZero(data.substring(0,1));
parseDigit(data.substring(1));
if (data.length()>1) {
parseDigit(data.substring(1));
}
}
//Checks if all digits of the number are permitted
else {
......@@ -293,10 +332,10 @@ public class Parser {
//checks if a String only contains numbers(including zero) with parseCharacter
//if not, a ParserException is thrown
private void parseDigit(String data) throws ParserException {
if(data.isEmpty()) {
throw new ParserException("RuntimeError: empty String instead of a digit(0-9)");
}
for(int index=0; index<data.length(); index++) {
if(data.isEmpty()) {
throw new ParserException("RuntimeError: empty String instead of a digit(0-9)");
}
String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "0123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character);
......
......@@ -7,8 +7,6 @@ import org.junit.Test;
import java.util.LinkedList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParserTest {
@Test
......@@ -62,4 +60,41 @@ public class ParserTest {
e.printStackTrace();
}
}
@Test
void testParseBinaryOperation() {
List<Lexer.Token> tokens = new LinkedList<>();
tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"("));
tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"5"));
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,"*"));
tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"3"));
var parser = new Parser();
try {
var ast = parser.parse(tokens);
}
catch(Exception e) {
e.printStackTrace();
}
}
@Test
void testParseWrongBinaryOperation() {
List<Lexer.Token> tokens = new LinkedList<>();
tokens.add(new Lexer.Token(Lexer.TokenType.SPECIAL,"("));
tokens.add(new Lexer.Token(Lexer.TokenType.NUMBER,"5"));
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,"3"));
var parser = new Parser();
try {
var ast = parser.parse(tokens);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
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