示例#1
0
 public Token(TokenParser.Tokens name, string value)
 {
     TokenName = name;
     TokenValue = value;
 }
示例#2
0
        private static int GetPrecedence(TokenParser.Tokens token)
        {
            if (token == TokenParser.Tokens.Add || token == TokenParser.Tokens.Subtract)
                return 1;

            if (token == TokenParser.Tokens.Multiply || token == TokenParser.Tokens.Divide || token == TokenParser.Tokens.Modulus)
                return 2;

            if (token == TokenParser.Tokens.Exponent)
                return 3;

            if (token == TokenParser.Tokens.Lparen || token == TokenParser.Tokens.Rparen)
                return 4;

            return 0;
        }
示例#3
0
 private static bool IsOperator(TokenParser.Tokens token)
 {
     return token == TokenParser.Tokens.Add || token == TokenParser.Tokens.Divide || token == TokenParser.Tokens.Exponent ||
            token == TokenParser.Tokens.Modulus || token == TokenParser.Tokens.Multiply || token == TokenParser.Tokens.Subtract;
 }
示例#4
0
        public SimplificationReturnValue Simplify(string equation)
        {
            var retval = new SimplificationReturnValue { OriginalEquation = equation };

            if (equation.Trim().StartsWith("-") || equation.Trim().StartsWith("+"))
                equation = "0" + equation;
            equation = equation.Replace("(+", "(0+");
            equation = equation.Replace("(-", "(0-");
            equation = equation.Replace("( +", "( 0+");
            equation = equation.Replace("( -", "( 0-");
            equation = equation.Replace(",-", ",0-");
            equation = equation.Replace(", -", ", 0-");
            equation = equation.Replace(",+", ",0+");
            equation = equation.Replace(", +", ", 0+");

            var tp = new TokenParser();

            foreach (var cf in _customFunctions)
            {
                tp.RegisterCustomFunction(cf.Key);
            }

            tp.InputString = equation;

            Token token = tp.GetToken();

            _operatorStack.Clear();
            _outputQueue.Clear();

            while (token != null)
            {
                if (token.TokenName == TokenParser.Tokens.Sqrt)
                {
                    string expression = token.TokenValue.Substring(4, token.TokenValue.Length - 4);

                    SimplificationReturnValue rv = EvaluateExpression(new NumberClass
                                                                          {
                                                                              Expression = expression,
                                                                              NumberType = NumberClass.NumberTypes.Expression
                                                                          });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Sqrt(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Sqrt(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.Sin)
                {
                    string expression = token.TokenValue.Substring(3, token.TokenValue.Length - 3);

                    SimplificationReturnValue rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Sin(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Sin(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.Log)
                {
                    string expression = token.TokenValue.Substring(3, token.TokenValue.Length - 3);

                    SimplificationReturnValue rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Log(rv.IntValue, 10).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Log(rv.DoubleValue, 10).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.LogN)
                {
                    string expression = token.TokenValue.Substring(4, token.TokenValue.Length - 4);

                    SimplificationReturnValue rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Log(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Log(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.Tan)
                {
                    string expression = token.TokenValue.Substring(3, token.TokenValue.Length - 3);

                    var rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Tan(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Tan(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.Abs)
                {
                    string expression = token.TokenValue.Substring(3, token.TokenValue.Length - 3);

                    var rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Abs(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Abs(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if (token.TokenName == TokenParser.Tokens.Cos)
                {
                    string expression = token.TokenValue.Substring(3, token.TokenValue.Length - 3);

                    var rv =
                        EvaluateExpression(new NumberClass
                        {
                            Expression = expression,
                            NumberType = NumberClass.NumberTypes.Expression
                        });

                    token.TokenName = TokenParser.Tokens.Float;

                    switch (rv.ReturnType)
                    {
                        case SimplificationReturnValue.ReturnTypes.Integer:
                            token.TokenValue = Math.Cos(rv.IntValue).ToString();
                            break;
                        case SimplificationReturnValue.ReturnTypes.Float:
                            token.TokenValue = Math.Cos(rv.DoubleValue).ToString();
                            break;
                    }
                }
                if ((int)token.TokenName >= 100)
                {
                    int ndx1 = token.TokenValue.IndexOf("(");
                    string fn = token.TokenValue.Substring(0, ndx1);
                    string origExpression = token.TokenValue.Substring(ndx1);
                    string[] expressions = origExpression.Replace(",", "),(").Split(',');
                    bool found = false;

                    foreach(var _f in _customFunctions)
                    {
                        if(_f.Key.Equals(fn))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        foreach (var ff in _customFunctions)
                        {
                            if (ff.Key.Equals(fn))
                            {
                                var p = new Parser();
                                foreach (var cfr in _customFunctions)
                                    p.AddCustomFunction(cfr.Key, cfr.Value);
                                foreach (var vr in _variables)
                                    p.AddVariable(vr.Key, vr.Value);
                                foreach (var vf in _functions)
                                    p.AddFunction(vf.Name, vf.Arguments, vf.Expression);

                                var ex = new SimplificationReturnValue[expressions.Length];

                                for(var i = 0; i < expressions.Length; i++)
                                {
                                    ex[i] = p.Simplify(expressions[i]);
                                }

                                object funcRetval = null;

                                if (ff.Value.Method.ReturnType == typeof(int))
                                {
                                    var intParams = new object[ex.Length];
                                    int ndx = 0;

                                    foreach (var pp in ex)
                                    {
                                        if (pp.ReturnType == SimplificationReturnValue.ReturnTypes.Float)
                                            intParams[ndx] = (int)pp.DoubleValue;
                                        if (pp.ReturnType == SimplificationReturnValue.ReturnTypes.Integer)
                                            intParams[ndx] = pp.IntValue;
                                        ndx++;
                                    }
                                    funcRetval = ff.Value.DynamicInvoke(intParams);
                                }
                                if (ff.Value.Method.ReturnType == typeof(double))
                                {
                                    var floatParams = new object[ex.Length];
                                    int ndx = 0;

                                    foreach (var pp in ex)
                                    {
                                        if (pp.ReturnType == SimplificationReturnValue.ReturnTypes.Float)
                                            floatParams[ndx] = pp.DoubleValue;
                                        if (pp.ReturnType == SimplificationReturnValue.ReturnTypes.Integer)
                                            floatParams[ndx] = pp.IntValue;
                                        ndx++;
                                    }
                                    funcRetval = ff.Value.DynamicInvoke(floatParams);
                                }
                                if (ff.Value.Method.ReturnType==typeof(object))
                                {
                                    var ex2 = new SimplificationReturnValue[expressions.Length];

                                    for(var i = 0; i < ex2.Length; i++)
                                        ex2[i] = p.Simplify(expressions[i]);

                                    funcRetval = ff.Value.DynamicInvoke(ex2);
                                }

                                //object funcRetval = ff.Value.DynamicInvoke(expressions.Select(p.Simplify).ToArray());

                                if (funcRetval is double)
                                {
                                    token.TokenValue = ((double)funcRetval).ToString();
                                    token.TokenName = TokenParser.Tokens.Float;
                                }
                                if (funcRetval is int)
                                {
                                    token.TokenValue = ((int)funcRetval).ToString();
                                    token.TokenName = TokenParser.Tokens.Integer;
                                }
                                if (funcRetval is SimplificationReturnValue)
                                {
                                    var srv = (SimplificationReturnValue)funcRetval;
                                    if (srv.ReturnType == SimplificationReturnValue.ReturnTypes.Integer)
                                    {
                                        token.TokenValue = srv.IntValue.ToString();
                                        token.TokenName = TokenParser.Tokens.Integer;
                                    }
                                    if (srv.ReturnType == SimplificationReturnValue.ReturnTypes.Float)
                                    {
                                        token.TokenValue = srv.DoubleValue.ToString();
                                        token.TokenName = TokenParser.Tokens.Float;
                                    }
                                }
                                break;
                            }
                        }
                    }

                    if (!found)
                    {
                        throw new NoSuchFunctionException(StringResources.No_such_function_defined + ": " + fn);
                    }
                }

                if (token.TokenName == TokenParser.Tokens.Function)
                {
                    int ndx1 = token.TokenValue.IndexOf("(");
                    string fn = token.TokenValue.Substring(0, ndx1).Remove(0, 4);
                    string origExpression = token.TokenValue.Substring(ndx1);
                    string[] expressions = origExpression.Replace(",", "),(").Split(',');
                    bool found = false;
                    FunctionClass fun = null;

                    foreach(var _f in _functions)
                    {
                        if(_f.Name.Equals(fn))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        foreach (var ff in _functions)
                            if (ff.Name.Equals(fn))
                                fun = ff;
                    }

                    if (!found)
                    {
                        throw new NoSuchFunctionException(StringResources.No_such_function_defined + ": " + fn);
                    }

                    var parser = new Parser();
                    foreach (var cfh in _customFunctions)
                        parser.AddCustomFunction(cfh.Key, cfh.Value);

                    foreach (var v in _variables)
                    {
                        if (v.Value.NumberType == NumberClass.NumberTypes.Float)
                        {
                            parser.AddVariable(v.Key, v.Value.FloatNumber);
                        }
                        if (v.Value.NumberType == NumberClass.NumberTypes.Integer)
                        {
                            parser.AddVariable(v.Key, v.Value.IntNumber);
                        }
                        if (v.Value.NumberType == NumberClass.NumberTypes.Expression)
                        {
                            parser.AddVariable(v.Key, v.Value.Expression);
                        }
                    }

                    foreach (var f in _functions)
                    {
                        parser.AddFunction(f.Name, f.Arguments, f.Expression);
                    }
                    var expressionList = new List<NumberClass>();

                    foreach (var expression in expressions)
                    {
                        SimplificationReturnValue simRetval = parser.Simplify(expression);

                        var numClass = new NumberClass();
                        if (simRetval.ReturnType == SimplificationReturnValue.ReturnTypes.Float)
                        {
                            numClass.FloatNumber = simRetval.DoubleValue;
                            numClass.NumberType = NumberClass.NumberTypes.Float;
                        }
                        if (simRetval.ReturnType == SimplificationReturnValue.ReturnTypes.Integer)
                        {
                            numClass.IntNumber = simRetval.IntValue;
                            numClass.NumberType = NumberClass.NumberTypes.Integer;
                        }
                        expressionList.Add(numClass);
                    }

                    if (fun != null)
                    {
                        var numClass = new NumberClass { NumberType = NumberClass.NumberTypes.Expression, Expression = fun.Expression };

                        SimplificationReturnValue sretval = parser.EvaluateFunction(numClass, fun, expressionList);

                        if (sretval != null && sretval.ReturnType == SimplificationReturnValue.ReturnTypes.Integer)
                        {
                            token.TokenName = TokenParser.Tokens.Integer;
                            token.TokenValue = sretval.IntValue.ToString();
                        }
                        if (sretval != null && sretval.ReturnType == SimplificationReturnValue.ReturnTypes.Float)
                        {
                            token.TokenName = TokenParser.Tokens.Float;
                            token.TokenValue = sretval.DoubleValue.ToString();
                        }
                    }
                }

                if (token.TokenName == TokenParser.Tokens.Variable)
                {
                    if (_variables.ContainsKey(token.TokenValue))
                    {
                        var z = _variables[token.TokenValue];

                        if (z.NumberType == NumberClass.NumberTypes.Float)
                        {
                            token.TokenName = TokenParser.Tokens.Float;
                            token.TokenValue = z.FloatNumber.ToString();
                        }
                        else if (z.NumberType == NumberClass.NumberTypes.Integer)
                        {
                            token.TokenName = TokenParser.Tokens.Integer;
                            token.TokenValue = z.IntNumber.ToString();
                        }
                    }
                    else
                    {
                        throw new NoSuchVariableException(StringResources.Undefined_Variable + ": " + token.TokenValue);
                    }
                }

                if (token.TokenName == TokenParser.Tokens.Whitespace || token.TokenName == TokenParser.Tokens.Newline)
                {
                    token = tp.GetToken();
                    continue;
                }
                if (token.TokenName == TokenParser.Tokens.Integer || token.TokenName == TokenParser.Tokens.Float)
                {
                    var nc = new NumberClass();

                    switch (token.TokenName)
                    {
                        case TokenParser.Tokens.Float:
                            nc.NumberType = NumberClass.NumberTypes.Float;
                            nc.FloatNumber = double.Parse(token.TokenValue);
                            break;
                        case TokenParser.Tokens.Integer:
                            nc.NumberType = NumberClass.NumberTypes.Integer;
                            nc.IntNumber = int.Parse(token.TokenValue);
                            break;
                    }
                    _outputQueue.Enqueue(nc);
                }
                if (IsOperator(token.TokenName))
                {
                    if (_operatorStack.Count > 0)
                    {
                        while (_operatorStack.Count > 0)
                        {
                            var op = _operatorStack.Peek(); //o2

                            if (op == "(" || op == ")")
                                break;
                            if ((GetPrecedence(token.TokenName) <= GetPrecedence(op) &&
                                 IsLeftAssociative(token.TokenValue)) ||
                                !IsLeftAssociative(token.TokenValue) &&
                                GetPrecedence(token.TokenName) < GetPrecedence(op))
                            {
                                op = _operatorStack.Pop();
                                var nc = new NumberClass { NumberType = NumberClass.NumberTypes.Operator, Operator = op };

                                _outputQueue.Enqueue(nc);
                            }
                            else break;
                        }
                    }
                    _operatorStack.Push(token.TokenValue);
                }
                if (token.TokenName == TokenParser.Tokens.Lparen)
                    _operatorStack.Push(token.TokenValue);
                if (token.TokenName == TokenParser.Tokens.Rparen)
                {
                    if (_operatorStack.Count > 0)
                    {
                        var op = _operatorStack.Pop();

                        while (op != "(")
                        {
                            var nc = new NumberClass { Operator = op, NumberType = NumberClass.NumberTypes.Operator };

                            _outputQueue.Enqueue(nc);

                            if (_operatorStack.Count > 0)
                                op = _operatorStack.Pop();
                            else
                            {
                                throw new MismatchedParenthesisException();
                            }
                        }
                    }
                    else
                    {
                        throw new MismatchedParenthesisException();
                    }
                }
                token = tp.GetToken();
            }

            while (_operatorStack.Count > 0)
            {
                var op = _operatorStack.Pop();

                if (op == "(" || op == ")")
                {
                    throw new MismatchedParenthesisException();
                }

                var nc = new NumberClass { NumberType = NumberClass.NumberTypes.Operator, Operator = op };

                _outputQueue.Enqueue(nc);
            }

            bool floatAnswer = false;
            bool slashAnswer = false;

            foreach(var v in _outputQueue)
            {
                if(v.NumberType == NumberClass.NumberTypes.Float)
                {
                    floatAnswer = true;
                }

                if(v.Operator == "/")
                {
                    slashAnswer = true;
                }
            }

            if (floatAnswer || slashAnswer)
            {
                var dblStack = new Stack<double>();

                foreach (var nc in _outputQueue)
                {
                    if (nc.NumberType == NumberClass.NumberTypes.Integer)
                        dblStack.Push(nc.IntNumber);

                    if (nc.NumberType == NumberClass.NumberTypes.Float)
                        dblStack.Push(nc.FloatNumber);

                    if (nc.NumberType == NumberClass.NumberTypes.Operator)
                    {
                        double val = DoMath(nc.Operator, dblStack.Pop(), dblStack.Pop());
                        dblStack.Push(val);
                    }
                }

                if (dblStack.Count == 0)
                    throw new CouldNotParseExpressionException();

                retval.DoubleValue = dblStack.Pop();
                retval.ReturnType = SimplificationReturnValue.ReturnTypes.Float;
            }
            else
            {
                var intStack = new Stack<int>();

                foreach (var nc in _outputQueue)
                {
                    if (nc.NumberType == NumberClass.NumberTypes.Integer)
                        intStack.Push(nc.IntNumber);

                    if (nc.NumberType == NumberClass.NumberTypes.Float)
                        intStack.Push((int)nc.FloatNumber);

                    if (nc.NumberType == NumberClass.NumberTypes.Operator)
                    {
                        int val = DoMath(nc.Operator, intStack.Pop(), intStack.Pop());
                        intStack.Push(val);
                    }
                }

                if (intStack.Count == 0)
                    throw new CouldNotParseExpressionException();

                retval.IntValue = intStack.Pop();
                retval.ReturnType = SimplificationReturnValue.ReturnTypes.Integer;
            }

            return retval;
        }