-
Dominic Daniel Krämer authoredDominic Daniel Krämer authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Parser.java 9.49 KiB
package main;
import Exceptions.ParserException;
import java.util.LinkedList;
import java.util.List;
public class Parser {
public abstract class Expression {
public abstract <T> T accept(Visitor<T> visitor);
}
public class BinaryOperation extends Expression {
Expression leftExpression;
String operator;
Expression rightExpression;
Boolean capsuled;
public BinaryOperation(Expression leftExpression, String operator, Expression rightExpression, Boolean capsuled) {
this.leftExpression = leftExpression;
this.operator = operator;
this.rightExpression = rightExpression;
this.capsuled = capsuled;
}
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 {
String variableName;
public Variable(String i, Boolean capsuled) {
this.variableName = i;
}
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
private abstract class Value extends Expression {
}
public class Number extends Value {
public String digits;
public Number(String i) {
this.digits = i;
}
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
public class Decimal extends Value {
public Number beforeDot;
public Number afterDot;
public Decimal(Number i1, Number i2) {
this.beforeDot = i1;
this.afterDot = i2;
}
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
//starting method of the parser
//parses a list of tokens
public Expression parse(List<Lexer.Token> list) throws ParserException {
if(list.isEmpty()) {
throw new ParserException("empty token list");
}
List<Lexer.Token> ts = new LinkedList<>(list);
Expression ast = parseExpression(ts);
if(!ts.isEmpty()) {
throw new ParserException("SyntaxError: " + ts.size() + " token(s) left");
}
return ast;
}
//called by method parse(...)
//parses a list of tokens into an expression
private Expression parseExpression(List<Lexer.Token> ts) throws ParserException {
if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
}
Expression 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;
}
//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;
}
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 {
if(ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
}
if(ts.size()==1) {
return null;
}
int index = 0;
int tokensInBracket = parseBrackets(ts);
boolean capsuled;
if(tokensInBracket+1==ts.size()) {
ts.remove(tokensInBracket);
ts.remove(0);
capsuled = true;
index = 1;
}
else if (tokensInBracket==-1) {
capsuled = false;
parseOperator(ts.get(1).getData());
index = 1;
}
else {
capsuled = false;
index = tokensInBracket+1;
}
List<Lexer.Token> leftList = new LinkedList<>();
for(int iterator = 0; iterator<index; iterator++) {
leftList.add(ts.remove(0));
}
Expression leftExpression = parseExpression(leftList);
String operator = ts.remove(0).getData();
Expression rightExpression = parseExpression(ts);
return new BinaryOperation(leftExpression, operator, rightExpression, capsuled);
}
private Variable parseVariable(List<Lexer.Token> ts) throws ParserException {
if (ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
}
if (ts.get(0).getType() != Lexer.TokenType.VARIABLE) {
return null;
}
String data = ts.remove(0).getData();
if (data.isEmpty()) {
throw new ParserException("SyntaxError: empty token");
}
if(!parseCharacter(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) {
throw new ParserException("Invalid variable character: " + data);
}
return new Variable(data, false);
}
//called by method parseException(...)
//parses a token/list of tokens into a value
private Value parseValue(List<Lexer.Token> ts) throws ParserException {
if (ts.isEmpty()) {
throw new ParserException("SyntaxError: empty token list");
}
if (ts.get(0).getType() != Lexer.TokenType.NUMBER) {
return null;
}
String data = ts.remove(0).getData();
if (data.isEmpty()) {
throw new ParserException("SyntaxError: empty token");
}
if(data.contains(".")) {
return parseDecimal(data);
}
return parseNumber(data, false);
}
//called by method parseValue(...)
//parses a decimal of a list of tokens & a string
private Decimal parseDecimal(String data) throws ParserException {
if(data.isEmpty()) {
throw new ParserException("SyntaxError: empty data");
}
int dot = data.indexOf('.');
String number1 = data.substring(0,dot);
String number2 = data.substring(dot+1);
Number beforeDot = (Number) parseNumber(number1, true);
Number afterDot = (Number) parseNumber(number2, false);
return new Decimal(beforeDot, afterDot);
}
//called by method parseValue(...)
//parses a String into a number
private Number parseNumber(String data, boolean afterDot) throws ParserException{
if (data.isEmpty()) {
throw new ParserException("RuntimeException: empty token");
}
if (data.startsWith("0") && data.length() == 1) {
return new Number(data);
}
if(afterDot) {
parseDigitWithoutZero(data.substring(0,1));
parseDigit(data.substring(1));
}
else {
parseDigit(data);
}
return new Number(data);
}
//called by method parseNumber(...)
//checks if a String only contains numbers(including zero) with parseCharacter(...)
private void parseDigit(String data) throws ParserException {
for(int index=0; index<data.length(); index++) {
String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "0123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character);
}
}
}
//called by method parseNumber(...)
//checks if a String only contains numbers(excluding zero) with parseCharacter(...)
private void parseDigitWithoutZero(String data) throws ParserException {
for(int index=0; index<data.length(); index++) {
String character = Character.toString(data.charAt(index));
if(!parseCharacter(character, "123456789")) {
throw new ParserException("SyntaxError: unexpected character: " + character);
}
}
}
//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));
}
}