namespace Lunar.Evil_Calculator { class EquationManager { private static readonly HashSet _operators = new() { "+", "-", "*", "/", "^", "√" }; List equation = new(); string currentOperand = ""; Label? outerEquationLabel; Label? outerOperandLabel; int openParentheses; //NO OPENING PARENTHESES AFTER NUMERICS OR CLOSING PARENTHESES => NULL, OPENING PARENTHESES OR OPERATOR EXPECTED //NO CLOSING PARENTHESES AFTER OPERATORS, EXCEPT IF $currentOperand IS NOT "" //NO CLOSING PARENTHESES WHEN $openParentheses <1 //OPERATOR OR null BEFORE OPENING PARENTHESES EXPECTED //$openParentheses SHOULD BE 0 BEFORE SOLVING, DISPLAY ERROR OTHERWISE => HANDLED BY SOLVER //MINUS AFTER OPENING PARENTHESES OR null GOES TO OPERAND IF $currentOperand IS "" //NO OPERATORS AFTER OPERATORS, OPENING PARENTHESES OR null (EXCEPT FOR MINUS THAT GOES TO OPERAND AND SQRT THAT IS UNAR) //NO NUMERICS IF currentOperand.StartsWith("0") AND currentOperand.Length == 1, . ALLOWED-EXPECTED //NO . IF currentOperand.Contains(",") public void ProcessButtonInput(object? sender, EventArgs e) { if (sender is Button buttonPressed) { switch (buttonPressed.Text) { //CLEAR case "C": currentOperand = ""; break; case "CE": equation.Clear(); currentOperand = ""; break; //OPERATORS // + - case "+": if ((!IsOperator() && !IsOpen() && !IsNull()) || currentOperand != "" && currentOperand != "-") { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text, 1)); currentOperand = ""; } break; case "-": if ((!IsOperator() || currentOperand != "") && currentOperand != "-") { if ((IsOpen() || IsNull()) && currentOperand == "") { currentOperand += "-"; } else { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text, 1)); currentOperand = ""; } } break; // * / case "*" or "/": if ((!IsOperator() && !IsOpen() && !IsNull()) || currentOperand != "" && currentOperand != "-") { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text, 2)); currentOperand = ""; } break; //SQUARE ROOT case "√": if (!IsClose()) { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text, 3)); currentOperand = ""; } break; //SQUARE AND POWER case "x²": if ((!IsOperator() && !IsOpen() && !IsNull()) || currentOperand != "" && currentOperand != "-") { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, "^", 3)); equation.Add(new Token(Token.TokenType.Operand, "2")); currentOperand = ""; } break; case "xˣ": if ((!IsOperator() && !IsOpen() && !IsNull()) || currentOperand != "" && currentOperand != "-") { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); equation.Add(new Token(Token.TokenType.Operator, "^", 3)); currentOperand = ""; } break; //PARENTHESES case "(": if (IsOperator() || IsOpen() || IsNull()) { equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text)); openParentheses++; currentOperand = ""; } break; case ")": if ((!IsOperator() || currentOperand != "") && openParentheses > 0 && currentOperand != "-") { if (currentOperand.Length > 0) { equation.Add(new Token(Token.TokenType.Operand, currentOperand)); currentOperand = ""; } equation.Add(new Token(Token.TokenType.Operator, buttonPressed.Text)); openParentheses--; } break; //POINT case ",": if (currentOperand.Length > 0 && !currentOperand.Contains(",")) { currentOperand += buttonPressed.Text; } break; //NUMERIC default: if (!(currentOperand.Length == 1 && currentOperand.StartsWith("0"))) { currentOperand += buttonPressed.Text; } break; } UpdateLabels(); } } public void EqualsButtonPressed(object? sender, EventArgs e) { if (sender is Button buttonEquals) { if (currentOperand != "") equation.Add(new Token(Token.TokenType.Operand, currentOperand)); buttonEquals.Text = "#"; currentOperand = ReversePolishNotationSolver.Solve(equation); UpdateLabels(); } } public void AcquireOutputLabels(Label equationTextBox, Label currentOperandTextBox) { outerEquationLabel = equationTextBox; outerOperandLabel = currentOperandTextBox; } public string equationToString() { string equationString = ""; foreach (Token token in equation) { equationString += token.value + " "; } return equationString; } private void UpdateLabels() { if (outerEquationLabel != null && outerOperandLabel != null) { outerEquationLabel.Text = equationToString(); outerOperandLabel.Text = currentOperand == "" ? "0" : currentOperand; } } private bool IsOperator() { if (equation.Count == 0) return false; return _operators.Contains(equation.Last().value); } private bool IsOpen() { if (equation.Count == 0) return false; return equation.Last().value == "("; } private bool IsClose() { if (equation.Count == 0) return false; return equation.Last().value == ")"; } private bool IsNull() { return equation.Count == 0; } } }