evaluateExpression function

double evaluateExpression(
  1. String expression
)

Evaluates an arithmetic expression and returns the result as a double.

The expression parameter is a string that represents the arithmetic expression to evaluate.

Example:

void main() {
  // Evaluate an arithmetic expression and print the result.
  final result = evaluateExpression('2 * (3 + 4) / 5');
  print(result); // Output: 2.80
}

Returns the result of the arithmetic expression as a double.

Implementation

double evaluateExpression(String expression) {
  int i = 0;

  if (expression.isEmpty) {
    throw Exception('Invalid expression');
  }

  // A recursive function that parses the expression and
  // returns the result as a Decimal.
  double parseExpression() {
    final values = <double>[]; // A stack to store numeric values.
    final operators = <String>[]; // A stack to store operators.
    double lastNonOperatorValue = 1.0;

    // Iterate through the expression.
    while (i < expression.length) {
      if (expression[i] == ' ') {
        i++; // Ignore spaces.
      } else if (isOperator(expression[i])) {
        // If the current character is an operator.
        if (isNegativeUnaryOperator(expression, i)) {
          // If the current character is a unary operator,
          // parse the number with a negative sign.
          i++;
          int j = i;

          while (j < expression.length &&
              isCharDigitOrDecimalPointOrPercentage(expression[j])) {
            j++;
          }

          final substring = '-${expression.substring(i, j)}';
          var dValue = double.parse(substring.replaceAll('%', ''));

          if (isStringPercentage(expression.substring(i, j)) &&
              (operators.isEmpty ||
                  operators.last == '+' ||
                  operators.last == '-')) {
            // Handle percentage operation for '+' or '-' operators.
            // Handle percentage operation for '+' or '-' operators.
            dValue = lastNonOperatorValue * (dValue / 100);
          }

          values.add(dValue); // Add the parsed number to the values stack.
          lastNonOperatorValue = dValue;
          i = j;
        } else {
          // If the current operator has lower or equal precedence than
          // the last operator in the stack, apply the last operator.
          while (operators.isNotEmpty &&
              precedence(expression[i]) <= precedence(operators.last)) {
            applyOperation(operators.removeLast(), values);
          }

          operators
              .add(expression[i]); // Add the current operator to the stack.
          i++;
        }
      } else if (expression[i] == '(') {
        // If the current character is an open parenthesis.
        i++;
        values.add(parseExpression()); // Call parseExpression recursively.
      } else if (expression[i] == ')') {
        // If the current character is a close parenthesis.
        i++;

        // Apply all remaining operators in the stack to the values
        // in the stack.
        while (operators.isNotEmpty) {
          applyOperation(operators.removeLast(), values);
        }

        return values.last; // Return the last value in the stack.
      } else {
        // If the current character is a digit or a decimal point.
        int j = i;

        while (j < expression.length &&
            isCharDigitOrDecimalPointOrPercentage(expression[j])) {
          j++;
        }

        final substring = expression.substring(i, j);
        var dValue = double.parse(substring.replaceAll('%', ''));

        if (isStringPercentage(expression.substring(i, j)) &&
            (operators.isEmpty ||
                operators.last == '+' ||
                operators.last == '-')) {
          // Handle percentage operation for '+' or '-' operators.
          dValue = lastNonOperatorValue * (dValue / 100);
        }

        values.add(dValue); // Add the parsed number to the values stack.
        lastNonOperatorValue = dValue;
        i = j;
      }
    }

    // Apply any remaining operators in the stack to the values in the stack.
    while (operators.isNotEmpty) {
      applyOperation(operators.removeLast(), values);
    }

    return values.last; // Return the last value in the stack.
  }

  return parseExpression()
      .toDouble(); // Call parseExpression and convert the result to double.
}