rechenmaschine/Rechenmaschine.java

303 lines
11 KiB
Java

import java.util.Scanner;
/**
* Hauptklasse des Projekts
*/
public class Rechenmaschine {
public static void main(String[] args) {
new Rechenmaschine();
}
private List<Token> tokenlist;
private String fehler;
private double result;
public Rechenmaschine() {
tokenlist = new List<>();
Scanner input = new Scanner(System.in);
System.out.println("Gib einen Term ein und bestätige mit ENTER: ");
String eingabe = input.nextLine();
input.close();
if( !scanne(eingabe) ) {
System.out.println("Fehler bei der lexikalischen Analyse:");
System.out.println(fehler);
return;
}
if( !parse() ) {
System.out.println("Fehler bei der syntaktischen Analyse:");
System.out.println(fehler);
return;
}
if( !analyse() ) {
System.out.println("Fehler bei der semantischen Analyse:");
System.out.println(fehler);
return;
}
run();
System.out.println("Ergebnis der Ausführung: " + result);
}
public boolean scanne( String pEingabe ) {
char[] eingabe = pEingabe.toCharArray();
int state = 0;
StringBuilder currentToken = new StringBuilder();
for(char buchstabe: eingabe){
switch(state){
case 0:
switch (buchstabe) {
case '0' -> {
currentToken.append(buchstabe);
state = 1;
}
case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
currentToken.append(buchstabe);
state = 2;
}
case '.' -> {
System.out.println("Am anfang des Termes kann kein . stehen.");
return false;
}
case '+', '-', '*', '/' -> {
System.out.println("Der Term darf nicht mir mit dem Operator " + buchstabe + " beginnen.");
return false;
}
default -> {
System.out.println("Der Buchstabe " + buchstabe + " ist nicht in der Sprache vorhanden.");
return false;
}
}
break;
case 1:
switch (buchstabe) {
case '.' -> {
currentToken.append(buchstabe);
state = 3;
}
case '+', '-', '*', '/' -> {
tokenlist.append(new Token("OPERAND", currentToken.toString()));
currentToken = new StringBuilder();
tokenlist.append(new Token("OPERATOR", Character.toString(buchstabe)));
state = 5;
}
default -> {
System.out.println("Der Buchstabe " + buchstabe + " ist nicht in der Sprache vorhanden.");
return false;
}
}
break;
case 2:
switch (buchstabe) {
case '.' -> {
currentToken.append(buchstabe);
state = 3;
}
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
currentToken.append(buchstabe);
state = 2;
}
case '+', '-', '*', '/' -> {
tokenlist.append(new Token("OPERAND", currentToken.toString()));
currentToken = new StringBuilder();
tokenlist.append(new Token("OPERATOR", Character.toString(buchstabe)));
state = 5;
}
default -> {
System.out.println("Der Buchstabe " + buchstabe + " ist nicht in der Sprache vorhanden.");
return false;
}
}
break;
case 3:
switch (buchstabe) {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
currentToken.append(buchstabe);
state = 4;
}
case '+', '-', '*', '/' -> {
System.out.println("Nach einem . darf kein Rechenoperator folgen");
return false;
}
}
break;
case 4:
switch (buchstabe) {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
currentToken.append(buchstabe);
state = 4;
}
case '+', '-', '*', '/' -> {
tokenlist.append(new Token("OPERAND", currentToken.toString()));
currentToken = new StringBuilder();
tokenlist.append(new Token("OPERATOR", Character.toString(buchstabe)));
state = 5;
}
case '.' -> {
System.out.println("Eine Dezimalzahl kann nur ein . haben.");
return false;
}
}
break;
case 5:
switch (buchstabe) {
case '0' -> {
currentToken.append(buchstabe);
state = 1;
}
case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
currentToken.append(buchstabe);
state = 2;
}
case '.' -> {
System.out.println("Nach einem Operator kann kein . stehen.");
return false;
}
case '+', '-', '*', '/' -> {
System.out.println("Nach einem Operator darf nicht direkt ein weiterer Operator folgen.");
return false;
}
default -> {
System.out.println("Der Buchstabe " + buchstabe + " ist nicht in der Sprache vorhanden.");
return false;
}
}
break;
}
}
if( state == 5 ) {
fehler = "Fehler im Wort " +pEingabe+ ":\nDas Wort darf nicht mit einem Operator enden!";
return false;
} else if (state == 3){
fehler = "Fehler im Wort " +pEingabe+ ":\nDas Wort darf nicht mit einem Operator enden!";
return false;
} else {
tokenlist.append(new Token("OPERAND", currentToken.toString()));
return true;
}
}
public boolean parse() {
int state = 0;
tokenlist.toFirst();
while( tokenlist.hasAccess() ) {
Token currentToken = tokenlist.getContent();
switch( state ) {
case 0:
if( currentToken.getType().equals("OPERATOR") ) {
fehler = "Rechenterm darf nicht mit einem Operator starten!";
return false;
} else if( currentToken.getType().equals("OPERAND") ) {
state = 1;
break;
} else {
fehler = "Unbekanntes Token: "+currentToken.getType();
return false;
}
case 1:
if( currentToken.getType().equals("OPERATOR") ) {
state = 0;
break;
} else if( currentToken.getType().equals("OPERAND") ) {
fehler = "Auf einen Operanden muss ein Operator folgen!";
return false;
} else {
fehler = "Unbekanntes Token: "+currentToken.getType();
return false;
}
}
tokenlist.next();
}
if( state == 0 ) {
fehler = "Ein Rechenterm darf nicht auf einen Operator enden!";
return false;
} else {
return true;
}
}
public boolean analyse() {
tokenlist.toFirst();
while(tokenlist.hasAccess()){
if(tokenlist.getContent().getToken().equals("/")){
tokenlist.next();
if(tokenlist.getContent().getToken().equals("0")){
fehler = "Es kann nicht durch 0 geteilt werden.";
return false;
}
}
tokenlist.next();
}
return true;
}
public void punktVorStrich(){
tokenlist.toFirst();
while(tokenlist.hasAccess()){
if(tokenlist.getContent().getToken().equals("*")){
tokenlist.remove();
Double a = Double.parseDouble(tokenlist.getContent().getToken());
tokenlist.current=tokenlist.getPrevious(tokenlist.current);
Double b = Double.parseDouble(tokenlist.getContent().getToken());
tokenlist.remove();
tokenlist.getContent().setToken(String.valueOf(a*b));
} else if(tokenlist.getContent().getToken().equals("/")){
tokenlist.remove();
Double b = Double.parseDouble(tokenlist.getContent().getToken());
//Previous muss gelöscht werden, tokenlist.getContent != null ist,
// wenn der 2. Token am ende des Termes ist.
tokenlist.current=tokenlist.getPrevious(tokenlist.current);
Double a = Double.parseDouble(tokenlist.getContent().getToken());
tokenlist.remove();
tokenlist.getContent().setToken(String.valueOf(a/b));
}
tokenlist.next();
}
}
public void run() {
result = 0;
punktVorStrich();
tokenlist.toFirst();
String previous="";
while( tokenlist.hasAccess() ) {
Token currentToken = tokenlist.getContent();
if(currentToken.getType().equals("OPERATOR")){
previous=currentToken.getToken();
}
if( currentToken.getType().equals("OPERAND") ) {
switch (previous) {
case "+", "" -> result += Double.parseDouble(currentToken.getToken());
case "-" -> result -= Double.parseDouble(currentToken.getToken());
}
}
tokenlist.next();
}
}
}