private Expression ParseEquationNoFunctions(string equation) { while (equation.IndexOf('(') != -1) //While there are still grouping symbols { var subEquation = GetSubExpression(equation.Substring(equation.IndexOf('(') + 1)); //Skip '(' subExpressions.Add(ParseEquationNoFunctions(subEquation)); equation = equation.Replace("(" + subEquation + ")", "{" + (subExpressions.Count - 1).ToString() + "}"); } CreateExpressions(ref equation, '^'); CreateExpressions(ref equation, '*', '/'); CreateExpressions(ref equation, '-', '+'); using (TypeTextReader reader = new TypeTextReader(new StringReader(equation.Substring(1)))) { var expressionID = (int)reader.ReadInt64(); return(subExpressions[expressionID]); } }
/// <summary> /// Parses a function as a string into an expression tree. /// </summary> /// <param name="function">The string to parse.</param> /// <returns>The expression tree representing the function.</returns> public Expression <Func <double, double> > ParseFunctionAsExpressionTree(string function) { function = Regex.Replace(function, @"({|\[)", "(");//Replace all non-paren grouping symbols with parens function = Regex.Replace(function, @"(}|\])", ")"); function = Regex.Replace(function, @"\s", ""); subExpressions.Clear(); subExpressions.Add(x); subExpressions.Add(Expression.Constant(Math.E)); subExpressions.Add(Expression.Constant(Math.PI)); function = function.Replace(nameof(x), "{0}"); function = function.Replace("e", "{1}"); function = function.Replace("pi", "{2}"); function = Regex.Replace(function, @"(?<number>[0-9]+){", @"${number}*{"); // Handles expressions such as 5x and changes it to 5 * x if (function[0] == '-') { if (function[1] != '{') // If we are not negating a subexpression { using (TypeTextReader reader = new TypeTextReader(new StringReader(function.Substring(1)))) { var val = reader.ReadDouble(); var exprID = subExpressions.Count; subExpressions.Add(Expression.Constant(-val)); var length = function.Length - reader.BaseReader.ReadToEnd().Length; function = function.Replace(function.Substring(0, length), "{" + exprID + "}"); } } else { using (TypeTextReader reader = new TypeTextReader(new StringReader(function.Substring(1)))) { var subExprId = (int)reader.ReadInt64(); var exprID = subExpressions.Count; subExpressions.Add(Expression.Negate(subExpressions[subExprId])); var length = function.Length - reader.BaseReader.ReadToEnd().Length; function = function.Replace(function.Substring(0, length), "{" + exprID + "}"); } } } var lambda = Expression.Lambda <Func <double, double> >(ParseEquation(function), x); return(lambda); }
private void CreateExpressions(ref string equation, params char[] operations) { var index = 0; while ((index = equation.IndexOfAny(operations)) != -1)// While one of the operations can still be performed { var previous = equation[index - 1]; Expression left, right; int startPlaceholder, endPlaceholder; if (previous == '}') { var openingIndex = equation.Substring(0, index).LastIndexOf('{'); var exprID = Int32.Parse(equation.Substring(openingIndex + 1, (index - 1) - (openingIndex + 1))); left = subExpressions[exprID]; startPlaceholder = openingIndex; } else { var substr = new string(equation.Substring(0, index).Reverse().ToArray()); var leftVal = Double.NaN; var leftBuilder = new StringBuilder(); using (StringReader reader = new StringReader(substr)) { var val = 0; while ((val = reader.Read()) != -1) { var ch = (char)val; if (Char.IsDigit(ch)) { leftBuilder.Append(ch); } else { break; } } leftVal = Double.Parse(new string(leftBuilder.ToString().Reverse().ToArray())); } left = Expression.Constant(leftVal); startPlaceholder = equation.Substring(0, index).LastIndexOf(leftVal.ToString()); } var next = equation[index + 1]; if (next == '{') { var closingIndex = equation.Substring(index).IndexOf('}'); int exprID; using (TypeTextReader reader = new TypeTextReader(new StringReader(equation.Substring(index + 2)))) { exprID = (int)reader.ReadInt64(); } right = subExpressions[exprID]; endPlaceholder = closingIndex + index + 1; } else { using (TypeTextReader reader = new TypeTextReader(new StringReader(equation.Substring(index + 1)))) { var exp = reader.ReadDouble(); right = Expression.Constant(exp); endPlaceholder = equation.Length - reader.BaseReader.ReadToEnd().Length; } } var op = equation[index]; equation = equation.Replace(equation.Substring(startPlaceholder, endPlaceholder - startPlaceholder), "{" + subExpressions.Count.ToString() + "}"); subExpressions.Add(Expression.MakeBinary(ExpTypeFromChar(op), left, right)); } }