コード例 #1
0
        /// <summary>
        /// Converts a non decimal number to decimal.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string AsDecimal(string value)
        {
            string number = value;
            int    length = number.Length - 1;

            if (NumberToken.__binNumberPattern.IsMatch(number))
            {
                number = Convert.ToInt64(number.Substring(0, length), 2).ToString();

                CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("2");
            }
            else if (NumberToken.__octNumberPattern.IsMatch(number))
            {
                number = Convert.ToInt64(number.Substring(0, length), 8).ToString();

                CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("8");
            }
            else if (NumberToken.__hexNumberPattern.IsMatch(number))
            {
                number = Convert.ToInt64(number.Substring(0, length), 16).ToString();

                CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("16");
            }
            else
            {
                CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("10");
            }

            return(number);
        }
コード例 #2
0
        /// <summary>
        /// Gets the next token while within ta prefix function token parse state.
        /// </summary>
        /// <param name="internalLine"></param>
        /// <param name="token"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public override bool GetNextToken(string internalLine, out Token token, out TokenParseState state)
        {
            bool  result    = false;
            Token lastToken = CalculatorContext.GetInstance()[CalculatorContext.LastToken];

            if ((result = (PerenthesisToken.TryParse(internalLine, out token) && ((PerenthesisToken)token).PerenthesisType == PerenthesisTokenType.Open)))
            {
                state = new PerenthesisTokenParseState();
            }
            else if (lastToken.ToString().Equals("!", StringComparison.InvariantCultureIgnoreCase))
            {
                if ((result = BooleanToken.TryParse(internalLine, out token) || ConstantToken.TryParse(internalLine, out token) || NumberToken.TryParse(internalLine, out token)))
                {
                    state = new ValueTokenParseState();
                }
                else if ((result = VariableToken.TryParse(internalLine, out token)))
                {
                    state = new VariableTokenParseState();
                }
                else
                {
                    state = new InvalidTokenParseState();
                }
            }
            else
            {
                state = new InvalidTokenParseState();
            }

            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Determines whether the last result was implied in the expression and if it was, adds the last result to the token collection.
        /// </summary>
        private void CheckForLastResultImplication()
        {
            if (_context.LastResultIsImplied)
            {
                _tokens.Add(CalculatorContext.GetInstance()[CalculatorContext.LastResult]);

                _context[CalculatorContext.LastToken] = _tokens[0];

                CalculatorContext.GetInstance().LastResultIsImplied = false;
            }
        }
コード例 #4
0
        /// <summary>
        /// Gets a reference to the singleton instance of CalculatorContext.
        /// </summary>
        /// <returns></returns>
        public static CalculatorContext GetInstance()
        {
            if (CalculatorContext.__instance == null)
            {
                lock (CalculatorContext.__lockObject)
                {
                    CalculatorContext.__instance = new CalculatorContext();
                }
            }

            return(CalculatorContext.__instance);
        }
コード例 #5
0
        /// <summary>
        /// Evaluates this expression.
        /// </summary>
        /// <returns></returns>
        public override Token Evaluate()
        {
            Token result = new NullToken();
            Token left   = Operands[1].Evaluate();
            Token right  = Operands[0].Evaluate();

            if (left is VariableToken)
            {
                result = right;

                CalculatorContext.GetInstance()[left.ToString()] = result;
            }

            return(result);
        }
コード例 #6
0
        /// <summary>
        /// Negates the value of this VariableToken.
        /// </summary>
        /// <returns></returns>
        public new Token Negate()
        {
            if (CalculatorContext.GetInstance().ContainsKey(ToString()))
            {
                Token value = CalculatorContext.GetInstance()[ToString()];

                if (value is NumberToken)
                {
                    value = ((NumberToken)value).Negate();
                }

                CalculatorContext.GetInstance()[ToString()] = value;
            }

            return(this);
        }
コード例 #7
0
        /// <summary>
        /// Gets the next token while in the set container token parse state.
        /// </summary>
        /// <param name="internalLine"></param>
        /// <param name="token"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public override bool GetNextToken(string internalLine, out Token token, out TokenParseState state)
        {
            bool  result    = false;
            Token lastToken = CalculatorContext.GetInstance()[CalculatorContext.LastToken];

            if ((result = SetContainerToken.TryParse(internalLine, out token) && ((SetContainerToken)token).SetContainerType == ((SetContainerToken)lastToken).SetContainerType))
            {
                state = new SetContainerTokenParseState();
            }
            else if ((result = CommentToken.TryParse(internalLine, out token)))
            {
                state = new NullTokenParseState();
            }
            else if (((SetContainerToken)lastToken).SetContainerType == SetContainerTokenType.Open)
            {
                if ((result = PrefixFunctionToken.TryParse(internalLine, out token)))
                {
                    state = new PrefixFunctionTokenParseState();
                }
                else if ((result = BooleanToken.TryParse(internalLine, out token) || ConstantToken.TryParse(internalLine, out token) || NumberToken.TryParse(internalLine, out token) || LastResultToken.TryParse(internalLine, out token)))
                {
                    state = new ValueTokenParseState();
                }
                else if ((result = VariableToken.TryParse(internalLine, out token)))
                {
                    state = new VariableTokenParseState();
                }
                else
                {
                    state = new InvalidTokenParseState();
                }
            }
            else if ((result = InfixFunctionToken.TryParse(internalLine, out token) || ArithmeticOperatorToken.TryParse(internalLine, out token) || BinaryOperatorToken.TryParse(internalLine, out token) || BooleanOperatorToken.TryParse(internalLine, out token)))
            {
                state = new InfixOperationParseState();
            }
            else if ((result = PostfixFunctionToken.TryParse(internalLine, out token)))
            {
                state = new PostfixFunctionParseState();
            }
            else
            {
                state = new InvalidTokenParseState();
            }

            return(result);
        }
コード例 #8
0
        /// <summary>
        /// Performs an evaluation on an expression.
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static string PerformEvaluation(string strExpression)
        {
            CalculatorContext context          = CalculatorContext.GetInstance();
            string            strResult        = "0";
            ITokenizer        tokenizer        = new BpcTokenizer(strExpression);
            ITokenizer        postfixTokenizer = new PostfixTokenizer(tokenizer);
            Expression        expression       = ExpressionYard.Formulate(postfixTokenizer);
            Token             result           = expression.Evaluate();

            if (result is VariableToken)
            {
                result = context[result.ToString()];
            }

            strResult = String.Format("{0}", result);

            if (result is NumberToken)
            {
                if (context[CalculatorContext.DisplayBase].ToString().Equals(DisplayBase.BinaryBase, StringComparison.InvariantCultureIgnoreCase))
                {
                    strResult = ((NumberToken)result).AsBin();

                    DisplayBase.ResetDisplayBase();
                }
                else if (context[CalculatorContext.DisplayBase].ToString().Equals(DisplayBase.OctalBase, StringComparison.InvariantCultureIgnoreCase))
                {
                    strResult = ((NumberToken)result).AsOct();

                    DisplayBase.ResetDisplayBase();
                }
                else if (context[CalculatorContext.DisplayBase].ToString().Equals(DisplayBase.HexadecimalBase, StringComparison.InvariantCultureIgnoreCase))
                {
                    strResult = ((NumberToken)result).AsHex();

                    DisplayBase.ResetDisplayBase();
                }
            }
            else if (!(result is BooleanToken))
            {
                throw new Exception(String.Format("Unexpected token was returned as result. Type: {0} value: {1}", result.Type, result));
            }

            context[CalculatorContext.LastResult] = result;

            return(strResult);
        }
コード例 #9
0
        /// <summary>
        /// Evaluates a sub-expression.
        /// </summary>
        /// <param name="operandIndex"></param>
        /// <returns></returns>
        protected Token EvaluateOperand(int operandIndex)
        {
            Token evaluation = _operands[operandIndex].Evaluate();

            if (evaluation is VariableToken)
            {
                CalculatorContext context = CalculatorContext.GetInstance();

                if (context.ContainsKey(evaluation.ToString()))
                {
                    evaluation = context[evaluation.ToString()];
                }
                else
                {
                    throw new MalformedExpressionException(String.Format("Variable named {0} is not defined", evaluation));
                }
            }

            return(evaluation);
        }
コード例 #10
0
        /// <summary>
        /// Creates an instance of Program.
        /// </summary>
        /// <param name="args"></param>
        private Program(ProgramArguments args)
        {
            bool continueExecution = true;

            _context = CalculatorContext.GetInstance();

            if (args.Args.Count > 0)
            {
                continueExecution = HandleArguments(args.Args);
            }

            if (continueExecution)
            {
                if (String.IsNullOrEmpty(args.Expression))
                {
                    Interact();
                }
                else
                {
                    string[] expressions = GetExpressions(args.Expression);

                    foreach (string nextExpression in expressions)
                    {
                        try
                        {
                            Console.WriteLine("{0}", Evaluator.PerformEvaluation(nextExpression));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("{0}", ex.Message);
                            Environment.ExitCode = 1;
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine();
            }
        }
コード例 #11
0
        /// <summary>
        /// Gets the next Token if the last token was a NullToken. It first tries to get a normal,
        /// valid first token. If that fails, then it checks for a normal secondary token, and if
        /// that passes then the context LastResultIsImplied is set to true.
        /// </summary>
        /// <param name="internalLine"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public override bool GetNextToken(string internalLine, out Token token, out TokenParseState state)
        {
            bool result = false;

            if ((result = PerenthesisToken.TryParse(internalLine, out token)))
            {
                state = new PerenthesisTokenParseState();
            }
            else if ((result = PrefixFunctionToken.TryParse(internalLine, out token)))
            {
                state = new PrefixFunctionTokenParseState();
            }
            else if ((result = BooleanToken.TryParse(internalLine, out token) || ConstantToken.TryParse(internalLine, out token) || NumberToken.TryParse(internalLine, out token) || LastResultToken.TryParse(internalLine, out token)))
            {
                state = new ValueTokenParseState();
            }
            else if ((result = VariableToken.TryParse(internalLine, out token)))
            {
                state = new VariableTokenParseState();
            }
            else if ((result = InfixFunctionToken.TryParse(internalLine, out token) || ArithmeticOperatorToken.TryParse(internalLine, out token) || BinaryOperatorToken.TryParse(internalLine, out token) || BooleanOperatorToken.TryParse(internalLine, out token)))
            {
                state = new InfixOperationParseState();
                CalculatorContext.GetInstance().LastResultIsImplied = true;
            }
            else if ((result = PostfixFunctionToken.TryParse(internalLine, out token)))
            {
                state = new PostfixFunctionParseState();
                CalculatorContext.GetInstance().LastResultIsImplied = true;
            }
            else
            {
                state = new InvalidTokenParseState();
            }

            return(result);
        }
コード例 #12
0
        /// <summary>
        /// Gets a Token of type LastResultToken from the beginning of a line of text. The resulting token
        /// needs to be a value token, like BooleanToken or NumberToken.
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public new static Token Parse(string line)
        {
            Token token = new NullToken();

            if (LastResultToken.__constantPattern.IsMatch(line))
            {
                string matchText = LastResultToken.__constantPattern.Matches(line)[0].Value;

                if (matchText.Equals("$", StringComparison.InvariantCultureIgnoreCase))
                {
                    token = new LastResultToken(CalculatorContext.GetInstance().GetLastResult(), matchText);

                    Token intermediateToken = new NullToken();

                    if (NumberToken.TryParse(token.ToString(), out intermediateToken, true) ||
                        BooleanToken.TryParse(token.ToString(), out intermediateToken, true))
                    {
                        token = intermediateToken;
                    }
                }
            }

            return(token);
        }
コード例 #13
0
        /// <summary>
        /// Evaluates this expression.
        /// </summary>
        /// <returns></returns>
        public override Token Evaluate()
        {
            Token  result        = new NullToken();
            string op            = Operation.ToString();
            bool   modeIsDegrees = CalculatorContext.GetInstance()[CalculatorContext.Mode].ToString().Equals("deg", StringComparison.InvariantCultureIgnoreCase);

            if (Operation is PrefixFunctionToken)
            {
                Token  val = EvaluateOperand(0);
                double res = 0.0;

                if (double.TryParse(val.ToString(), out res))
                {
                    if (op.Equals("abs", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Abs(res)).ToString());
                    }
                    else if (op.Equals("cosh", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Cosh(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("sinh", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Sinh(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("tanh", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Tanh(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("cos", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Cos(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("sin", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Sin(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("tan", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (modeIsDegrees)
                        {
                            res = ToRadians(res);
                        }

                        res = Math.Tan(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("acos", StringComparison.InvariantCultureIgnoreCase))
                    {
                        res = modeIsDegrees ? ToDegrees(Math.Acos(res)) : Math.Acos(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("asin", StringComparison.InvariantCultureIgnoreCase))
                    {
                        res = modeIsDegrees ? ToDegrees(Math.Asin(res)) : Math.Acos(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("atan", StringComparison.InvariantCultureIgnoreCase))
                    {
                        res = modeIsDegrees ? ToDegrees(Math.Atan(res)) : Math.Acos(res);

                        result = new NumberToken(res.ToString());
                    }
                    else if (op.Equals("log", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Log10(res)).ToString());
                    }
                    else if (op.Equals("ln", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Log(res)).ToString());
                    }
                    else if (op.Equals("lb", StringComparison.InvariantCultureIgnoreCase) || op.Equals("ld", StringComparison.InvariantCultureIgnoreCase) || op.Equals("lg", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Log(res) / Math.Log(2.0)).ToString());
                    }
                    else if (op.Equals("deg", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((ToDegrees(res)).ToString());
                    }
                    else if (op.Equals("rad", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((ToRadians(res)).ToString());
                    }
                    else if (op.Equals("sqrt", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Sqrt(res)).ToString());
                    }
                    else if (op.Equals("too", StringComparison.InvariantCultureIgnoreCase))
                    {
                        CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("8");

                        result = new NumberToken(val);
                    }
                    else if (op.Equals("tod", StringComparison.InvariantCultureIgnoreCase))
                    {
                        CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("10");

                        result = new NumberToken(val);
                    }
                    else if (op.Equals("toh", StringComparison.InvariantCultureIgnoreCase))
                    {
                        CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("16");

                        result = new NumberToken(val);
                    }
                    else if (op.Equals("tob", StringComparison.InvariantCultureIgnoreCase))
                    {
                        CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("2");

                        result = new NumberToken(val);
                    }
                    else if (op.Equals("-", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((res * (-1)).ToString());
                    }
                    else if (op.Equals("!", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (val is BooleanToken)
                        {
                            result = ((BooleanToken)val).Not();
                        }
                        else if (val is NumberToken)
                        {
                            result = ((NumberToken)val).Negate();
                        }
                    }
                }
                else
                {
                    throw new FormatException(String.Format("Could not parse double value from {0}", val));
                }
            }
            else if (Operation is InfixFunctionToken)
            {
                Token  left   = EvaluateOperand(1);
                Token  right  = EvaluateOperand(0);
                double dLeft  = 0.0;
                double dRight = 0.0;

                if (double.TryParse(left.ToString(), out dLeft) && double.TryParse(right.ToString(), out dRight))
                {
                    if (op.Equals("**", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((Math.Pow(dLeft, dRight)).ToString());
                    }
                    else if (op.Equals("%", StringComparison.InvariantCultureIgnoreCase))
                    {
                        result = new NumberToken((dLeft % dRight).ToString());
                    }
                    else if (op.Equals("//", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if ((left is NumberToken && right is NumberToken))
                        {
                            long lLeft  = 0;
                            long lRight = 0;

                            if ((long.TryParse(((NumberToken)left).WholePart(), out lLeft) && long.TryParse(((NumberToken)right).WholePart(), out lRight)))
                            {
                                long rem   = 0;
                                long whole = Math.DivRem(lLeft, lRight, out rem);

                                result = new NumberToken(whole.ToString());
                            }
                        }
                        else
                        {
                            throw new FormatException(String.Format("Could not parse long values from {0} or {1}.", left, right));
                        }
                    }
                }
                else
                {
                    throw new FormatException(String.Format("Could not parse double values from {0} or {1}.", left, right));
                }
            }
            else if (Operation is PostfixFunctionToken)
            {
                Token  val = EvaluateOperand(0);
                double res = 0.0;

                if (double.TryParse(val.ToString(), out res))
                {
                    if (op.Equals("!", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (Operation is PostfixFunctionToken)
                        {
                            double counter = res;
                            double total   = counter;

                            while (counter > 1)
                            {
                                counter--;

                                total *= counter;
                            }

                            result = new NumberToken(total.ToString());
                        }
                    }
                }
                else
                {
                    throw new FormatException(String.Format("Could not parse double value from {0}", val));
                }
            }
            else
            {
                throw new InvalidTokenException(String.Format("Operation {0} not currently supported. Please submit a feature request.", Operation));
            }

            return(result);
        }
コード例 #14
0
 /// <summary>
 /// Resets the display base to 10.
 /// </summary>
 public static void ResetDisplayBase()
 {
     CalculatorContext.GetInstance()[CalculatorContext.DisplayBase] = new NumberToken("10", "10");
 }