Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        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();
        }
Esempio n. 3
0
        // "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);
        }
Esempio n. 4
0
        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);
        }