예제 #1
0
        public Token(TokenType type, string text, Value value)
        {
            _type = type;
            _text = text;
            _value = value;

            Initialize();
        }
예제 #2
0
        public Value Subtract(Value right)
        {
            if ((IsFractional && right.IsFractional)
                || (IsFractional && right.IsInteger)
                || (IsInteger && right.IsFractional))
            {
                Value ret = Clone();
                if (!ret.IsFractional) ret._format = right._format;
                decimal scale = ret.FindCommonDenom(right._denom);
                ret._num = Math.Round(ret._num - right._num * scale);
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            if (_format == ValueFormat.Date)
            {
                decimal result = _decValue - right._decValue;
                ValueFormat fmt = ValueFormat.Date;
                if (right._format == ValueFormat.Date) fmt = ValueFormat.TimeSpan;
                return new Value(result, fmt);
            }

            return new Value(_decValue - right._decValue, DecideFormat(_format, right._format));
        }
예제 #3
0
 public Value ShiftRight(Value right)
 {
     return new Value(Convert.ToDecimal(Convert.ToInt32(_decValue) >> Convert.ToInt32(right._decValue)), DecideFormat(_format, right._format));
 }
예제 #4
0
        public Value Power(Value right)
        {
            // When a value is being raised to the power of a fraction, don't keep it as a fraction.
            // Exponent value must be integer in order to stay a fraction.

            if (IsFractional && right.IsInteger)
            {
                Value ret = Clone();
                ret._num = Math.Round(Convert.ToDecimal(Math.Pow(Convert.ToDouble(ret._num), Convert.ToDouble(right._decValue))));
                ret._denom = Math.Round(Convert.ToDecimal(Math.Pow(Convert.ToDouble(ret._denom), Convert.ToDouble(right._decValue))));
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            //if (_format == ValueFormat.Date || right._format == ValueFormat.Date) throw new Exception("Exponent cannot be used with dates.");

            return new Value(Convert.ToDecimal(Math.Pow(Convert.ToDouble(_decValue), Convert.ToDouble(right._decValue))), DecideFormat(_format, right._format));
        }
예제 #5
0
        public Value Multiply(Value right)
        {
            if ((IsFractional && right.IsFractional)
                || (IsFractional && right.IsInteger)
                || (IsInteger && right.IsFractional))
            {
                Value ret = Clone();
                if (!ret.IsFractional) ret._format = right._format;
                ret._num = Math.Round(ret._num * right._num);
                ret._denom = Math.Round(ret._denom * right._denom);
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            //if (_format == ValueFormat.Date || right._format == ValueFormat.Date) throw new Exception("Dates cannot be multiplied.");

            return new Value(_decValue * right._decValue, DecideFormat(_format, right._format));
        }
예제 #6
0
        public Value Modulus(Value right)
        {
            if ((IsFractional && right.IsFractional)
                || (IsFractional && right.IsInteger)
                || (IsInteger && right.IsFractional))
            {
                Value ret = Clone();
                if (!ret.IsFractional) ret._format = right._format;
                decimal scale = ret.FindCommonDenom(right._denom);
                ret._num = Math.Round(ret._num % (right._num * scale));
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            //if (_format == ValueFormat.Date || right._format == ValueFormat.Date) throw new Exception("Modulus cannot be used with dates.");

            return new Value(_decValue % right._decValue, DecideFormat(_format, right._format));
        }
예제 #7
0
        public Value Divide(Value right)
        {
            if ((IsFractional && right.IsFractional)
                || (IsFractional && right.IsInteger)
                || (IsInteger && right.IsFractional))
            {
                Value ret = Clone();
                if (!ret.IsFractional) ret._format = right._format;
                if (right._num == 0 || right._denom == 0) throw new Exception("Division by zero.");
                ret._num = Math.Round(ret._num / right._num);
                ret._denom = Math.Round(ret._denom / right._denom);
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            if (right._decValue == 0) throw new Exception("Division by zero.");
            //if (_format == ValueFormat.Date || right._format == ValueFormat.Date) throw new Exception("Dates cannot be divided.");

            return new Value(_decValue / right._decValue, DecideFormat(_format, right._format));
        }
예제 #8
0
 private static void SetValue(Token tok, Value val)
 {
     tok.Value = val;
     //tok.Type = TokenType.None;
     tok.Precedence = 0;
 }
예제 #9
0
 public Value BitwiseXor(Value right)
 {
     return new Value(Convert.ToDecimal(Convert.ToInt64(_decValue) ^ Convert.ToInt64(right._decValue)), DecideFormat(_format, right._format));
 }
예제 #10
0
        public Value Add(Value right)
        {
            if ((IsFractional && right.IsFractional)
                || (IsFractional && right.IsInteger)
                || (IsInteger && right.IsFractional))
            {
                Value ret = Clone();
                if (!ret.IsFractional) ret._format = right._format;
                decimal scale = ret.FindCommonDenom(right._denom);
                ret._num = Math.Round(ret._num + right._num * scale);
                ret._decValue = ret._num / ret._denom;
                ret.SimplifyFraction();
                return ret;
            }

            return new Value(_decValue + right._decValue, DecideFormat(_format, right._format));
        }
예제 #11
0
        public static Value CreateFraction(Value numValue, Value denomValue)
        {
            if (denomValue.DecValue == 0) throw new Exception("Division by zero.");

            if ((!numValue.IsInteger && !numValue.IsFractional) ||
                (!denomValue.IsInteger && !denomValue.IsFractional))
            {
                // These values are not integers, so this operator will use the default format instead.
                // In this case the fraction operator will act like the division operator.
                return new Value(numValue.DecValue / denomValue.DecValue, Value.DecideFormat(numValue.Format, denomValue.Format));
            }

            if (numValue.IsFractional)
            {
                // Numerator is fraction, and denominator 'might' be.
                return numValue.Divide(denomValue);
            }

            if (denomValue.IsFractional)
            {
                // Numerator is not a fraction but is an integer, and denominator is a fraction.
                return new Value(numValue.DecValue, ValueFormat.Fraction).Divide(denomValue);
            }

            // Numerator and denominator are both integers.
            return new Value(numValue.DecValue, denomValue.DecValue, ValueFormat.Fraction);
        }
예제 #12
0
        public static Value Execute(string funcName, Value[] args)
        {
            switch (funcName.ToLower())
            {
                case "abs":
                    if (args.Length != 1) throw new Exception("'abs' requires 1 argument.");
                    return new Value(Math.Abs(args[0].DecValue), args[0].Format);

                case "acos":
                    if (args.Length != 1) throw new Exception("'acos' requires 1 argument.");
                    return new Value(Util.ToAngle(Math.Acos(args[0].DblValue)), args[0].Format);

                case "asin":
                    if (args.Length != 1) throw new Exception("'asin' requires 1 argument.");
                    return new Value(Util.ToAngle(Math.Asin(args[0].DblValue)), args[0].Format);

                case "atan":
                    if (args.Length != 1) throw new Exception("'atan' requires 1 argument.");
                    return new Value(Util.ToAngle(Math.Atan(args[0].DblValue)), args[0].Format);

                case "bin":
                    if (args.Length != 1) throw new Exception("'bin' requires 1 argument.");
                    return new Value(args[0].DecValue, ValueFormat.Bin);

                case "case":
                    {
                        if (args.Length < 4) throw new Exception("'case' requires at least 4 arguments.");
                        if (args.Length % 2 != 0) throw new Exception("'case' requires an even number of arguments.");
                        for (int i = 1, ii = args.Length - 1; i < ii; i += 2)
                        {
                            if (args[i].DecValue == args[0].DecValue) return args[i + 1].Clone();
                        }
                        return args[args.Length - 1].Clone();
                    }

                case "ceil":
                    if (args.Length != 1) throw new Exception("'ceil' requires 1 argument.");
                    return new Value(Math.Ceiling(args[0].DecValue), args[0].Format);

                case "cos":
                    if (args.Length != 1) throw new Exception("'cos' requires 1 argument.");
                    return new Value(Math.Cos(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "cosh":
                    if (args.Length != 1) throw new Exception("'cosh' requires 1 argument.");
                    return new Value(Math.Cosh(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "day":
                    {
                        if (args.Length != 1) throw new Exception("'day' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Day, ValueFormat.Dec);
                    }

                case "days":
                    {
                        if (args.Length != 1) throw new Exception("'days' requires 1 argument.");
                        return new Value(args[0].LongValue / 864000000000, ValueFormat.Dec);
                    }

                case "dec":
                    if (args.Length != 1) throw new Exception("'dec' requires 1 argument.");
                    return new Value(args[0].DecValue, ValueFormat.Dec);

                case "floor":
                    if (args.Length != 1) throw new Exception("'floor' requires 1 argument.");
                    return new Value(Math.Floor(args[0].DecValue), args[0].Format);

                case "hex":
                    if (args.Length != 1) throw new Exception("'hex' requires 1 argument.");
                    return new Value(args[0].DecValue, ValueFormat.Hex);

                case "hour":
                    {
                        if (args.Length != 1) throw new Exception("'hour' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Hour, ValueFormat.Dec);
                    }

                case "hours":
                    {
                        if (args.Length != 1) throw new Exception("'hours' requires 1 argument.");
                        return new Value(args[0].LongValue / 36000000000, ValueFormat.Dec);
                    }

                case "if":
                    if (args.Length < 3) throw new Exception("'if' requires at least 3 arguments.");
                    if (args.Length % 2 == 0) throw new Exception("'if' requires an odd number of arguments.");
                    for (int i = 0, ii = args.Length - 1; i < ii; i += 2)
                    {
                        if (args[i].DecValue != 0) return args[i + 1].Clone();
                    }
                    return args[args.Length - 1].Clone();

                case "lg":
                    if (args.Length != 1) throw new Exception("'lg' requires 1 argument.");
                    return new Value(Math.Log(args[0].DblValue, 2), args[0].Format);

                case "ln":
                    if (args.Length != 1) throw new Exception("'ln' requires 1 argument.");
                    return new Value(Math.Log10(args[0].DblValue), args[0].Format);

                case "log":
                    if (args.Length == 1)
                    {
                        return new Value(Math.Log10(args[0].DblValue), args[0].Format);
                    }
                    else if (args.Length == 2)
                    {
                        return new Value(Math.Log(args[0].DblValue, args[1].DblValue), Value.DecideFormat(args[0].Format, args[1].Format));
                    }
                    else throw new Exception("'log' requires 1 or 2 arguments.");

                case "makedate":
                    {
                        if (args.Length < 3 || args.Length > 7) throw new Exception("'makedate' requires between 3 and 7 arguments.");
                        if (!args[0].IsInteger) throw new Exception("'makedate' year must be an integer.");
                        if (!args[1].IsInteger) throw new Exception("'makedate' month must be an integer.");
                        if (!args[2].IsInteger) throw new Exception("'makedate' day must be an integer.");
                        if (args.Length > 3 && !args[3].IsInteger) throw new Exception("'makedate' hour must be an integer.");
                        if (args.Length > 4 && !args[4].IsInteger) throw new Exception("'makedate' minute must be an integer.");
                        if (args.Length > 5 && !args[5].IsInteger) throw new Exception("'makedate' second must be an integer.");
                        if (args.Length > 6 && !args[6].IsInteger) throw new Exception("'makedate' millisecond must be an integer.");

                        DateTime dt;
                        try
                        {
                            dt = new DateTime(args[0].IntValue, args[1].IntValue, args[2].IntValue,
                                (args.Length > 3 ? args[3].IntValue : 0),
                                (args.Length > 4 ? args[4].IntValue : 0),
                                (args.Length > 5 ? args[5].IntValue : 0),
                                (args.Length > 6 ? args[6].IntValue : 0));
                        }
                        catch (Exception)
                        {
                            throw new Exception("Invalid date.");
                        }

                        return new Value(dt.Ticks, ValueFormat.Date);
                    }

                case "max":
                    {
                        if (args.Length < 2) throw new Exception("'max' requires 2 or more arguments.");
                        decimal m = 0;
                        bool first = true;
                        foreach (Value arg in args)
                        {
                            if (first || arg.DecValue > m)
                            {
                                m = arg.DecValue;
                                first = false;
                            }
                        }
                        return new Value(m, args[0].Format);
                    }

                case "min":
                    {
                        if (args.Length < 2) throw new Exception("'min' requires 2 or more arguments.");
                        decimal m = 0;
                        bool first = true;
                        foreach (Value arg in args)
                        {
                            if (first || arg.DecValue < m)
                            {
                                m = arg.DecValue;
                                first = false;
                            }
                        }
                        return new Value(m, args[0].Format);
                    }

                case "minute":
                    {
                        if (args.Length != 1) throw new Exception("'minute' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Minute, ValueFormat.Dec);
                    }

                case "minutes":
                    {
                        if (args.Length != 1) throw new Exception("'minutes' requires 1 argument.");
                        return new Value(args[0].LongValue / 600000000, ValueFormat.Dec);
                    }

                case "month":
                    {
                        if (args.Length != 1) throw new Exception("'month' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Month, ValueFormat.Dec);
                    }

                case "msec":
                    {
                        if (args.Length != 1) throw new Exception("'msec' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Millisecond, ValueFormat.Dec);
                    }

                case "msecs":
                    {
                        if (args.Length != 1) throw new Exception("'msecs' requires 1 argument.");
                        return new Value(args[0].LongValue / 10000, ValueFormat.Dec);
                    }

                case "oct":
                    if (args.Length != 1) throw new Exception("'oct' requires 1 argument.");
                    return new Value(args[0].DecValue, ValueFormat.Oct);

                case "pow":
                    if (args.Length != 2) throw new Exception("'pow' requires 2 arguments.");
                    return args[0].Power(args[1]);

                case "rand":
                    if (args.Length == 0)
                    {
                        return new Value(Settings.Rand.NextDouble(), ValueFormat.Default);
                    }
                    else if (args.Length == 1)
                    {
                        return new Value(Settings.Rand.NextDouble() * args[0].DblValue, args[0].Format);
                    }
                    else if (args.Length == 2)
                    {
                        return new Value(Settings.Rand.NextDouble() * (args[1].DblValue - args[0].DblValue) + args[0].DblValue, Value.DecideFormat(args[0].Format, args[1].Format));
                    }
                    else throw new Exception("'rand' requires 0, 1 or 2 arguments.");

                case "round":
                    if (args.Length == 1)
                    {
                        return new Value(Math.Round(args[0].DecValue, MidpointRounding.AwayFromZero), args[0].Format);
                    }
                    else if (args.Length == 2)
                    {
                        int numDecimals = args[1].IntValue;
                        if (numDecimals < 0 || numDecimals > 20) throw new Exception("'round' number of decimals must be between 0 and 20.");
                        return new Value(Math.Round(args[0].DecValue, args[1].IntValue, MidpointRounding.AwayFromZero), args[0].Format);
                    }
                    else throw new Exception("'round' requires 1 or 2 arguments.");

                case "sci":
                    if (args.Length != 1) throw new Exception("'sci' requires 1 argument.");
                    return new Value(args[0].DecValue, ValueFormat.Sci);

                case "second":
                    {
                        if (args.Length != 1) throw new Exception("'second' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Second, ValueFormat.Dec);
                    }

                case "seconds":
                    {
                        if (args.Length != 1) throw new Exception("'seconds' requires 1 argument.");
                        return new Value(args[0].LongValue / (10000000), ValueFormat.Dec);
                    }

                case "sin":
                    if (args.Length != 1) throw new Exception("'sin' requires 1 argument.");
                    return new Value(Math.Sin(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "sinh":
                    if (args.Length != 1) throw new Exception("'sinh' requires 1 argument.");
                    return new Value(Math.Sinh(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "sqrt":
                    if (args.Length != 1) throw new Exception("'sqrt' requires 1 argument.");
                    if (args[0].DblValue < 0) throw new Exception("Cannot calculate the square-root of a negative number.");
                    return new Value(Math.Sqrt(args[0].DblValue), args[0].Format);

                case "tan":
                    if (args.Length != 1) throw new Exception("'tan' requires 1 argument.");
                    return new Value(Math.Tan(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "tanh":
                    if (args.Length != 1) throw new Exception("'tanh' requires 1 argument.");
                    return new Value(Math.Tanh(Util.ToRads(args[0].DblValue)), args[0].Format);

                case "xor":
                    if (args.Length != 2) throw new Exception("'xor' requires 2 arguments.");
                    return args[0].BitwiseXor(args[1]);

                case "year":
                    {
                        if (args.Length != 1) throw new Exception("'year' requires 1 argument.");
                        DateTime dt = new DateTime(args[0].LongValue);
                        return new Value(dt.Year, ValueFormat.Dec);
                    }

                default:
                    throw new Exception("Unknown function '" + funcName + "'.");
            }
        }
예제 #13
0
        public void LoadTokenGroup(Token token, Value[] args)
        {
            if (args.Length != _args.Length) throw new Exception("Macro '" + _name + "' requires " + _args.Length + " argument(s).");

            SortedList<string, Value> argList = new SortedList<string, Value>();
            int argIndex = 0;
            foreach (string argName in _args) argList.Add(argName, args[argIndex++]);

            foreach (Token eqToken in _eqGroup) token.AppendChild(eqToken.Clone());
            PrepareTokenGroupForMacroExe(token.Group, argList);
        }
예제 #14
0
 private static void UnaryOp(Value val)
 {
     SetValue(_token, val);
     _rightToken.Enabled = false;
 }
예제 #15
0
        private void Execute(Token parentToken, Token leftToken2, Token leftToken, Token rightToken)
        {
            switch (_type)
            {
                case TokenType.Operator:
                    Calc.Operator.Execute(this, parentToken, leftToken2, leftToken, rightToken);
                    break;

                case TokenType.Group:
                    if (leftToken != null && (leftToken._type == TokenType.Function || leftToken._type == TokenType.Macro)) _isFuncArgs = true;
                    ExecuteGroup();
                    _precedence = 0;
                    break;

                case TokenType.Function:
                    if (rightToken == null || rightToken._returnValues == null) throw new Exception("Missing argument list for function '" + _text + "'.");
                    _value = Function.Execute(_text, rightToken._returnValues.ToArray());
                    _precedence = 0;
                    rightToken.Enabled = false;
                    break;

                case TokenType.Macro:
                    {
                        if (rightToken == null || rightToken._returnValues == null) throw new Exception("Missing argument list for macro '" + _text + "'.");

                        // Pretend we're a group
                        this._type = TokenType.Group;

                        Data.GetMacro(Text).LoadTokenGroup(this, rightToken._returnValues.ToArray());
                        ExecuteGroup();
                        if (_returnValues.Count != 1) throw new Exception("Macro '" + _text + "' syntax error.");
                        _value = _returnValues[0];
                        _precedence = 0;
                        rightToken.Enabled = false;
                    }
                    break;

                default:
                    throw new Exception("Internal: Cannot execute token type '" + _type.ToString() + "'.");
            }
        }
예제 #16
0
 public Value Clone()
 {
     Value val = new Value(_decValue, _num, _denom, _format);
     val._num = _num;
     val._denom = _denom;
     return val;
 }
예제 #17
0
 private static void AssignOp(Value val)
 {
     SetValue(_leftToken, val);
     _rightToken.Enabled = _token.Enabled = false;
 }