예제 #1
0
        static void Main(string[] args)
        {
            var calc = new CalcString(new PolishNotationConvertor());

            calc.Operators.Add(new Operator('^', (a) => Math.Pow(a[0], a[1]), 2, Priority.Highest)); //Пример добавления нового оператора
            calc.Operators.Add(new Operator('%', (a) => a[0] % a[1], 2, Priority.Highest));
            calc.Operators.Add(new Operator('s', (a) => Math.Sqrt(a[0]), 1, Priority.Highest));      //Добавление унарного оператора

            Console.Write("Введите строку для расчета. Для выхода введите \"exit\".\n> ");
            string s = Console.ReadLine();

            while (s.ToLower() != "exit")
            {
                try
                {
                    Console.WriteLine("> " + calc.Calculate(s));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Ошибка: " + ex.Message);
                }
                Console.Write("> ");
                s = Console.ReadLine();
            }
        }
예제 #2
0
        // Concatenates two strings.
        public static CalcValue BinPlusStrings(CalcObject left, CalcObject right, CLLocalStore vars, CLContextProvider context)
        {
            CalcString strLeft  = left as CalcString;
            CalcString strRight = right as CalcString;

            return(new CalcString(strLeft + strRight));
        }
예제 #3
0
        // Returns the string, reversed.
        public static CalcValue PreMinusString(CalcObject param, CLLocalStore vars, CLContextProvider context)
        {
            CalcString strParam = param as CalcString;

            char[] chars = strParam.Value.ToCharArray();
            Array.Reverse(chars);

            return(new CalcString(new string(chars)));
        }
예제 #4
0
        // Multiplies a string by a number.
        public static CalcValue BinTimesString(CalcObject left, CalcObject right, CLLocalStore vars, CLContextProvider context)
        {
            CalcString strLeft  = left as CalcString;
            CalcNumber numRight = right as CalcNumber;

            int count = (int)numRight;

            if (count < 0)
            {
                throw new CLException("Strings cannot be repeated negative times.");
            }

            string strRet = "";

            for (int i = 0; i < count; i++)
            {
                strRet += strLeft;
            }

            return(new CalcString(strRet));
        }
        // Parses a single "operation chain"
        private static CalcObject ParseChain(List <CLObjectPiece> pieces)
        {
            // First, we can't parse an empty list.
            if (pieces.Count == 0)
            {
                throw new CLSyntaxException("Empty list received.", 0);
            }

            LinkedList <CLExpressionBuilder> exps = new LinkedList <CLExpressionBuilder>();
            CalcObject hold      = null;
            bool       valueLast = false;

            // Loop through all the pieces now.
            while (pieces.Count != 0)
            {
                CLObjectPiece piece = pieces[0];

                // Get the next value, if there is one.
                CalcObject obj = null;
                bool       err = false;

                // If it's a ()[]},
                if (piece.Type == CLObjectPieceType.Spacer)
                {
                    if (piece.Contents == "(")
                    {
                        if (!valueLast)
                        {
                            obj = ParseParentheses(pieces);
                        }
                        else
                        {
                            err = true;
                        }
                    }
                    else if (piece.Contents == "[")
                    {
                        if (!valueLast)
                        {
                            obj = ParseList(pieces);
                        }
                        else
                        {
                            err = true;
                        }
                    }
                    else /* ], ), }, , */
                    {
                        // Send control back up a parser level
                        break;
                    }
                }
                else if (piece.Type == CLObjectPieceType.FunctionName)
                {
                    if (!valueLast)
                    {
                        obj = ParseFunction(pieces);
                    }
                    else
                    {
                        err = true;
                    }
                }
                else if (piece.Type == CLObjectPieceType.Number)
                {
                    if (!valueLast)
                    {
                        obj = new CalcNumber(Decimal.Parse(piece.Contents));
                        pieces.RemoveAt(0);
                    }
                    else
                    {
                        err = true;
                    }
                }
                else if (piece.Type == CLObjectPieceType.String)
                {
                    if (!valueLast)
                    {
                        // Strip the quotes
                        string check = piece.Contents.Substring(1, piece.Contents.Length - 2);
                        // Parse special characters
                        check = check.Replace(@"\\", "\uF000")
                                .Replace(@"\n", "\n")
                                .Replace(@"\t", "\t")
                                .Replace(@"\", "")
                                .Replace("\uF000", @"\");
                        obj = new CalcString(check);
                        pieces.RemoveAt(0);
                    }
                    else
                    {
                        err = true;
                    }
                }

                if (err)
                {
                    throw new CLSyntaxException("Two consecutive values", piece.Position);
                }

                // If there's a value, put it in the most recent expression
                if (obj != null)
                {
                    valueLast = true;

                    // If there's no expression, just hold the value.
                    if (exps.Count == 0)
                    {
                        hold = obj;
                    }
                    else
                    {
                        // Put it on the most recent expression
                        CLExpressionBuilder exp = exps.Last.Value;
                        exp.Right = obj;
                    }

                    continue;
                }

                // Otherwise, this piece must be an operator.
                CLExpressionBuilder expNew = new CLExpressionBuilder();
                CLOperator          op     = null;
                valueLast = false;

                if (piece.Type == CLObjectPieceType.BinaryOperator)
                {
                    op = CLOperators.BinaryOperators[piece.Contents];
                }
                else if (piece.Type == CLObjectPieceType.PrefixOperator)
                {
                    op = CLOperators.PrefixOperators[piece.Contents];
                }
                else if (piece.Type == CLObjectPieceType.PostfixOperator)
                {
                    op = CLOperators.PostfixOperators[piece.Contents];
                }

                expNew.Operator = op;

                // If it's the first operator...
                if (exps.Count == 0)
                {
                    // ... use the held value if one exists
                    if (hold != null)
                    {
                        expNew.Left = hold;
                    }
                    exps.AddLast(expNew);
                }
                // Otherwise...
                else
                {
                    // For prefix operators we don't need to check priorities to the
                    // left. They can just stack on in.
                    if (op is CLPrefixOperator)
                    {
                        exps.Last.Value.Right = expNew;
                        exps.AddLast(expNew);
                    }
                    else
                    {
                        CLExpressionBuilder expOld  = null;
                        CLExpressionBuilder expNext = null;
                        // This code removes expressions from the stack that are a
                        // higher priority than the one being removed, or that are
                        // postfix.
                        while (exps.Count != 0)
                        {
                            expNext = exps.Last.Value;
                            if (
                                // The next expression is a postfix expression.
                                expNext.Operator is CLPostfixOperator ||
                                // The next expression on the stack is still higher
                                // priority
                                expNext.Operator.Priority > op.Priority ||
                                // The next expression on the stack is equal priority,
                                // but evaluated left-to-right
                                (expNext.Operator.Priority == op.Priority &&
                                 !CLOperators.IsFromRight(op.Priority))
                                )
                            {
                                expOld = exps.Last.Value;
                                exps.RemoveLast();
                                expNext = null;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // The last removed expression becomes the left of this one.
                        // (If there's no such expression, then the right of the next
                        // expression on the stack becomes our left.)
                        if (expOld != null)
                        {
                            expNew.Left = expOld;
                        }
                        else
                        {
                            expNew.Left = expNext.Right;
                        }

                        // Then, this expression becomes the right of the next one.
                        if (expNext != null)
                        {
                            expNext.Right = expNew;
                        }

                        exps.AddLast(expNew);
                    }
                }

                pieces.RemoveAt(0);
            }

            if (exps.Count == 0)
            {
                return(hold);
            }
            else
            {
                return(exps.First.Value.Build());
            }
        }
예제 #6
0
        private void calc(string input)
        {
            if (CurrentValue == "NaN")
            {
                CurrentValue = "";
            }
            Regex isNumber = new Regex(@"^\d$");

            if (isNumber.IsMatch(input))
            {
                CurrentValue += input;
                CurrentValue  = format(CurrentValue);
            }
            else if (input == "🗑")
            {
                Historique.Clear();
            }
            else if (input == "C")
            {
                CalcString   = "";
                CurrentValue = "";
            }
            else if (input == "CE")
            {
                CurrentValue = "";
            }
            else if (input == "=")
            {
                if (CalcString.Length > 0)
                {
                    if (CurrentValue.Length == 0 && CalcString.Substring(CalcString.Length - 1) != "!" && CalcString.Substring(CalcString.Length - 1) != ")")
                    {
                        CalcString = CalcString.Substring(0, CalcString.Length - 1);
                    }
                    CalcString += CurrentValue;
                    if (CalcString.Count(x => x == '(') > CalcString.Count(x => x == ')'))
                    {
                        int numberOfOpen  = CalcString.Count(x => x == '(');
                        int numberOfClose = CalcString.Count(x => x == ')');
                        int rest          = numberOfOpen - numberOfClose;
                        for (int i = 0; i < rest; i++)
                        {
                            CalcString += ')';
                        }
                    }
                    CalcString = CalcString.Replace(",", ".");
                    org.mariuszgromada.math.mxparser.Expression expression = new org.mariuszgromada.math.mxparser.Expression(new string(CalcString.ToCharArray().Where(c => !Char.IsWhiteSpace(c)).ToArray()));
                    double result = expression.calculate();
                    CurrentValue = format(result.ToString());
                    Historique.Add(new Calcul(CalcString, format(result.ToString())));
                    CalcString = "";
                }
            }
            else if (input == ",")
            {
                if (CurrentValue.IndexOf(',') == -1 && CurrentValue.Length != 0)
                {
                    CurrentValue += input;
                }
            }
            else if (input == "(")
            {
                CalcString += input;
            }
            else if (input == ")")
            {
                CalcString  += CurrentValue + ")";
                CurrentValue = "";
            }
            else
            {
                // Supprime la virgule en fin de lignesi un opérateur est choisie
                if (CurrentValue.Length > 0 && CurrentValue.Substring(CurrentValue.Length - 1) == ",")
                {
                    CurrentValue = CurrentValue.Substring(0, CurrentValue.Length - 1);
                }
                // Ajoute un opérateur s'il y a déjà une valeur enregistré
                if (CurrentValue != "" || (CalcString.Length > 0 && CalcString.Substring(CalcString.Length - 1) == "!") || (CalcString.Length > 0 && CalcString.Substring(CalcString.Length - 1) == ")"))
                {
                    CalcString  += CurrentValue + input;
                    CurrentValue = "";
                }
                else if (CalcString.Length > 0)
                {
                    CalcString = CalcString.Substring(0, CalcString.Length - 1) + input;
                }
                if (input == "-" && CalcString.Length == 0)
                {
                    CalcString = "0-";
                }
            }
        }
예제 #7
0
 public void CreateCalcStringNullTest()
 {
     calc = new CalcString(null);
 }