Beispiel #1
0
        private void Level12Assign()
        {
            Level11Or();        // get left value

            if (sp.IsCharMoveOn('='))
            {
                if (SetSymbolValue == null)
                {
                    value = new StringParser.ConvertError("= operator not supported");
                }
                else
                {
                    StringParser.ConvertError err = value as StringParser.ConvertError;

                    string symbolname;

                    if (unaryentrytimes == 1 && lvaluename != null)    // if 1 entry to unary, and symbol value is set, its a current value
                    {
                        symbolname = lvaluename;
                    }
                    else
                    {                                                   // else its an equal without an error but not a symbol, so its not an lvalue
                        value = new StringParser.ConvertError("Lvalue required for = operator");
                        return;
                    }

                    Evaluate(false, false);                             // get next expression

                    if (!InError)
                    {
                        value = SetSymbolValue(symbolname, value);
                    }
                }
            }
        }
Beispiel #2
0
        // for supporting functions..  given a list of types of parameters, collect them, comma separ.
        public List <Object> Parameters(string name, int min, IEvalParaListType [] ptypes)
        {
            List <Object> list = new List <object>();

            for (int n = 0; n < ptypes.Length; n++)
            {
                Object evres = Evaluate(false, false);
                if (InError)
                {
                    return(null);
                }

                if ((ptypes[n] == IEvalParaListType.String && (evres is string)) ||
                    (ptypes[n] == IEvalParaListType.Number && (evres is double || evres is long)) ||
                    (ptypes[n] == IEvalParaListType.NumberOrInteger && (evres is double || evres is long)) ||
                    (ptypes[n] == IEvalParaListType.Integer && (evres is long)) ||
                    (ptypes[n] == IEvalParaListType.IntegerOrString && (evres is string || evres is long)) ||
                    (ptypes[n] == IEvalParaListType.All)
                    )
                {
                    if (ptypes[n] is IEvalParaListType.Number && evres is long)
                    {
                        evres = (double)(long)evres;
                    }

                    list.Add(evres);

                    if (n < ptypes.Length - 1)      // if not maximum point
                    {
                        if (!sp.IsCharMoveOn(','))  // and not comma..
                        {
                            if (list.Count() < min) // ensure minimum
                            {
                                value = new StringParser.ConvertError(name + "() requires " + min + " parameters minimum");
                                return(null);
                            }
                            else
                            {
                                return(list);        // have min, return it
                            }
                        }
                    }
                }
                else
                {
                    value = new StringParser.ConvertError(name + "() type mismatch in parameter " + (n + 1) + " wanted " + ptypes[n].ToString().SplitCapsWord());
                    return(null);
                }
            }

            if (sp.IsChar(','))     // if at max, can't have another
            {
                value = new StringParser.ConvertError(name + "() takes " + ptypes.Length + " parameters maximum");
                return(null);
            }

            return(list);
        }
Beispiel #3
0
        private void Level6Equals()
        {
            Level5GreaterLess();        // get left value

            bool equals = false;

            while (!InError && ((equals = sp.IsString("==")) || sp.IsString("!=")))
            {
                sp.MoveOn(2);

                Object leftside = value;    // remember left side value

                Level5GreaterLess();        // get left value

                if (InError)
                {
                    return;
                }

                bool result;

                if (leftside is string || value is string)
                {
                    if (!(leftside is string) || !(value is string))
                    {
                        value = new StringParser.ConvertError("Cannot mix string and number types in comparisions");
                        return;
                    }
                    else
                    {
                        int cmp = String.Compare(leftside as string, value as string, IgnoreCase, Culture);
                        result = equals ? (cmp == 0) : (cmp != 0);
                    }
                }
                else if (leftside is double || value is double)
                {
                    double l = AsDouble(leftside);
                    double r = AsDouble(value);
                    result = equals ? (l == r) : (l != r);
                }
                else
                {
                    long l = (long)(leftside);
                    long r = (long)(value);
                    result = equals ? (l == r) : (l != r);
                }

                value = result ? (long)1 : (long)0;
            }
        }
Beispiel #4
0
        public Object Functions(string name, IEval evaluator)
        {
            Object ret = BaseFunctions != null?BaseFunctions(name, evaluator) : new StringParser.ConvertError("() not recognised");

            StringParser.ConvertError ce = ret as StringParser.ConvertError;

            if (ce != null && ce.ErrorValue.Contains("() not recognised"))
            {
                if (functions.ContainsKey(name))
                {
                    FuncDef fd = functions[name];

                    bool hasparas = fd.parameters.Length > 0;

                    if (hasparas)
                    {
                        IEvalParaListType[] plist = new IEvalParaListType[fd.parameters.Length];
                        plist = Enumerable.Repeat(IEvalParaListType.All, fd.parameters.Length).ToArray();

                        List <Object> paras = evaluator.Parameters(name, fd.parameters.Length, plist);
                        if (paras == null)              // if error, stop and return error
                        {
                            return(evaluator.Value);
                        }

                        symbols.Push();
                        for (int i = 0; i < fd.parameters.Length; i++)          // add to symbol list on next level the parameter names and values
                        {
                            System.Diagnostics.Debug.WriteLine(symbols.Levels + " " + name + " Push " + fd.parameters[i] + "=" + paras[i]);
                            symbols.Add(fd.parameters[i], paras[i]);
                        }
                    }

                    Eval   evfunc = (Eval)evaluator.Clone();                    // we need a fresh one just to evaluate this, but with the same configuration
                    Object res    = evfunc.Evaluate(fd.funcdef);                // and evaluate

                    if (hasparas)
                    {
                        symbols.Pop();                                          // clear back stack..
                    }
                    return(res);
                }
            }

            return(ret);
        }
Beispiel #5
0
        public Object Evaluate(bool unary, bool checkend)          // Allow control of unary entry and check end on a case by case basis
        {
            System.Diagnostics.Debug.Assert(sp != null);

            unaryentrytimes = 0;

            if (unary)
            {
                Level0Unary();
            }
            else
            {
                Level12Assign();
            }

            if (!InError && checkend && !sp.IsEOL)
            {
                value = new StringParser.ConvertError("Extra characters after expression: " + sp.LineLeft);
            }

            //System.Diagnostics.Debug.WriteLine("Evaluate Value is " + value + " : of type " + value.GetType().Name);
            return(value);
        }
Beispiel #6
0
        private void Level1Not()
        {
            if (sp.IsCharMoveOn('!'))
            {
                Level1Not();       // allow recurse..

                lvaluename = null; // clear symbol name, can't use with !

                if (IsLong)
                {
                    value = ((long)value != 0) ? 0L : 1L;
                }
                else if (!InError)
                {
                    value = new StringParser.ConvertError("! only valid with integers");
                }
            }
            else if (sp.IsCharMoveOn('~'))
            {
                Level1Not();       // allow recurse..

                lvaluename = null; // clear symbol name, can't use with ~

                if (IsLong)
                {
                    value = ~(long)value;
                }
                else if (!InError)
                {
                    value = new StringParser.ConvertError("~ is only valid with integers");
                }
            }
            else
            {
                Level0Unary();
            }
        }
Beispiel #7
0
        private void Level5GreaterLess()
        {
            Level4Shift();        // get left value

            while (!InError && sp.IsCharOneOf("<>"))
            {
                bool left   = sp.GetChar() == '<';
                bool equals = sp.IsCharMoveOn('=');
                sp.SkipSpace();

                Object leftside = value; // remember left side value

                Level4Shift();           // get right side

                if (InError)
                {
                    return;
                }

                bool result;

                if (leftside is string || value is string)
                {
                    if (!(leftside is string) || !(value is string))
                    {
                        value = new StringParser.ConvertError("Cannot mix string and number types in comparisions");
                        return;
                    }
                    else
                    {
                        int cmp = String.Compare(leftside as string, value as string, IgnoreCase, Culture);
                        if (left)
                        {
                            result = equals ? (cmp <= 0) : (cmp < 0);
                        }
                        else
                        {
                            result = equals ? (cmp >= 0) : (cmp > 0);
                        }
                    }
                }
                else if (leftside is double || value is double)
                {
                    double l = AsDouble(leftside);
                    double r = AsDouble(value);

                    if (left)
                    {
                        result = equals ? (l <= r) : (l < r);
                    }
                    else
                    {
                        result = equals ? (l >= r) : (l > r);
                    }
                }
                else
                {
                    long l = (long)(leftside);
                    long r = (long)(value);

                    if (left)
                    {
                        result = equals ? (l <= r) : (l < r);
                    }
                    else
                    {
                        result = equals ? (l >= r) : (l > r);
                    }
                }

                value = result ? (long)1 : (long)0;
            }
        }
Beispiel #8
0
        private void Level3Add()
        {
            Level2Times();        // get left value

            while (!InError && sp.IsCharOneOf("+-"))
            {
                char operation = sp.GetChar(skipspace: true);

                if (IsString && operation == '-')
                {
                    value = new StringParser.ConvertError("- is not supported with strings");
                    return;
                }

                Object leftside = value;            // remember left side value

                Level2Times();                      // get right side

                if (InError)
                {
                    return;
                }

                if (leftside is string && IsString) // two strings, +
                {
                    value = (leftside as string) + (value as string);
                }
                else
                {
                    if (leftside is string || IsString)
                    {
                        value = new StringParser.ConvertError("Cannot mix string and number types");
                        return;
                    }
                    else if (leftside is double || value is double)    // either double, its double
                    {
                        double left  = AsDouble(leftside);
                        double right = AsDouble(value);

                        if (operation == '+')
                        {
                            value = left + right;
                        }
                        else
                        {
                            value = left - right;
                        }
                    }
                    else
                    {
                        long left  = (long)(leftside);
                        long right = (long)(value);

                        if (operation == '+')
                        {
                            value = left + right;
                        }
                        else
                        {
                            value = left - right;
                        }
                    }
                }
            }
        }
Beispiel #9
0
        private void Level2Times()
        {
            Level1Not();        // get left value

            while (!InError && sp.IsCharOneOf("*/%"))
            {
                if (!IsNumeric)
                {
                    value = new StringParser.ConvertError("*/% only valid with numbers");
                    return;
                }

                char operation = sp.GetChar(skipspace: true);

                Object leftside = value;            // remember left side value

                Level1Not();                        // get right side

                if (InError)
                {
                    return;
                }
                else if (!IsNumeric)
                {
                    value = new StringParser.ConvertError("*/% only valid with numbers");
                    return;
                }

                if (leftside is double || value is double)    // either double, its double
                {
                    double left  = AsDouble(leftside);
                    double right = AsDouble(value);

                    if (operation == '*')
                    {
                        value = left * right;
                    }
                    else if (operation == '/')
                    {
                        if (right == 0)
                        {
                            value = new StringParser.ConvertError("Divide by zero");
                            return;
                        }

                        value = left / right;
                    }
                    else
                    {
                        value = new StringParser.ConvertError("Cannot perform modulo with floating point values");
                        return;
                    }
                }
                else
                {
                    long left  = (long)(leftside);
                    long right = (long)(value);

                    if (operation == '*')
                    {
                        value = left * right;
                    }
                    else if (operation == '/')
                    {
                        if (right == 0)
                        {
                            value = new StringParser.ConvertError("Divide by zero");
                            return;
                        }

                        value = left / right;
                    }
                    else
                    {
                        value = left % right;
                    }
                }
            }
        }
Beispiel #10
0
        private void Level0Unary()      // Value left as Error, double, long, string
        {
            unaryentrytimes++;          // counts entry to the unary level.. if 1, and symbolname set, its a symbol def on left side
            lvaluename = null;

            long sign = 0;

            if (sp.IsCharMoveOn('-'))   // space allowed after unary minus plus to entry
            {
                sign = -1;
            }
            else if (sp.IsCharMoveOn('+'))
            {
                sign = 1;
            }

            if (sp.IsCharMoveOn('('))       // ( value )
            {
                value = Evaluate(false, false);

                if (!(value is StringParser.ConvertError) && !sp.IsCharMoveOn(')'))
                {
                    value = new StringParser.ConvertError("Missing ) at end of expression");
                }
            }
            else
            {
                value = sp.ConvertNumberStringSymbolChar(DefaultBase, AllowFP, AllowStrings, ReplaceEscape);

                if (value is StringParser.ConvertSymbol)    // symbol must resolve to a value or Error
                {
                    string symname = (value as StringParser.ConvertSymbol).SymbolValue;

                    if (sp.IsCharMoveOn('('))
                    {
                        if (ReturnFunctionValue != null)
                        {
                            value = ReturnFunctionValue(symname, this);

                            if (!(value is StringParser.ConvertError) && !sp.IsCharMoveOn(')'))         // must be ) terminated
                            {
                                value = new StringParser.ConvertError("Function not terminated with )");
                            }
                        }
                        else
                        {
                            value = new StringParser.ConvertError("Functions not supported");
                        }
                    }
                    else if (ReturnSymbolValue != null)
                    {
                        lvaluename = (sign == 0) ? symname : null;              // pass back symbol name found, only if not signed.
                        value      = ReturnSymbolValue(symname);                // could be Error with symbol value in it.
                    }
                    else
                    {
                        value = new StringParser.ConvertError("Symbols not supported");
                    }
                }
            }

            // value now Error, double, long, string

            if (!(value is StringParser.ConvertError) && sign != 0)      // if not error, and signed
            {
                if (value is double)
                {
                    value = (double)value * sign;
                }
                else if (value is long)
                {
                    value = (long)value * sign;
                }
                else
                {
                    value = new StringParser.ConvertError("Unary +/- not allowed in front of string");
                }
            }
        }
Beispiel #11
0
        private void Level0Unary()      // Value left as Error, double, long, string
        {
            unaryentrytimes++;          // counts entry to the unary level.. if 1, and symbolname set, its a symbol def on left side
            lvaluename = null;

            long sign = 0;

            if (sp.IsCharMoveOn('-'))   // space allowed after unary minus plus to entry
            {
                sign = -1;
            }
            else if (sp.IsCharMoveOn('+'))
            {
                sign = 1;
            }

            if (sp.IsCharMoveOn('('))       // ( value )
            {
                value = Evaluate(false, false);

                if (!(value is StringParser.ConvertError) && !sp.IsCharMoveOn(')'))
                {
                    value = new StringParser.ConvertError("Missing ) at end of expression");
                }
            }
            else
            {
                value = sp.ConvertNumberStringSymbolChar(DefaultBase, AllowFP, AllowStrings, ReplaceEscape, AllowMemberSymbol);

                if (value is StringParser.ConvertSymbol)    // symbol must resolve to a value or Error
                {
                    string symname = (value as StringParser.ConvertSymbol).SymbolValue;

                    if (sp.IsCharMoveOn('('))
                    {
                        if (ReturnFunctionValue != null)
                        {
                            value = ReturnFunctionValue(symname, this);

                            if (!(value is StringParser.ConvertError) && !sp.IsCharMoveOn(')'))         // must be ) terminated
                            {
                                value = new StringParser.ConvertError("Function not terminated with )");
                            }
                        }
                        else
                        {
                            value = new StringParser.ConvertError("Functions not supported");
                        }
                    }
                    else if (ReturnSymbolValue == null)
                    {
                        value = new StringParser.ConvertError("Symbols not supported");
                    }
                    else
                    {
                        while (AllowArrays && sp.IsCharMoveOn('[')) // is it an array symbol..
                        {
                            value = Evaluate(false, false);         // get [] expression

                            if (value is StringParser.ConvertError) // see what we have back and generate array
                            {
                                break;
                            }
                            if (value is long)
                            {
                                symname += $"[{((long)value).ToStringInvariant()}]";
                            }
                            else if (value is double)
                            {
                                value = new StringParser.ConvertError("Cannot use floating point value as array index");
                                break;
                            }
                            else
                            {
                                symname += $"[{((string)value).AlwaysQuoteString()}]";
                            }

                            if (!sp.IsCharMoveOn(']', false))         // must be ] terminated
                            {
                                value = new StringParser.ConvertError("Array not terminated with ]");
                                break;
                            }

                            if (!sp.IsLetterDigitUnderscoreMember())        // if no following chars, we are done
                            {
                                break;
                            }

                            string moresym;         // more symbol text beyond it

                            if (AllowMemberSymbol)
                            {
                                moresym = sp.NextWord((c) => { return(char.IsLetterOrDigit(c) || c == '_' || c == '.'); });
                            }
                            else
                            {
                                moresym = sp.NextWord((c) => { return(char.IsLetterOrDigit(c) || c == '_'); });
                            }

                            symname += moresym;     // add on
                        }

                        if (!(value is StringParser.ConvertError))      // if not in error, see if symbols is there
                        {
                            lvaluename = (sign == 0) ? symname : null;  // pass back symbol name found, only if not signed.
                            value      = ReturnSymbolValue(symname);    // could be Error with symbol value in it.
                        }
                    }
                }
            }

            // value now Error, double, long, string

            if (!(value is StringParser.ConvertError) && sign != 0)      // if not error, and signed
            {
                if (value is double)
                {
                    value = (double)value * sign;
                }
                else if (value is long)
                {
                    value = (long)value * sign;
                }
                else
                {
                    value = new StringParser.ConvertError("Unary +/- not allowed in front of string");
                }
            }

            if (Fake)       // if we are faking the eval, return 1L long as the default output.
            {
                value = 1L;
            }
        }