public Token(TokenType type, string text, Value value) { _type = type; _text = text; _value = value; Initialize(); }
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)); }
public Value ShiftRight(Value right) { return new Value(Convert.ToDecimal(Convert.ToInt32(_decValue) >> Convert.ToInt32(right._decValue)), DecideFormat(_format, right._format)); }
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)); }
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)); }
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)); }
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)); }
private static void SetValue(Token tok, Value val) { tok.Value = val; //tok.Type = TokenType.None; tok.Precedence = 0; }
public Value BitwiseXor(Value right) { return new Value(Convert.ToDecimal(Convert.ToInt64(_decValue) ^ Convert.ToInt64(right._decValue)), DecideFormat(_format, right._format)); }
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)); }
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); }
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 + "'."); } }
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); }
private static void UnaryOp(Value val) { SetValue(_token, val); _rightToken.Enabled = false; }
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() + "'."); } }
public Value Clone() { Value val = new Value(_decValue, _num, _denom, _format); val._num = _num; val._denom = _denom; return val; }
private static void AssignOp(Value val) { SetValue(_leftToken, val); _rightToken.Enabled = _token.Enabled = false; }