private static CalculateExpression Parse(Dictionary <string, MoneyColumnMetadataJsModel> columns, MoneyColumnMetadataJsModel column, string function) { CalculateExpression currentExpression = new EmptyExpression(column); try { while (function.Length > 0) { function = function.Trim(); if (function[0] == '[') { var referenceName = function.Substring(1, function.IndexOf(']') - 1); function = function.Remove(0, function.IndexOf(']') + 1); var matchingColumn = columns[referenceName]; currentExpression = currentExpression.TryApply(new ReferenceExpression(matchingColumn)); } else if (function[0] == '(') { var counter = 1; int i; for (i = 1; i < function.Length && counter > 0; i++) { if (function[i] == '(') { counter++; } if (function[i] == ')') { counter--; } } var sub = function.Substring(0, i); var subExp = Parse(columns, column, sub.TrimStart('(').TrimEnd(')')); currentExpression = currentExpression.TryApply(new ParenthesisExpression(subExp)); function = function.Substring(i); } else if (function[0] == '{') { var constant = function.Substring(1, function.IndexOf('}') - 1); function = function.Remove(0, function.IndexOf('}') + 1); currentExpression = currentExpression.TryApply(new ConstantExpression(column, constant)); } else { var symbol = BinaryExpression.Symbols.FirstOrDefault(function.StartsWith); if (symbol != null) { currentExpression = new BinaryExpression(column, symbol).TryApply(currentExpression); function = function.Substring(symbol.Length); } else { return(new FailedToParseExpression(column, function)); } } } } catch { return(new FailedToParseExpression(column, function)); } return(currentExpression); }