private void enter_pressed(object sender, EventArgs e) { indicator.Text = ""; //saves calculation checker.Text = save + " " + textdisp.Text + " = "; string inputvalue = textdisp.Text; switch (operation) { case "+": textdisp.Text = (results + Double.Parse(textdisp.Text)).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "-": textdisp.Text = (results - Double.Parse(textdisp.Text)).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "÷": if (textdisp.Text == "0") { textdisp.Text = "invalid"; MessageBox.Show("invalid"); checker.Text = checker.Text + textdisp.Text; } else { textdisp.Text = (results / Double.Parse(textdisp.Text)).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); } break; case "×": textdisp.Text = (results * Double.Parse(textdisp.Text)).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "%": textdisp.Text = (results % Double.Parse(textdisp.Text)).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "^": if (results == 0 && Double.Parse(textdisp.Text) == -1) { textdisp.Text = "invalid"; checker.Text = checker.Text + textdisp.Text; } else { textdisp.Text = (Math.Pow(results, Double.Parse(textdisp.Text))).ToString(); checker.Text = checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); } break; case "√": if (results <= 0) { textdisp.Text = "invalid"; checker.Text = "√" + checker.Text + textdisp.Text; } else { textdisp.Text = (Math.Sqrt(results)).ToString(); checker.Text = "√" + checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); } break; case "^-1": if (results == 0) { textdisp.Text = "invalid"; checker.Text = checker.Text + "^-1" + " = " + textdisp.Text; } else { textdisp.Text = (1 / results).ToString(); checker.Text = checker.Text + "^-1" + Math.Round(Convert.ToDecimal(textdisp.Text), 3); } break; case "sin": inputvalue = textdisp.Text; textdisp.Text = (Math.Sin(results * (Math.PI) / 180)).ToString(); checker.Text = "sin " + inputvalue + " = " + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "cos": inputvalue = textdisp.Text; textdisp.Text = (Math.Cos(results * (Math.PI) / 180)).ToString(); checker.Text = "cos " + inputvalue + " = " + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "tan": inputvalue = textdisp.Text; textdisp.Text = (Math.Tan(results * (Math.PI) / 180)).ToString(); checker.Text = "tan " + inputvalue + " = " + Math.Round(Convert.ToDecimal(textdisp.Text), 3); break; case "ln": if (results <= 0) { textdisp.Text = "invalid"; checker.Text = "ln" + checker.Text + textdisp.Text; } else { textdisp.Text = (Math.Log(results)).ToString(); checker.Text = "ln" + checker.Text + Math.Round(Convert.ToDecimal(textdisp.Text), 3); } break; } using (MySqlConnection mysqlCon = new MySqlConnection(connectionString)) { mysqlCon.Open(); MySqlCommand cmd = new MySqlCommand("calcAdd", mysqlCon); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("_ID", ID); cmd.Parameters.AddWithValue("_calculation", checker.Text); cmd.Parameters.AddWithValue("_Calcdate", DateTime.Now.ToString("MM-dd-yyyy")); cmd.Parameters.AddWithValue("_Calctime", DateTime.Now.ToString("HH:mm:ss")); cmd.ExecuteNonQuery(); connection.Close(); } //MySqlCommand cmd = new MySqlCommand("insert into calculations (calculation)Values('" + checker.Text + "')", connection); //cmd.ExecuteNonQuery(); populategrid(); }
protected override void DoAction(int action) { #pragma warning disable 162, 1522 switch (action) { case 4: // statement -> ASSIGN, NAME, EQUAL, expression, SEMICOLON #line 33 "Parser.gppg" { MainX.VariableMap[ValueStack[ValueStack.Depth - 4].name] = ValueStack[ValueStack.Depth - 2].value; } #line default break; case 5: // statement -> READ, optional_output, name_list, SEMICOLON #line 37 "Parser.gppg" { try { string buffer = Console.In.ReadLine(); string[] textArray = buffer.Split(','); if (ValueStack[ValueStack.Depth - 2].nameList.Count != textArray.Length) { Console.Error.WriteLine("Invalid number of values."); Environment.Exit(-1); } for (int index = 0; index < ValueStack[ValueStack.Depth - 2].nameList.Count; ++index) { string name = ValueStack[ValueStack.Depth - 2].nameList[index], text = textArray[index]; double value = double.Parse(text); // double value = double.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture); MainX.VariableMap[name] = value; } } catch (Exception exception) { Console.Error.WriteLine("Invalid input: " + exception.ToString()); Environment.Exit(-1); } } #line default break; case 6: // statement -> WRITE, optional_output, expression_list, SEMICOLON #line 60 "Parser.gppg" { bool first = true; foreach (double value in ValueStack[ValueStack.Depth - 2].valueList) { Console.Out.Write((first ? "" : ", ") + value); first = false; } Console.Out.WriteLine(); } #line default break; case 7: // statement -> NEWLINE, SEMICOLON #line 70 "Parser.gppg" { Console.Out.WriteLine(); } #line default break; case 9: // optional_output -> TEXT, COMMA #line 76 "Parser.gppg" { Console.Out.Write(ValueStack[ValueStack.Depth - 2].text); } #line default break; case 10: // name_list -> NAME #line 81 "Parser.gppg" { CurrentSemanticValue.nameList = new List <string>(); CurrentSemanticValue.nameList.Add(ValueStack[ValueStack.Depth - 1].name); } #line default break; case 11: // name_list -> name_list, COMMA, NAME #line 85 "Parser.gppg" { CurrentSemanticValue.nameList = ValueStack[ValueStack.Depth - 3].nameList; CurrentSemanticValue.nameList.Add(ValueStack[ValueStack.Depth - 1].name); } #line default break; case 12: // expression_list -> expression #line 91 "Parser.gppg" { CurrentSemanticValue.valueList = new List <double>(); CurrentSemanticValue.valueList.Add(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 13: // expression_list -> expression_list, COMMA, expression #line 95 "Parser.gppg" { CurrentSemanticValue.valueList = ValueStack[ValueStack.Depth - 3].valueList; CurrentSemanticValue.valueList.Add(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 14: // expression -> binary_expression #line 101 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 1].value; } #line default break; case 15: // expression -> expression, PLUS, binary_expression #line 104 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 3].value + ValueStack[ValueStack.Depth - 1].value; } #line default break; case 16: // expression -> expression, MINUS, binary_expression #line 107 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 3].value - ValueStack[ValueStack.Depth - 1].value; } #line default break; case 17: // binary_expression -> unary_expression #line 112 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 1].value; } #line default break; case 18: // binary_expression -> binary_expression, TIMES, unary_expression #line 115 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 3].value * ValueStack[ValueStack.Depth - 1].value; } #line default break; case 19: // binary_expression -> binary_expression, DIVIDE, unary_expression #line 118 "Parser.gppg" { if (ValueStack[ValueStack.Depth - 1].value == 0) { Console.Error.WriteLine("Division by Zero."); Environment.Exit(-1); } CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 3].value / ValueStack[ValueStack.Depth - 1].value; } #line default break; case 20: // unary_expression -> primary_expression #line 128 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 1].value; } #line default break; case 21: // unary_expression -> PLUS, unary_expression #line 131 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 1].value; } #line default break; case 22: // unary_expression -> MINUS, unary_expression #line 134 "Parser.gppg" { CurrentSemanticValue.value = -ValueStack[ValueStack.Depth - 1].value; } #line default break; case 23: // unary_expression -> SIN, unary_expression #line 137 "Parser.gppg" { CurrentSemanticValue.value = Math.Sin(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 24: // unary_expression -> COS, unary_expression #line 140 "Parser.gppg" { CurrentSemanticValue.value = Math.Cos(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 25: // unary_expression -> TAN, unary_expression #line 143 "Parser.gppg" { CurrentSemanticValue.value = Math.Tan(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 26: // unary_expression -> LOG, unary_expression #line 146 "Parser.gppg" { if (ValueStack[ValueStack.Depth - 1].value <= 0) { Console.Error.WriteLine("Logarithm of Non-Positive Value."); Environment.Exit(-1); } CurrentSemanticValue.value = Math.Log(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 27: // unary_expression -> EXP, unary_expression #line 154 "Parser.gppg" { CurrentSemanticValue.value = Math.Exp(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 28: // unary_expression -> LOG10, unary_expression #line 157 "Parser.gppg" { if (ValueStack[ValueStack.Depth - 1].value <= 0) { Console.Error.WriteLine("Logarithm of Non-Positive Value."); Environment.Exit(-1); } CurrentSemanticValue.value = Math.Log10(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 29: // unary_expression -> EXP10, unary_expression #line 165 "Parser.gppg" { CurrentSemanticValue.value = Math.Pow(10, ValueStack[ValueStack.Depth - 1].value); } #line default break; case 30: // unary_expression -> SQRT, unary_expression #line 168 "Parser.gppg" { if (ValueStack[ValueStack.Depth - 1].value < 0) { Console.Error.WriteLine("Square Root of Negativ Value."); Environment.Exit(-1); } CurrentSemanticValue.value = Math.Sqrt(ValueStack[ValueStack.Depth - 1].value); } #line default break; case 31: // primary_expression -> LEFT_PAREN, expression, RIGHT_PAREN #line 178 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 2].value; } #line default break; case 32: // primary_expression -> NAME #line 181 "Parser.gppg" { if (MainX.VariableMap.ContainsKey(ValueStack[ValueStack.Depth - 1].name)) { CurrentSemanticValue.value = MainX.VariableMap[ValueStack[ValueStack.Depth - 1].name]; } else { Console.Error.WriteLine("Unknown Name: \"" + ValueStack[ValueStack.Depth - 1].name + "\"."); Environment.Exit(-1); } } #line default break; case 33: // primary_expression -> VALUE #line 190 "Parser.gppg" { CurrentSemanticValue.value = ValueStack[ValueStack.Depth - 1].value; } #line default break; } #pragma warning restore 162, 1522 }
public void InitDefaults() { this.Add("about", new StaticFunction("About", delegate(object[] ps) { return("@Calculator - a Tiny Expression Evaluator v1.0\r\nby Herre Kuijpers - Copyright © 2011 under the CPOL license"); }, 0, 0)); this.Add("help", new StaticFunction("Help", Help, 0, 0)); // high precision functions this.Add("abs", new StaticFunction("Abs", delegate(object[] ps) { return(Math.Abs(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("acos", new StaticFunction("Acos", delegate(object[] ps) { return(Math.Acos(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("asin", new StaticFunction("Asin", delegate(object[] ps) { return(Math.Asin(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("atan", new StaticFunction("Atan", delegate(object[] ps) { return(Math.Atan(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("atan2", new StaticFunction("Atan2", delegate(object[] ps) { return(Math.Atan2(Convert.ToDouble(ps[0]), Convert.ToDouble(ps[1]))); }, 2, 2)); this.Add("ceiling", new StaticFunction("Ceiling", delegate(object[] ps) { return(Math.Ceiling(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("cos", new StaticFunction("Cos", delegate(object[] ps) { return(Math.Cos(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("cosh", new StaticFunction("Cosh", delegate(object[] ps) { return(Math.Cosh(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("exp", new StaticFunction("Exp", delegate(object[] ps) { return(Math.Exp(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("int", new StaticFunction("int", delegate(object[] ps) { return((int)Math.Floor(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("fact", new StaticFunction("Fact", Fact, 1, 1)); // factorials 1*2*3*4... this.Add("floor", new StaticFunction("Floor", delegate(object[] ps) { return(Math.Floor(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("log", new StaticFunction("Log", Log, 1, 2)); // log allows 1 or 2 parameters this.Add("ln", new StaticFunction("Ln", delegate(object[] ps) { return(Math.Log(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("pow", new StaticFunction("Pow", delegate(object[] ps) { if ( (Convert.ToInt64(ps[0]) != Convert.ToDouble(ps[0])) || (Convert.ToInt64(ps[1]) != Convert.ToDouble(ps[1])) ) { return(Math.Pow(Convert.ToDouble(ps[0]), Convert.ToDouble(ps[1]))); } else // use integral maths instead to avoid silent overflow { long number = Convert.ToInt64(ps[0]); long power = Convert.ToInt64(ps[1]); long result = 1L; for (long i = 0; i < power; i++) { result *= number; } return(result); } }, 2, 2)); this.Add("round", new StaticFunction("Round", delegate(object[] ps) { return(Math.Round(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("sign", new StaticFunction("Sign", delegate(object[] ps) { return(Math.Sign(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("sin", new StaticFunction("Sin", delegate(object[] ps) { return(Math.Sin(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("sinh", new StaticFunction("Sinh", delegate(object[] ps) { return(Math.Sinh(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("sqr", new StaticFunction("Sqr", delegate(object[] ps) { return(Convert.ToDouble(ps[0]) * Convert.ToDouble(ps[0])); }, 1, 1)); this.Add("sqrt", new StaticFunction("Sqrt", delegate(object[] ps) { return(Math.Sqrt(Convert.ToDouble(ps[0]))); }, 1, 1)); this.Add("trunc", new StaticFunction("Trunc", delegate(object[] ps) { return(Math.Truncate(Convert.ToDouble(ps[0]))); }, 1, 1)); // array functions this.Add("avg", new StaticFunction("Avg", Avg, 1, int.MaxValue)); this.Add("stdev", new StaticFunction("StDev", StDev, 1, int.MaxValue)); this.Add("var", new StaticFunction("Var", Var, 1, int.MaxValue)); this.Add("max", new StaticFunction("Max", Max, 1, int.MaxValue)); this.Add("median", new StaticFunction("Min", Median, 1, int.MaxValue)); this.Add("min", new StaticFunction("Min", Min, 1, int.MaxValue)); //boolean functions this.Add("not", new StaticFunction("Not", delegate(object[] ps) { return(!Convert.ToBoolean(ps[0])); }, 1, 1)); this.Add("if", new StaticFunction("If", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) ? ps[1] : ps[2]); }, 3, 3)); this.Add("and", new StaticFunction("And", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) && Convert.ToBoolean(ps[1])); }, 2, 2)); this.Add("or", new StaticFunction("Or", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) || Convert.ToBoolean(ps[1])); }, 2, 2)); // string functions this.Add("left", new StaticFunction("Left", delegate(object[] ps) { int len = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length; return(ps[0].ToString().Substring(0, len)); }, 2, 2)); this.Add("right", new StaticFunction("Right", delegate(object[] ps) { int len = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length; return(ps[0].ToString().Substring(ps[0].ToString().Length - len, len)); }, 2, 2)); this.Add("mid", new StaticFunction("Mid", delegate(object[] ps) { int idx = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length; int len = Convert.ToInt32(ps[2]) < ps[0].ToString().Length - idx ? Convert.ToInt32(ps[2]) : ps[0].ToString().Length - idx; return(ps[0].ToString().Substring(idx, len)); }, 3, 3)); this.Add("hex", new StaticFunction("Hex", delegate(object[] ps) { return(String.Format("0x{0:X}", Convert.ToInt32(ps[0].ToString()))); }, 1, 1)); this.Add("format", new StaticFunction("Format", delegate(object[] ps) { return(string.Format(ps[0].ToString(), ps[1])); }, 2, 2)); this.Add("len", new StaticFunction("Len", delegate(object[] ps) { return(Convert.ToDouble(ps[0].ToString().Length)); }, 1, 1)); this.Add("lower", new StaticFunction("Lower", delegate(object[] ps) { return(ps[0].ToString().ToLowerInvariant()); }, 1, 1)); this.Add("upper", new StaticFunction("Upper", delegate(object[] ps) { return(ps[0].ToString().ToUpperInvariant()); }, 1, 1)); this.Add("val", new StaticFunction("Val", delegate(object[] ps) { return(Convert.ToDouble(ps[0])); }, 1, 1)); }
// Methods // Todo: We're missing type-checking and appropriate error handling! // Todo: Switch to an type operator based computation! // Todo: Introduce Implicit Casting! public object Evaluate() { var stack = new SpecializedStack <Operand>(); var variables = new Dictionary <string, Operand>(); foreach (var token in _lexer.GetTokens()) { switch (token.Kind) { // Arithmetic Operators case TokenKind.Add: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)left.Value + (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.Subtract: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)left.Value - (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.Multiply: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)left.Value * (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.Divide: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)left.Value / (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.ClearStackAndVariables: { variables.Clear(); stack.Clear(); break; } case TokenKind.ClearStack: { stack.Clear(); break; } case TokenKind.ClearVariables: { variables.Clear(); break; } case TokenKind.BooleanNot: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Boolean) { stack.Push(Operand.FromBoolean(!(bool)operand.Value)); } else { throw new FormatException(); } break; } case TokenKind.Modulus: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)left.Value % (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.Increment: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)operand.Value + 1)); } else { throw new FormatException(); } break; } case TokenKind.Decrement: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)operand.Value - 1)); } else { throw new FormatException(); } break; } // Bitwise Operators case TokenKind.BitwiseAnd: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to a long. stack.Push(Operand.FromNumber((long)(decimal)left.Value & (long)(decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BitwiseOr: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to a long. stack.Push(Operand.FromNumber((long)(decimal)left.Value | (long)(decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BitwiseXor: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to a long. stack.Push(Operand.FromNumber((long)(decimal)left.Value ^ (long)(decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BitwiseNot: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to a long. stack.Push(Operand.FromNumber(~(long)(decimal)operand.Value)); } else { throw new FormatException(); } break; } case TokenKind.BitwiseShiftLeft: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to an int/long. stack.Push(Operand.FromNumber((long)(decimal)left.Value << (int)(decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BitwiseShiftRight: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { // Todo: Let's pretend we can always convert to an int/long. stack.Push(Operand.FromNumber((long)(decimal)left.Value >> (int)(decimal)right.Value)); } else { throw new FormatException(); } break; } // Boolean Operators case TokenKind.BooleanAnd: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean) { stack.Push(Operand.FromBoolean((bool)left.Value && (bool)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BooleanOr: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean) { stack.Push(Operand.FromBoolean((bool)left.Value || (bool)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.BooleanXor: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean) { var leftValue = (bool)left.Value; var rightValue = (bool)right.Value; stack.Push(Operand.FromBoolean((leftValue && leftValue == false) || (leftValue == false && leftValue))); } else { throw new FormatException(); } break; } // Comparison Operators case TokenKind.LessThan: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value < (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.LessThanOrEqualTo: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value <= (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.EqualTo: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value == (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.GreaterThan: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value > (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.GreaterThanOrEqualTo: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value >= (decimal)right.Value)); } else { throw new FormatException(); } break; } case TokenKind.NotEqualTo: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromBoolean((decimal)left.Value != (decimal)right.Value)); } else { throw new FormatException(); } break; } // Trigonometric Functions case TokenKind.Acos: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Acos((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Asin: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Asin((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Atan: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Atan((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Cos: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Cos((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Cosh: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Cosh((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Sin: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Sin((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Sinh: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Sinh((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Tanh: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Tanh((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } // Numeric Utilities case TokenKind.Ceil: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Ceiling((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Floor: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Floor((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Round: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Round((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.IntegerPart: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Truncate((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.FloatingPart: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { var value = (decimal)operand.Value; stack.Push(Operand.FromNumber(value - Math.Truncate(value))); } else { throw new FormatException(); } break; } case TokenKind.Sign: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: I'm not sure I understand the documentation on this one! var value = (decimal)operand.Value; stack.Push(Operand.FromNumber(value < 0 ? -1 : 0)); } else { throw new FormatException(); } break; } case TokenKind.Absolute: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Abs((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Max: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Max((decimal)left.Value, (decimal)right.Value))); } else { throw new FormatException(); } break; } case TokenKind.Min: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(Math.Min((decimal)left.Value, (decimal)right.Value))); } else { throw new FormatException(); } break; } // Display Modes case TokenKind.DisplayAsHex: { DisplayMode = EvaluatorDisplayMode.Hexadecimal; break; } case TokenKind.DisplayAsDecimal: { DisplayMode = EvaluatorDisplayMode.Decimal; break; } case TokenKind.DisplayAsBinary: { DisplayMode = EvaluatorDisplayMode.Binary; break; } case TokenKind.DisplayAsOctal: { DisplayMode = EvaluatorDisplayMode.Octal; break; } // Constants case TokenKind.PushE: { stack.Push(Operand.FromNumber((decimal)Math.E)); break; } case TokenKind.PushPi: { stack.Push(Operand.FromNumber((decimal)Math.PI)); break; } case TokenKind.PushRandom: { stack.Push(Operand.FromNumber((decimal)_random.Next())); break; } // Mathematic Functions case TokenKind.Exp: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Exp((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Fact: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber(BuiltIn.Factorial((decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Sqrt: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Sqrt((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Ln: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Log((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Log: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to double! stack.Push(Operand.FromNumber((decimal)Math.Log10((double)(decimal)operand.Value))); } else { throw new FormatException(); } break; } case TokenKind.Pow: { var right = stack.Pop(); var left = stack.Pop(); if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number) { stack.Push(Operand.FromNumber((decimal)Math.Pow((double)(decimal)left.Value, (double)(decimal)right.Value))); } else { throw new FormatException(); } break; } // Networking case TokenKind.HostToNetworkLong: case TokenKind.HostToNetworkShort: case TokenKind.NetworkToHostLong: case TokenKind.NetworkToHostShort: { throw new NotImplementedException(); } // Stack Manipulation case TokenKind.Pick: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to int! stack.Push(stack.Pick((int)operand.Value)); } else { throw new FormatException(); } break; } case TokenKind.Repeat: { // Todo: Complete! throw new NotImplementedException(); } case TokenKind.Depth: { stack.Push(Operand.FromNumber(stack.Count)); break; } case TokenKind.Drop: { stack.Pop(); break; } case TokenKind.DropN: { var operand = stack.Pop(); if (operand.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to int! for (int i = 0; i < (int)operand.Value; i++) { stack.Pop(); } } else { throw new FormatException(); } break; } case TokenKind.Dup: { stack.Push(stack.Peek()); break; } case TokenKind.DupN: { var op1 = stack.Pop(); var op2 = stack.Peek(); if (op1.Kind == OperandKind.Number) { // Todo: Let's pretend it's ok to convert to int! for (int i = 0; i < (int)op1.Value; i++) { stack.Push(op2); } } else { throw new FormatException(); } break; } case TokenKind.Roll: case TokenKind.RollDownwards: case TokenKind.ToggleStack: case TokenKind.Swap: { // Todo: Implement! throw new NotImplementedException(); } // Macros and Variables case TokenKind.Macro: //case TokenKind.Variable: { // Todo: Implement! throw new NotImplementedException(); } // Operand case TokenKind.Operand: { stack.Push(Operand.FromNumber((decimal)token.Value)); break; } default: break; } } return(stack.Count > 0 ? stack.Pop().Value : null); }