//---------------------------------------------------------------------------
 private bool changeN(char c, NKT kt)
 {
     if (c == '(')
     {
         kt.setNkt(kt.getNkt() + 1);
         return(true);
     }
     if (c == ')')
     {
         kt.setNkt(kt.getNkt() - 1);
         return(true);
     }
     return(false);
 }
        //---------------------------------------------------------------------------
        //---------------------------------------------------------------------------
        private String pDivFlip(String q)
        {
            int i;
            NKT kt = new NKT(0);

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }

                if ((kt.getNkt() == 0) && (q[i] == '/'))
                {
                    q = q.Substring(0, i) + "*" + q.Substring(i + 1);
                    continue;
                }
            }
            return(q);
        }
        //---------------------------------------------------------------------------

        //---------------------------------------------------------------------------
        private int anzahlParameter(String q)
        {
            int i, Anzahl;
            NKT kt = new NKT(0);

            Anzahl = 0;

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                if ((kt.getNkt() == 0) && (q[i] == ','))
                {
                    Anzahl++;
                }
            }

            return(Anzahl);
        }
        //---------------------------------------------------------------------------

        /**
         * Dies ist die eigentliche Parser - Funktion. Hier wird Funktion analysiert
         * und geparst und in eine Auswertbare Form übertragen (Item in Liste)
         * hier werden keine Funktionswerte bestimmt, nur der
         * Funktionstext geparst
         * Die Vorgehnsweise ist rekursivin pr wird or an
         * verschiedenen Stellen neu aufgerufen
         */
        private int pr(String q)
        {
            // Vorbereitungen
            int    i, error, anzahl;
            String ca, cb, c1 = "", c2 = "", s;
            Double param;
            // NKT bedeutet nKlammertiefe
            NKT    kt  = new NKT(0);
            IsZahl isz = new IsZahl(false);

            q = q.Trim();

            // wenn leer, dann gibts nichts zu parsen (Fehler)
            if (String.IsNullOrEmpty(q))
            {
                return(21);
            }


            // Kann ein x sein
            if (q.ToUpper() == "X")
            {
                return(addItem(0, 0.0, -1, "x"));
            }
            // kann ein pi sein
            if (q.ToUpper() == "PI")
            {
                try
                {
                    param = Math.PI;
                }
                catch (Exception ex)
                {
                    return(1);
                }
                return(addItem(3, param, -1, "Pi"));
            }
            // kann die Eulerzahl sein
            if (q.ToUpper() == "E")
            {
                try
                {
                    param = Math.E;
                }
                catch (Exception ex)
                {
                    return(1);
                }
                return(addItem(3, param, -1, "e"));
            }

            // Leerzeichen eleminieren
            s = "";
            for (i = 0; i < q.Length; i++)
            {
                if (q[i] != ' ')
                {
                    s = s + q[i];
                }
            }
            q = s;

            // zuviele Vorzeichen reduzieren auf das
            // eigentliche Vorzeichen
            while ((q.IndexOf("++") > 0) || (q.IndexOf("+-") > 0) ||
                   (q.IndexOf("-+") > 0) || (q.IndexOf("--") > 0))
            {
                if (q.IndexOf("++") > 0)
                {
                    q = q.Substring(0, q.IndexOf("++") + 1)
                        + q.Substring(q.IndexOf("++") + 2);
                }
                if (q.IndexOf("-+") > 0)
                {
                    q = q.Substring(0, q.IndexOf("-+") + 1)
                        + q.Substring(q.IndexOf("-+") + 2);
                }
                if (q.IndexOf("+-") > 0)
                {
                    q = q.Substring(0, q.IndexOf("+-"))
                        + q.Substring(q.IndexOf("+-") + 1);
                }
                if (q.IndexOf("--") > 0)
                {
                    q = q.Substring(0, q.IndexOf("--"))
                        + "+" + q.Substring(q.IndexOf("--") + 2);
                }
            }

            // Pluszeichen am Anfang hat keine Bedeutung
            if (q[0] == '+')
            {
                return(pr(q.Substring(1)));
            }

            // Minuszeichen - den positiven teil analysieren und
            // zum Schluss mal (-1.0) nehmen
            if (q[0] == '-')
            {
                q = q.Substring(1);

                q = pMinusFlip(q);

                addItem(1, 0.0, -1, "(");
                // Rekursives Weitergehen nach Innen
                error = pr(q);
                if (error != 0)
                {
                    return(error);
                }
                addItem(2, 0.0, -1, ")");
                addItem(4, 0.0, 9, "*(-1.0)");
                return(0);
            }

            // Mal und geteilt am Anfang ist Boedsinn - Fehler
            // '**' auch enthalten
            if ((q[0] == '*') ||
                (q[0] == '/'))
            {
                // kein mathematischer Ausdruck
                return(3);
            }

            // Feststellen, ob es einfach nur ein Zahlenwert ist,
            // kein mathematischer Ausdruck (Term)
            error = pIsZahl(q, isz);
            if (error != 0)
            {
                return(error);
            }
            else
            {
                if (isz.getIsZahl())
                {
                    // Punkt muss durch Komma ersetzt werden
                    // q = changePointToKomma( q );

                    try
                    {
                        // versuchen, aus dem Zahlenwert ein Double zu machen

                        param = Double.Parse(q, CultureInfo.InvariantCulture);
                    }
                    catch (Exception ex)
                    {
                        return(1);
                    }
                    addItem(3, param, -1, q);
                    return(0);
                }
            }

            // inn kt werden die Anzahl der offenen Klammer gezaehlt
            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                // nur wenn kt gleich 0 ist, dann laesst sich Term
                // weiter analysieren in binäre oder mono - Operationen
                // erst + - Zeichen (Punktrechnugn vor Strichrechnung)
                // von Aussen nach Innen !!
                if ((kt.getNkt() == 0) && (q[i] == '+') &&
                    (q[i - 1] != '*') &&
                    (q[i - 1] != '/'))
                {
                    if (i == 0)
                    {
                        return(3);
                    }
                    ca = q.Substring(0, i);
                    cb = q.Substring(i + 1);
                    if (String.IsNullOrEmpty(cb.Trim()))
                    {
                        // kein mathematischer Ausdruck
                        return(3);
                    }
                    addItem(1, 0.0, -1, "(");
                    // Rekursives Weitergehen nach Innen
                    error = pr(ca);
                    if (error != 0)
                    {
                        return(error);
                    }
                    // Rekursives Weitergehen nach Innen
                    error = pr(cb);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 0, "+");
                    return(0);
                }
            }
            if (kt.getNkt() != 0)
            {
                return(2);
            }

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                // - Zeichen wwie + Zeichen
                if ((kt.getNkt() == 0) && (q[i] == '-') &&
                    (q[i - 1] != '*') &&
                    (q[i - 1] != '/'))
                {
                    if (i == 0)
                    {
                        return(3);
                    }
                    ca = q.Substring(0, i);
                    cb = q.Substring(i + 1);
                    if (String.IsNullOrEmpty(cb.Trim()))
                    {
                        // kein mathematischer Ausdruck
                        return(3);
                    }
                    cb = pMinusFlip(cb);
                    addItem(1, 0.0, -1, "(");
                    error = pr(ca);
                    if (error != 0)
                    {
                        return(error);
                    }
                    error = pr(cb);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 1, "-");
                    return(0);
                }
            }
            if (kt.getNkt() != 0)
            {
                return(2);
            }

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                // * - Zeichen wie + Zeichen (kein Exponentieren!!)
                if ((kt.getNkt() == 0) && (q[i] == '*') &&
                    ((q.Substring(i, 2)) != "**") &&
                    ((q.Substring(i - 1, 2)) != "**"))
                {
                    if (i == 0)
                    {
                        return(3);
                    }
                    ca = q.Substring(0, i);
                    cb = q.Substring(i + 1);
                    if (String.IsNullOrEmpty(cb.Trim()))
                    {
                        // kein mathematischer Ausdruck
                        return(3);
                    }
                    addItem(1, 0.0, -1, "(");
                    error = pr(ca);
                    if (error != 0)
                    {
                        return(error);
                    }
                    error = pr(cb);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 2, "*");
                    return(0);
                }
            }
            if (kt.getNkt() != 0)
            {
                return(2);
            }

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                // 'geteilt' Zeichen wie + Zeichen
                if ((kt.getNkt() == 0) && (q[i] == '/'))
                {
                    if (i == 0)
                    {
                        return(3);
                    }
                    ca = q.Substring(0, i);
                    cb = q.Substring(i + 1);
                    if (String.IsNullOrEmpty(cb.Trim()))
                    {
                        // kein mathematischer Ausdruck
                        return(3);
                    }

                    cb = pDivFlip(cb);
                    addItem(1, 0.0, -1, "(");
                    error = pr(ca);
                    if (error != 0)
                    {
                        return(error);
                    }
                    error = pr(cb);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 3, "/");
                    return(0);
                }
            }
            if (kt.getNkt() != 0)
            {
                return(2);
            }

            for (i = 0; i < q.Length; i++)
            {
                if (changeN(q[i], kt))
                {
                    continue;
                }
                // Exponentieren wwie + Zeichen
                if ((kt.getNkt() == 0) &&
                    (q.Substring(i, 2) == "**"))
                {
                    if (i == 0)
                    {
                        return(3);
                    }
                    ca = q.Substring(0, i);
                    cb = q.Substring(i + 2);
                    if (String.IsNullOrEmpty(cb.Trim()))
                    {
                        // kein mathematischer Ausdruck
                        return(3);
                    }

                    addItem(1, 0.0, -1, "(");
                    error = pr(ca);
                    if (error != 0)
                    {
                        return(error);
                    }
                    error = pr(cb);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 10, "**");
                    return(0);
                }
            } // for ( i = 1; i<= q.Length(); i++)

            // kann nur eingeklammerter Bereich sein
            if ((q[0] == '(') &&
                (q[q.Length - 1] == ')'))
            {
                ca = q.Substring(1, q.Length - 2);
                if (String.IsNullOrEmpty(ca.Trim()))
                {
                    return(6);
                }
                error = pr(ca);
                if (error != 0)
                {
                    return(error);
                }
                return(0);
            }

            // ab hier kann sich nur noch um Funktion handeln
            if (kt.getNkt() != 0)
            {
                return(2);
            }

            if ((q[q.Length - 1] != ')') ||
                (q.IndexOf('(') < 0))
            {
                return(8);
            }

            ca = q.Substring(q.IndexOf('(') + 1);
            ca = ca.Substring(0, ca.Length - 1);
            if (String.IsNullOrEmpty(ca.Trim()))
            {
                return(6);
            }
            addItem(1, 0.0, -1, "(");
            cb = q.Substring(0, q.IndexOf('('));
            if (String.IsNullOrEmpty(cb.Trim()))
            {
                return(5);
            }
            anzahl = anzahlParameter(ca);
            if (anzahl > 1)
            {
                return(9);
            }
            if (anzahlParameter(ca) == 1)
            { // 2parametrige Funktion
                for (i = 0; i < ca.Length; i++)
                {
                    if (changeN(ca[i], kt))
                    {
                        continue;
                    }
                    if ((kt.getNkt() == 0) && (ca[i] == ','))
                    {
                        c1 = ca.Substring(0, i);
                        c2 = ca.Substring(i + 1);
                        if ((String.IsNullOrEmpty(c1.Trim())) || (String.IsNullOrEmpty(c2.Trim())))
                        {
                            // kein mathematischer Ausdruck
                            return(4);
                        }
                        break;
                    }
                } // for ( i = 1; i<= q.Length(); i++)
                if (kt.getNkt() != 0)
                {
                    return(2);
                }
                if (cb.ToUpper() == "NK")
                { // jedesmal extra, da auch verschachtelte Funtionen möglich sind!
                    error = pr(c1);
                    if (error != 0)
                    {
                        return(error);
                    }
                    error = pr(c2);
                    if (error != 0)
                    {
                        return(error);
                    }
                    addItem(2, 0.0, -1, ")");
                    addItem(4, 0.0, 11, "nk");
                    return(0);
                }

                // Error - unbekannte einparametrige Funktion
                return(10);
            } // if (ca.Pos(",")>0)

            error = pr(ca);
            if (error != 0)
            {
                return(error);
            }
            addItem(2, 0.0, -1, ")");
            if (cb.ToUpper() == "SIN")
            {
                addItem(4, 0.0, 4, "sin");
                return(0);
            }
            else if (cb.ToUpper() == "COS")
            {
                addItem(4, 0.0, 5, "cos");
                return(0);
            }
            else if (cb.ToUpper() == "TAN")
            {
                addItem(4, 0.0, 6, "tan");
                return(0);
            }
            else if (cb.ToUpper() == "E")
            {
                addItem(4, 0.0, 7, "e");
                return(0);
            }
            else if (cb.ToUpper() == "LN")
            {
                addItem(4, 0.0, 8, "ln");
                return(0);
            }
            else if (cb.ToUpper() == "ASIN")
            {
                addItem(4, 0.0, 12, "asin");
                return(0);
            }
            else if (cb.ToUpper() == "ACOS")
            {
                addItem(4, 0.0, 13, "acos");
                return(0);
            }
            else if (cb.ToUpper() == "ATAN")
            {
                addItem(4, 0.0, 14, "atan");
                return(0);
            }

            return(5);
        }