예제 #1
0
        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));
        }
예제 #2
0
        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
        }
예제 #3
0
        private void convert_click(object sender, EventArgs e)
        {
            if (txt_display.Text != "NaN" && txt_display.Text != "" && txt_display.Text != "∞" && txt_display.Text != "-∞")
            {
                Button b = (Button)sender;
                converation = b.Text;
                //if (converation == "1∕x")
                //{
                //    result = 1 / (Double.Parse(txt_display.Text));


                //    txt_showops.Text = txt_showops + "1/" + txt_display.Text;
                //    operation_str = txt_showops + result.ToString();
                //    txt_display.Text = result.ToString();
                //    enter_operation = true;
                //    enter_value = true;
                //    txt_history.Text = txt_showops.Text + " = " + result.ToString() + "\n" + txt_history.Text.ToString();

                //    result = new double();

                //}
                //else
                if (converation == "x²")
                {
                    result = Math.Pow(Double.Parse(txt_display.Text), 2);

                    //    txt_showops.Text = txt_showops + "1/" + txt_display.Text;
                    //    operation_str = txt_showops + result.ToString();
                    operation_str    = txt_showops.Text;
                    txt_showops.Text = txt_showops.Text + txt_display.Text + "²";

                    txt_history.Text = txt_display.Text + "²" + " = " + result.ToString() + "\n" + txt_history.Text.ToString();

                    txt_display.Text = result.ToString();
                    enter_operation  = true;
                    enter_value      = false;

                    result = new double();
                }
                else if (converation == "✓")
                {
                    result = Math.Sqrt(Double.Parse(txt_display.Text));

                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + " ✓" + txt_display.Text;
                    txt_history.Text = " ✓" + txt_display.Text + " = " + result.ToString() + "\n" + txt_history.Text.ToString();

                    txt_display.Text = result.ToString();
                    enter_operation  = true;
                    enter_value      = false;

                    result = new double();
                }

                else if (converation == "±")
                {
                    if (txt_display.Text != "")
                    {
                        result           = -Double.Parse(txt_display.Text);
                        txt_display.Text = result.ToString();
                        enter_operation  = true;
                    }
                }
                else if (converation == "n!")
                {
                    int n = int.Parse(txt_display.Text);
                    if (txt_display.Text != "-1")
                    {
                        operation_str = txt_showops.Text;

                        txt_showops.Text = txt_showops.Text + txt_display.Text + "!";
                        txt_history.Text = txt_display.Text + "! = " + n.ToString() + "\n" + txt_history.Text.ToString();

                        txt_display.Text = n.ToString();
                    }
                    else
                    {
                        txt_display.Text = "NaN";
                    }


                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "10^x")
                {
                    result        = Math.Pow(10, Double.Parse(txt_display.Text));
                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "10 ^ " + txt_display.Text;
                    txt_history.Text = "10 ^ " + txt_display.Text + " = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "ln")
                {
                    result        = Math.Log(Double.Parse(txt_display.Text));
                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "Ln(" + txt_display.Text + ")";
                    txt_history.Text = "Ln(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "Log")
                {
                    result        = Math.Log10(Double.Parse(txt_display.Text));
                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "Log(" + txt_display.Text + ")";
                    txt_history.Text = "Log(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "Exp")
                {
                    result        = Math.Exp(Double.Parse(txt_display.Text));
                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "Exp(" + txt_display.Text + ")";
                    txt_history.Text = "Exp(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "sin")
                {
                    if (degree)
                    {
                        if (int.Parse(txt_display.Text) % 180 != 0)
                        {
                            result = Math.Sin(Math.PI * Double.Parse(txt_display.Text) / 180.0);
                        }
                        else
                        {
                            result = 0;
                        }
                    }
                    //RAD
                    else
                    {
                        double degrees = Math.Round((180 / Math.PI) * double.Parse(txt_display.Text), 0);

                        if (degrees % 180 != 0)
                        {
                            result = Math.Sin(Math.PI * degrees / 180.0);
                            //result = Math.PI * result;
                        }
                        else
                        {
                            result = 0;
                        }
                    }

                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "sin(" + txt_display.Text + ")";
                    txt_history.Text = "sin(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "cos")
                {
                    if (degree)
                    {
                        if (int.Parse(txt_display.Text) % 90 != 0 || int.Parse(txt_display.Text) % 180 == 0)
                        {
                            result = Math.Cos(Math.PI * Double.Parse(txt_display.Text) / 180.0);
                        }
                        else
                        {
                            result = 0;
                        }
                    }
                    //RAD
                    else
                    {
                        double degrees = Math.Round((180 / Math.PI) * double.Parse(txt_display.Text), 0);

                        if (degrees % 90 != 0 && degrees % 180 == 0)
                        {
                            result = Math.Cos(Math.PI * degrees / 180.0);
                            //result = Math.PI * result;
                        }
                        else
                        {
                            result = 0;
                        }
                    }



                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "cos(" + txt_display.Text + ")";
                    txt_history.Text = "cos(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = true;
                    result          = new double();
                }
                else if (converation == "tan")
                {
                    if (degree)
                    {
                        result = Math.Tan(Math.PI * Double.Parse(txt_display.Text) / 180.0);
                    }
                    else
                    {
                        result = Math.Tan(Double.Parse(txt_display.Text));
                    }
                    operation_str = txt_showops.Text;

                    txt_showops.Text = txt_showops.Text + "tan(" + txt_display.Text + ")";
                    txt_history.Text = "tan(" + txt_display.Text + ") = " + result.ToString() + "\n" + txt_history.Text.ToString();
                    txt_display.Text = result.ToString();

                    enter_operation = true;
                    enter_value     = false;
                    result          = new double();
                }
                else if (converation == "sinh")
                {
                    result           = Math.Sinh(Double.Parse(txt_display.Text));
                    txt_showops.Text = "sinh( " + txt_display.Text + " )";


                    txt_display.Text = result.ToString();

                    txt_history.Text = txt_showops.Text + " = " + txt_display.Text + "\n" + txt_history.Text.ToString();

                    enter_operation = true;
                    enter_value     = true;
                    result          = new double();
                }
                else if (converation == "cosh")
                {
                    result           = Math.Cosh(Double.Parse(txt_display.Text));
                    txt_showops.Text = "cosh( " + txt_display.Text + " )";


                    txt_display.Text = result.ToString();

                    txt_history.Text = txt_showops.Text + " = " + txt_display.Text + "\n" + txt_history.Text.ToString();

                    enter_operation = true;
                    enter_value     = true;
                    result          = new double();
                }
                else if (converation == "tanh")
                {
                    result           = Math.Tanh(Double.Parse(txt_display.Text));
                    txt_showops.Text = "tanh( " + txt_display.Text + " )";


                    txt_display.Text = result.ToString();

                    txt_history.Text = txt_showops.Text + " = " + txt_display.Text + "\n" + txt_history.Text.ToString();

                    enter_operation = true;
                    enter_value     = true;
                    result          = new double();
                }
            }
        }
예제 #4
0
        // 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);
        }