/*
         * Factorial
         */
        private JongFunction parse_factorial() //throws JongError
        {
            JongFunction ans = parse_unaryminus();

            while (token.Equals("!"))
            {
                //getToken();
                String newFncName = token; getToken(); ans = new JongFuncSpecific(newFncName, ans);

                //Commented out by Ant: ans = new Factorial(ans);
            }

            return(ans);
        }
        /*
         * add or subtract
         */
        private JongFunction parse_addsubtract() //throws JongError
        {
            JongFunction ans = parse_multiplydivide();

            while (token.Equals("+") ||
                   token.Equals("-"))
            {
                String newFncName = token; getToken(); ans = new JongFuncSpecific(newFncName, ans, parse_multiplydivide());

                //Commented out by Ant: if      (token.Equals("+")) {getToken(); ans = new Add(ans, parse_multiplydivide());}
                //Commented out by Ant: else if (token.Equals("-")) {getToken(); ans = new Subtract(ans, parse_multiplydivide());}
            }

            return(ans);
        }
        /*
         * multiply, divide, modulus
         */
        private JongFunction parse_multiplydivide() //throws JongError
        {
            JongFunction ans = parse_pow();

            while (token.Equals("*") ||
                   token.Equals("/") ||
                   token.Equals("%") ||
                   token.Equals("||"))
            {
                String newFncName = token; getToken(); ans = new JongFuncSpecific(newFncName, ans, parse_pow());

                //Commented out by Ant: if      (token.Equals("*")) {getToken(); ans = new Multiply(ans, parse_pow());}
                //Commented out by Ant: else if (token.Equals("/")) {getToken(); ans = new Divide(ans, parse_pow());}
                //Commented out by Ant: else if (token.Equals("%")) {getToken(); ans = new Modulus(ans, parse_pow());}
                //Commented out by Ant: else if (token.Equals("||")) {getToken(); ans = new Xor(ans, parse_pow());}
            }

            return(ans);
        }
        /*
         * conditional operators and bitshift
         */
        private JongFunction parse_conditions() //throws JongError
        {
            JongFunction ans = parse_comparison();

            while (token.Equals("&") ||
                   token.Equals("|") ||
                   token.Equals("<<") ||
                   token.Equals(">>"))
            {
                String newFncName = token; getToken(); ans = new JongFuncSpecific(newFncName, ans, parse_comparison());

                //Commented out by Ant:            if      (token.Equals("&")) {getToken(); ans = new And(ans, parse_comparison());}
                //Commented out by Ant:             else if (token.Equals("|")) {getToken(); ans = new Or(ans, parse_comparison());}
                //Commented out by Ant: else if (token.Equals("<<")) {getToken(); ans = new Bitshiftleft(ans, parse_comparison());}
                //Commented out by Ant: else if (token.Equals(">>")) {getToken(); ans = new Bitshiftright(ans, parse_comparison());}
            }

            return(ans);
        }
        /*
         * comparison operators
         */
        private JongFunction parse_comparison() //throws JongError
        {
            JongFunction ans = parse_addsubtract();

            while (token.Equals("=") ||
                   token.Equals("<>") ||
                   token.Equals("<") ||
                   token.Equals(">") ||
                   token.Equals("<=") ||
                   token.Equals(">="))
            {
                String newFncName = token; getToken(); ans = new JongFuncSpecific(newFncName, ans, parse_addsubtract());

                //Commented out by Ant: if      (token.Equals("="))  {getToken(); ans = new Equal(ans, parse_addsubtract());}
                //Commented out by Ant: else if (token.Equals("<>")) {getToken(); ans = new Unequal(ans, parse_addsubtract());}
                //Commented out by Ant: else if (token.Equals("<"))  {getToken(); ans = new Smaller(ans, parse_addsubtract());}
                //Commented out by Ant: else if (token.Equals(">"))  {getToken(); ans = new Larger(ans, parse_addsubtract());}
                //Commented out by Ant: else if (token.Equals("<=")) {getToken(); ans = new Smallereq(ans, parse_addsubtract());}
                //Commented out by Ant: else if (token.Equals(">=")) {getToken(); ans = new Largereq(ans, parse_addsubtract());}
            }

            return(ans);
        }
        /*
         * functions
         */
        private JongFunction parse_function() //throws JongError
        {
            JongFunction ans;

            if (token_type == TOKENTYPE.FUNCTION)
            {
                String fn_name = token;     //.ToUpper();

                getToken();

                // parse the parentheses and parameters of the function
                List <JongFunction> values = new List <JongFunction>();
                if (token.Equals("("))
                {
                    getToken();
                    values.Add(parse_conditions());

                    // parse a list with parameters
                    while (token.Equals(","))
                    {
                        getToken();
                        values.Add(parse_conditions());
                    }

                    if (!token.Equals(")"))
                    {
                        throw new JongError(3, row(), col());
                    }
                    getToken();

                    //                // arithmetic functions
                    //
                    //                List<String> oneArgFuncNames = new ArrayList<String>();
                    //
                    //                oneArgFuncNames.Add("ABS");	//)      ans = new Abs();
                    //                //
                    //                oneArgFuncNames.Add("CUBE");	//)     ans = new Cube();
                    //                oneArgFuncNames.Add("EXP");	//)      ans = new Exp();
                    //                oneArgFuncNames.Add("LOG");	//)      ans = new Log();
                    //                oneArgFuncNames.Add("LOG10");	//)    ans = new Log10();
                    //                oneArgFuncNames.Add("POW");	//)      ans = new Pow();
                    //                oneArgFuncNames.Add("SIGN");	//)     ans = new Sign();
                    //                oneArgFuncNames.Add("SQRT");	//)     ans = new Sqrt();
                    //                oneArgFuncNames.Add("SQUARE");	//)   ans = new Square();
                    //
                    //                                // probabiliy functions
                    //                oneArgFuncNames.Add("FACTORIAL");	//)ans = new Factorial();
                    //
                    //                                // statistical functions
                    //                oneArgFuncNames.Add("AVG");	//)      ans = new Avg();
                    //                oneArgFuncNames.Add("MAX");	//)      ans = new Max();
                    //                oneArgFuncNames.Add("MEDIAN");	//)   ans = new Median();
                    //                oneArgFuncNames.Add("MIN");	//)      ans = new Min();
                    //                oneArgFuncNames.Add("PROD");	//)     ans = new Prod();
                    //                oneArgFuncNames.Add("STD");	//)      ans = new Std();
                    //                oneArgFuncNames.Add("SUM");	//)      ans = new Sum();
                    //                oneArgFuncNames.Add("VAR");	//)      ans = new Var();
                    //
                    //                                // trigonometric functions
                    //                oneArgFuncNames.Add("SIN");	//)      ans = new Sin();
                    //                oneArgFuncNames.Add("COS");	//)      ans = new Cos();
                    //                oneArgFuncNames.Add("TAN");	//)      ans = new Tan();
                    //                oneArgFuncNames.Add("ASIN");	//)     ans = new Asin();
                    //                oneArgFuncNames.Add("ACOS");	//)     ans = new Acos();
                    //                oneArgFuncNames.Add("ATAN");	//)     ans = new Atan();
                    //                oneArgFuncNames.Add("ATAN2");	//)    ans = new Atan2();

                    bool   bFound = false;
                    String sFound = "";

                    bFound = _checkModelName.CheckModelName(fn_name, "");
                    if (bFound)
                    {
                        sFound = fn_name;
                    }

                    //                for (String knownName : oneArgFuncNames)
                    //                {
                    //                  if (fn_name.Equals(knownName))
                    //                  {
                    //                      sFound=fn_name;
                    //                      bFound = true;
                    //                      break;
                    //                  }
                    //                }

                    //Commented out by Ant:
                    //                if      (fn_name.Equals("ABS"))      ans = new Abs();
                    //
                    //                else if (fn_name.Equals("CUBE"))     ans = new Cube();
                    //                else if (fn_name.Equals("EXP"))      ans = new Exp();
                    //                else if (fn_name.Equals("LOG"))      ans = new Log();
                    //                else if (fn_name.Equals("LOG10"))    ans = new Log10();
                    //                else if (fn_name.Equals("POW"))      ans = new Pow();
                    //                else if (fn_name.Equals("SIGN"))     ans = new Sign();
                    //                else if (fn_name.Equals("SQRT"))     ans = new Sqrt();
                    //                else if (fn_name.Equals("SQUARE"))   ans = new Square();
                    //
                    //                // probabiliy functions
                    //                else if (fn_name.Equals("FACTORIAL"))ans = new Factorial();
                    //
                    //                // statistical functions
                    //                else if (fn_name.Equals("AVG"))      ans = new Avg();
                    //                else if (fn_name.Equals("MAX"))      ans = new Max();
                    //                else if (fn_name.Equals("MEDIAN"))   ans = new Median();
                    //                else if (fn_name.Equals("MIN"))      ans = new Min();
                    //                else if (fn_name.Equals("PROD"))     ans = new Prod();
                    //                else if (fn_name.Equals("STD"))      ans = new Std();
                    //                else if (fn_name.Equals("SUM"))      ans = new Sum();
                    //                else if (fn_name.Equals("VAR"))      ans = new Var();
                    //
                    //                // trigonometric functions
                    //                else if (fn_name.Equals("SIN"))      ans = new Sin();
                    //                else if (fn_name.Equals("COS"))      ans = new Cos();
                    //                else if (fn_name.Equals("TAN"))      ans = new Tan();
                    //                else if (fn_name.Equals("ASIN"))     ans = new Asin();
                    //                else if (fn_name.Equals("ACOS"))     ans = new Acos();
                    //                else if (fn_name.Equals("ATAN"))     ans = new Atan();
                    //                else if (fn_name.Equals("ATAN2"))    ans = new Atan2();

                    if (bFound)
                    {
                        ans = new JongFuncSpecific(sFound);
                    }
                    else if (functionlist.ContainsKey(fn_name))
                    {
                        // it is an assigned function
                        ans = new JongFunctionGet(functionlist, fn_name);
                    }
                    else
                    {
                        // unknown function
                        throw new JongError(102, fn_name, row(), col());
                    }

                    // apply the parameter values to the found function
                    ans.set(values);

                    return(ans);
                }
                else
                {
                    throw new JongError(3, row(), col());
                }
            }

            return(parse_parentheses());
        }