forked from IF-LK-2020/rechenmaschine
274 lines
10 KiB
Java
274 lines
10 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 Plusterm 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 run() {
|
|
result = 0;
|
|
|
|
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());
|
|
case "*" -> result *= Double.parseDouble(currentToken.getToken());
|
|
default -> result /= Double.parseDouble(currentToken.getToken());
|
|
}
|
|
}
|
|
tokenlist.next();
|
|
}
|
|
}
|
|
|
|
}
|