package expressions;

import tokens.Token;

import java.util.Stack;

/**
 * Expression stellt einen Ausdruck dar, der mit der eval()-Methode ausgewertet werden kann. Der Ausdruck
 * kann eine Variable x enthalten, die als Argument an eval übergeben wird.
 */
public abstract class Expression {
    protected Expression() {
    }

    /**
     * eval wertet den Ausdruck aus. Dabei wird der übergebene Wert für die Variable x eingesetzt.
     *
     * @param x Der für x einzusetzende Wert. Der Parameter x sollte stets übergeben werden, muss aber von
     *          Tochterklassen nicht benutzt werden, falls der dargestellte Ausdruck kein x enthält.
     * @return Das Ergebnis des Ausdrucks mit dem ggf. eingesetzten x.
     */
    public abstract double eval(double x);



    // TODO: Vervollständige den parseRPN-Algorithmus. Nutze dazu einen Switch-Case. Weitere Informationen
    // TODO: zum Algorithmus und zum Umgang mit dem Stack findest du auf dem Aufgabenblatt.
    /**
     * parseRPN liest ein Array aus Tokens, die in umgekehrter polnischer Notation sortiert sein müssen, und konstruiert
     * daraus einen Syntaxbaum aus Expression-Tochterklassen.
     *
     * Die Konstruktion des Syntaxbaumes funktioniert so:
     * Gehe das Array von vorne nach hinten durch und führe die folgenden Aktionen aus:
     *  * Wenn in tokens eine Zahl oder ein x angetroffen wird, wird eine NumberExpression/XExpression erzeugt und auf
     *    den Stack gelegt.
     *  * Wenn in tokens ein FunctionToken angetroffen wird, wird eine Expression vom Stack genommen, als
     *    Funktionsargument genutzt, und eine UnaryFunctionExpression mit diesem Argument erzeugt und auf den Stack
     *    gelegt.
     *  * Wenn in tokens ein Rechen-Operator angetroffen wird, werden zwei Expressions vom Stack genommen, als
     *    linke und rechte Operanden genutzt und eine OperatorExpression mit diesen Operanden erzeugt und auf den Stack
     *    gelegt.
     *  * Wirf an einer passenden Stelle eine IllegalArgumentException und fange an einer anderen Stelle
     *    eine EmptyStackException ab
     *  Durch die Wiederverwendung der Expressions auf dem Stack entsteht auf diese Weise nach und nach eine
     *  Baumstruktur.
     *
     * @param tokens Tokens, die einen mathematischen Ausdruck in umgekehrter polnischer Notation darstellen.
     * @return Eine Expression, die rekursiv den kompletten Ausdruck darstellt.
     * @throws IllegalArgumentException wird im Fehlerfall geworfen.
     */
    public static Expression parseRPN(Token[] tokens) {
        // Bitte diesen Stack benutzen. Methoden sind z.B. stack.pop, stack.push, stack.peek.
        Stack<Expression> stack = new Stack<>();
    }
}