Regex para correspondência de funções e captura de argumentos

Eu estou trabalhando em uma calculadora e leva expressões string e avalia-os. Eu tenho uma função que procura a expressão para funções matemáticas usando Regex, recupera os argumentos, procura o nome da função e avalia-o. O que estou tendo problema é que eu só posso fazer isso se eu sei quantos argumentos haverá, não consigo acertar o Regex. E se eu apenas dividir o conteúdo do( e) personagens pelo, caractere, então eu não posso ter outras chamadas de função nesse argumento.

Aqui está o padrão de correspondência de funções:\b([a-z][a-z0-9_]*)\((..*)\)\b

Ele só funciona com um argumento, posso criar um grupo para cada argumento excluindo aqueles dentro de funções aninhadas? Por exemplo, corresponderia:func1(2 * 7, func2(3, 5)) e crie grupos de captura para:2 * 7 efunc2(3, 5)

Aqui a função que estou usando para avaliar a expressão:

    /// <summary>
    /// Attempts to evaluate and store the result of the given mathematical expression.
    /// </summary>
    public static bool Evaluate(string expr, ref double result)
    {
        expr = expr.ToLower();

        try
        {
            // Matches for result identifiers, constants/variables objects, and functions.
            MatchCollection results = Calculator.PatternResult.Matches(expr);
            MatchCollection objs = Calculator.PatternObjId.Matches(expr);
            MatchCollection funcs = Calculator.PatternFunc.Matches(expr);

            // Parse the expression for functions.
            foreach (Match match in funcs)
            {
                System.Windows.Forms.MessageBox.Show("Function found. - " + match.Groups[1].Value + "(" + match.Groups[2].Value + ")");

                int argCount = 0;
                List<string> args = new List<string>();
                List<double> argVals = new List<double>();
                string funcName = match.Groups[1].Value;

                // Ensure the function exists.
                if (_Functions.ContainsKey(funcName)) {
                    argCount = _Functions[funcName].ArgCount;
                } else {
                    Error("The function '"+funcName+"' does not exist.");
                    return false;
                }

                // Create the pattern for matching arguments.
                string argPattTmp = funcName + "\\(\\s*";

                for (int i = 0; i < argCount; ++i)
                    argPattTmp += "(..*)" + ((i == argCount - 1) ? ",":"") + "\\s*";
                argPattTmp += "\\)";

                // Get all of the argument strings.
                Regex argPatt = new Regex(argPattTmp);

                // Evaluate and store all argument values.
                foreach (Group argMatch in argPatt.Matches(match.Value.Trim())[0].Groups)
                {
                    string arg = argMatch.Value.Trim();
                    System.Windows.Forms.MessageBox.Show(arg);

                    if (arg.Length > 0)
                    {
                        double argVal = 0;

                        // Check if the argument is a double or expression.
                        try {
                            argVal = Convert.ToDouble(arg);
                        } catch {
                            // Attempt to evaluate the arguments expression.
                            System.Windows.Forms.MessageBox.Show("Argument is an expression: " + arg);

                            if (!Evaluate(arg, ref argVal)) {
                                Error("Invalid arguments were passed to the function '" + funcName + "'.");
                                return false;
                            }
                        }

                        // Store the value of the argument.
                        System.Windows.Forms.MessageBox.Show("ArgVal = " + argVal.ToString());
                        argVals.Add(argVal);
                    }
                    else
                    {
                        Error("Invalid arguments were passed to the function '" + funcName + "'.");
                        return false;
                    }
                }

                // Parse the function and replace with the result.
                double funcResult = RunFunction(funcName, argVals.ToArray());
                expr = new Regex("\\b"+match.Value+"\\b").Replace(expr, funcResult.ToString());
            }

            // Final evaluation.
            result = Program.Scripting.Eval(expr);
        }
        catch (Exception ex)
        {
            Error(ex.Message);
            return false;
        }

        return true;
    }

    ////////////////////////////////// ---- PATTERNS ---- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    /// <summary>
    /// The pattern used for function calls.
    /// </summary>
    public static Regex PatternFunc = new Regex(@"([a-z][a-z0-9_]*)\((..*)\)");

Como você pode ver, há uma tentativa muito ruim de construir um Regex para corresponder aos argumentos. Não funciona

Tudo o que estou tentando fazer é extrair2 * 7 efunc2(3, 5) da expressãofunc1(2 * 7, func2(3, 5)) mas deve funcionar para funções com diferentes contagens de argumentos também. Se existe uma maneira de fazer isso sem usar o Regex, isso também é bom.

questionAnswers(5)

yourAnswerToTheQuestion