rpnToComputable function

Computable rpnToComputable(
  1. List<Token<TokenType>> tokens, {
  2. ComputeContext context = const DefaultComputeContext(),
})

Collapses the RPN into a tree of computable expressions.

Implementation

Computable rpnToComputable(List<Token> tokens,
    {ComputeContext context = const DefaultComputeContext()}) {
  if (tokens.isEmpty) {
    return Result.zero();
  }

  final List<Computable> stack = [];
  for (final token in tokens) {
    _log.finest('Current token: $token Stack: $stack');
    if (token is OperatorToken) {
      if (stack.isEmpty) {
        throw ComputationError(ComputationStep.eval,
            message: "Tried to use operator ${token.rawValue} but no operands",
            globalPosition: token.globalOffset);
      }
      final rightHand = stack.removeLast();
      final Computable leftHand;
      if (stack.isEmpty) {
        leftHand = Result.zero();
      } else {
        leftHand = stack.removeLast();
      }

      stack.add(Expression(
          operator: token.operator, leftHand: leftHand, rightHand: rightHand));
    } else if (token is ModifierToken) {
      stack.add(token.modifier.modify(stack.removeLast().compute(context)));
    } else if (token is FunctionToken) {
      final arguments = List.generate(token.function.requiredParameterCount,
          (index) => stack.removeLast().compute(context));
      stack.add(token.function.compute(context, arguments));
    } else {
      stack.add(token);
    }
  }

  return stack.singleOrNull ?? tokens.single.compute(context);
}