/// <summary> /// Static constructor that creates MathFuncCodeGenerator object and generate C# code of input math expression. /// </summary> /// <param name="functionText">Text of math expression</param> public static MathFuncCodeGenerator Generate(string functionText) { MathFuncCodeGenerator result = new MathFuncCodeGenerator(functionText); result.Parse(); return(result); }
private void Build_Click(object sender, EventArgs e) { if (Func_box.Text != null) { Func_box.Text = Func_box.Text.Replace(" ", ""); } if (string.IsNullOrEmpty(Func_box.Text)) { MessageBox.Show("Не задана функция графика"); return; } // Code generation of math function MathFuncCodeGenerator generatedFuncCode = MathFuncCodeGenerator.Generate(Func_box.Text); if (string.IsNullOrEmpty(generatedFuncCode.Error)) { FuncCode_box.Text = "Код функции : " + generatedFuncCode.OutputText; } else { MessageBox.Show("Ошибка : " + generatedFuncCode.Error); return; } // Compile (with reflection) method with generated math function CompiledMathFunction compiledMathFunction = MathFuncCodeCompiler.CompileMathFuction(generatedFuncCode.OutputText); if (!string.IsNullOrWhiteSpace(compiledMathFunction.Error)) { FuncCode_box.Text = $"{FuncCode_box.Text}\nВозникли ошибки компиляции: {compiledMathFunction.Error}"; return; } ChartOptions chartOptions = AnalyzeChartInputParametersAndCookChartOptions(Xmin_box.Text, Xmax_box.Text, Ymin_box.Text, Ymax_box.Text); if (chartOptions.Errors.Count > 0) { MessageBox.Show("Обнаружны ошибки задания диапазона: " + string.Join("! ", chartOptions.Errors)); return; } // Create ChartWindow form ChartWindow f = new ChartWindow(); f.InitializeChart(Func_box.Text, chartOptions, compiledMathFunction.Func); f.Show(); }
// "wrapper" parameter should contains "{0}" that will be replaced with generated expression code private static MathExpression NestedExpression(string mathFunc, int start, char openChar, char closeChar, string errSnippet, string wrapper) { if (mathFunc[start] == openChar) { int pos = 1; int openedCount = 1; while (openedCount > 0 && start + pos < mathFunc.Length) { if (mathFunc[start + pos] == openChar) { openedCount++; } else if (mathFunc[start + pos] == closeChar) { openedCount--; } pos++; } if (openedCount > 0) { return new MathExpression() { Error = $"Незакрытые {errSnippet} скобки в выражении \"{mathFunc}\" на позиции {start}" } } ; else { if (pos == 2) { return new MathExpression() { Error = $"Пустые {errSnippet} скобки в выражении \"{mathFunc}\" на позиции {start}" } } ; // When we found some expression in consistency (open and close) parentheses/brackets - create recursively and try to parse math expression in parentheses/brackets MathFuncCodeGenerator nestedExpression = MathFuncCodeGenerator.Generate(mathFunc.Substring(start + 1, pos - 2)); // If parsing of expression in parentheses/brackets is failed - return error feedback if (!string.IsNullOrEmpty(nestedExpression.Error)) { return new MathExpression() { Error = nestedExpression.Error } } ; // If expression in parentheses/brackets is parsed with success - return generated code recursively (this allows parsing of any nesting levels) return(new MathExpression() { Type = ExpressionType.Brackets, Position = start, Length = pos, Original = mathFunc.Substring(start, pos), Replaced = string.Format(wrapper, nestedExpression.OutputText) }); } } return(null); }
public static MathExpression Function(string mathFunc, int start) { string t = mathFunc.Substring(start, mathFunc.Length - start); Match m = FunctionRegex.Match(t); if (m.Success && Functions.Get.ContainsKey(m.Groups[1].Value)) { int cpos = start + m.Value.Length; int countParentheses = 1; int countBrackets = 0; StringBuilder temppar = new StringBuilder(); List <string> parameters = new List <string>(); bool isFuncParenthesesClosed = true; while (isFuncParenthesesClosed & cpos < mathFunc.Length) { if (mathFunc[cpos] == '(') { countParentheses++; } if (mathFunc[cpos] == ')') { countParentheses--; } if (mathFunc[cpos] == '[') { countBrackets++; } if (mathFunc[cpos] == ']') { countBrackets--; } if (countBrackets < 0) { return new MathExpression() { Error = $"Обнаружена лишняя закрывающая квадратная скобка в параметрах функции {m.Groups[1].Value} в выражении: {mathFunc} на позиции {start}" } } ; if (countBrackets == 0 && ((mathFunc[cpos] == ',' && countParentheses == 1) || (mathFunc[cpos] == ')' && countParentheses == 0))) // Condition is true when parameter' separator (coma out of parentheses/brackets) is detected { parameters.Add(temppar.ToString()); temppar = new StringBuilder(); } else { temppar.Append(mathFunc[cpos]); } if (countParentheses == 0 && countBrackets == 0) { isFuncParenthesesClosed = false; } cpos++; } if (isFuncParenthesesClosed) { if (countBrackets == 0) { return new MathExpression() { Error = $"Обнаружена незарытая круглая скобка в параметрах функции {m.Groups[1].Value} в выражении: {mathFunc} на позиции {start}" } } ; else { return new MathExpression() { Error = $@"Обнаружена незарытая круглая скобка в параметрах функции {m.Groups[1].Value} в выражении: {mathFunc} на позиции {start}! Возможно некорректное использование квадратных скобок [] (countBrackets={countBrackets})" } }; } if (parameters.Count == 1 && parameters[0].Length == 0) { return new MathExpression() { Error = $"Непонятный вызов ошибки пустой функции (константы) {m.Groups[1].Value}() в выражении: {mathFunc} на позиции {start}" } } ; if (parameters.Count != Functions.Get[m.Groups[1].Value].ParametersNumber) { List <string> tp = new List <string>(); for (int i = 0; i < parameters.Count; i++) { tp.Add($"p{i + 1}=\"{parameters[i]}\""); } return(new MathExpression() { Error = $@"Обнаружено неверное количество указаных параметров в функции {m.Groups[1].Value} в выражении {mathFunc} на позиции{start}. Функция предполагает параметров - {Functions.Get[m.Groups[1].Value].ParametersNumber}, обнаружено {parameters.Count}. Обнаружены следующие параметры: {string.Join(",", tp)}" }); } // Parse recursively every found parameter List <string> parsedParameters = new List <string>(); foreach (string p in parameters) { MathFuncCodeGenerator sp = MathFuncCodeGenerator.Generate(p); if (!string.IsNullOrEmpty(sp.Error)) { return new MathExpression() { Error = sp.Error } } ; // Error feedback else { parsedParameters.Add(sp.OutputText); } } return(new MathExpression() { Type = ExpressionType.Function, Position = start, Length = cpos - start, Original = mathFunc.Substring(start, cpos - start), Replaced = $"{Functions.Get[m.Groups[1].Value].Name}({string.Join(",", parsedParameters)})" }); } return(null); }