fromStringExtended static method

MathExpression fromStringExtended(
  1. String expression, {
  2. bool isMinusNegativeFunction = false,
  3. bool isImplicitMultiplication = true,
  4. Set<String> variableNames = const {'x'},
  5. MathCustomFunctionsImplemented customFunctions = const MathCustomFunctionsImplemented({}),
})

Create a new MathExpression from String

Compared to fromString, this method also supports creating MathExpression entities, like MathComparisonEquation, MathComparisonGreater, MathComparisonLess. This means, this method supports =, < and > operators.

Implementation

static MathExpression fromStringExtended(
  /// The expression to convert
  String expression, {
  /// Converts all X - Y to X + (-Y)
  bool isMinusNegativeFunction = false,

  /// Allows skipping the multiplication (*) operator
  bool isImplicitMultiplication = true,

  /// Expressions which should be marked as variables
  Set<String> variableNames = const {'x'},

  /// Expressions which should be marked as functions
  MathCustomFunctionsImplemented customFunctions =
      const MathCustomFunctionsImplemented({}),
}) {
  final nodes = <_MathExpressionPart>[];

  int start = 0;
  for (final match in RegExp('(<=|>=|=|<|>)').allMatches(expression, 0)) {
    var r = expression.substring(start, match.start);
    if (r.isNotEmpty) nodes.add(_MathExpressionPartString(r));
    r = match[0]!;
    if (r.isNotEmpty) {
      nodes.add(_MathExpressionPartString(r));
    }
    start = match.end;
  }

  final r = expression.substring(start);
  if (r.isNotEmpty) nodes.add(_MathExpressionPartString(r));

  for (var i = 0; i < nodes.length; i++) {
    final token = nodes[i];
    if (token is! _MathExpressionPartString ||
        !RegExp(r'^(<=|>=|=|<|>)$').hasMatch(token.str)) continue;

    if (i == 0 || i == nodes.length - 1) {
      throw MissingOperatorOperandException(token.str);
    }

    final left = nodes[i - 1];
    late final _MathExpressionPartParsed leftParsed;

    if (left is _MathExpressionPartString) {
      leftParsed = _MathExpressionPartParsed(
        fromString(
          left.str,
          isMinusNegativeFunction: isImplicitMultiplication,
          isImplicitMultiplication: isImplicitMultiplication,
          customFunctions: customFunctions,
          variableNames: variableNames,
        ),
      );
    } else if (left is _MathExpressionPartParsed) {
      leftParsed = left;
    } else {
      throw CantProcessExpressionException([left]);
    }

    final right = nodes[i + 1];
    late final _MathExpressionPartParsed rightParsed;

    if (right is _MathExpressionPartString) {
      rightParsed = _MathExpressionPartParsed(
        fromString(
          right.str,
          isMinusNegativeFunction: isImplicitMultiplication,
          isImplicitMultiplication: isImplicitMultiplication,
          customFunctions: customFunctions,
          variableNames: variableNames,
        ),
      );
    } else if (right is _MathExpressionPartParsed) {
      rightParsed = right;
    } else {
      throw CantProcessExpressionException([right]);
    }

    nodes.removeAt(i - 1);
    nodes.removeAt(i - 1);
    nodes.removeAt(i - 1);

    late final MathExpression result;

    if (token.str == '>=') {
      result =
          MathComparisonGreaterOrEquals(leftParsed.node, rightParsed.node);
    } else if (token.str == '<=') {
      result = MathComparisonLessOrEquals(leftParsed.node, rightParsed.node);
    } else if (token.str == '=') {
      result = MathComparisonEquation(leftParsed.node, rightParsed.node);
    } else if (token.str == '>') {
      result = MathComparisonGreater(leftParsed.node, rightParsed.node);
    } else if (token.str == '<') {
      result = MathComparisonLess(leftParsed.node, rightParsed.node);
    } else {
      throw UnknownOperationException(token.str);
    }

    nodes.insert(i - 1, _MathExpressionPartParsed(result));
    i -= 2;
  }

  if (nodes.length == 1) {
    if (nodes[0] is _MathExpressionPartString) {
      return fromString(
        nodes[0].str!,
        isMinusNegativeFunction: isImplicitMultiplication,
        isImplicitMultiplication: isImplicitMultiplication,
        customFunctions: customFunctions,
        variableNames: variableNames,
      );
    } else if (nodes[0] is _MathExpressionPartParsed) {
      return nodes[0].node!;
    }
  }

  throw CantProcessExpressionException(nodes);
}