private IEnumerable <ExcelExpressionPart> EvaluateFunctionArguments(ExcelExpression expression, ExpressionScope scope) { var args = new List <ExcelExpressionPart>(); ExcelExpression activeArg = null; foreach (var item in expression) { if (item.TokenType == ExcelFormulaTokenType.Argument) { if (activeArg == null) { // possible optional argument -- consecutive commas args.Add(new ExcelExpressionPart(ExcelValue.NULL)); } else { args.Add(activeArg.Evaluate(scope)); } activeArg = null; } else { if (activeArg == null) { activeArg = new ExcelExpression(); } activeArg.Add(item); } } if (activeArg != null) { args.Add(activeArg.Evaluate(scope)); } return(args); }
private EvaluationResult Evaluate(string name, string cell, IEnumerable <ExcelFormulaToken> tokens, ExpressionScope scope, ExpressionFormat format) { var result = new EvaluationResult() { Name = name, Cell = cell }; try { var queue = new Queue <ExcelFormulaToken>(tokens); var excelExpression = new ExcelExpression(); TraverseExpression(excelExpression, queue, scope); var operand = excelExpression.Evaluate(scope); scope.Set(cell ?? name, operand.Value); result.Value = operand.Value.InnerValue; result.Text = operand.Value?.ToString(outputLang, format); } catch (Exception ex) { result.Error = ex.Message; } finally { } return(result); }
private void TraverseExpression(ExcelExpression expression, Queue <ExcelFormulaToken> tokens, ExpressionScope scope) { while (tokens.Any()) { var token = tokens.Dequeue(); if (token.Subtype == ExcelFormulaTokenSubtype.Stop) { return; } else if (token.Subtype == ExcelFormulaTokenSubtype.Start) { var childExpression = new ExcelExpression(); TraverseExpression(childExpression, tokens, scope); switch (token.Type) { case ExcelFormulaTokenType.Function: var name = token.Value.ToUpper(); var args = EvaluateFunctionArguments(childExpression, scope) .Select(o => o.Value) .ToList(); var value = Functions.INSTANCE.Evaluate(name, args, scope); expression.Add(new ExcelExpressionPart(value)); break; case ExcelFormulaTokenType.Subexpression: var subExpression = childExpression.Evaluate(scope); expression.Add(subExpression); break; default: throw new NotImplementedException($"Start TokenType={token.Type}"); } } else { expression.Add(new ExcelExpressionPart(token, scope)); } } }