Exemplo n.º 1
0
        //holds operands and alwasys both
        //however if exactly unary function - meaningfull just right
        //the left will be empty

        public Operation(string name, FormulaObject _left, FormulaObject _right)
        {
            if (!OperationDictionary.ContainsKey(name))
            {
                throw new Exception("Unacceptable formula : " + name);
            }
            index        = OperationDictionary[name];
            left         = _left;
            right        = _right;
            wasActivated = false;
        }
Exemplo n.º 2
0
        //this class reshape the text of formula to
        //it's binary tree of computing
        //so any node (which roly is being playing by FormulaObject - it's just node container)
        //contains either operation and forks (operands) or constant
        //so we need FormulaObject just for these purpose - unified Container

        public Function(string formula)
        {
            if (formula == null)
            {
                throw new Exception("Empty Formula");
            }
            formula = formula.ToLower().Trim(' ');
            //there the formula is being prePared for parsing and transforms onto simplified form

            List <FormulaObject> parsedFormula = new List <FormulaObject>();

            parsedFormula = new List <FormulaObject>();
            //this list will hold the sequence of recognized FormulaObjects

            int parenthesesCounter = 0;

            //if we need to properly parse formula we have to notify if parentheses are positioned correctly
            //therefore keep the count of still opened parentheses

            for (int i = 0; i < formula.Length;)
            //and going through the text formula
            {
                if (formula[i] == '(')
                //if we meet the Opening Parenthese - we are looking for it's end
                //if there is no end - "parenthesesCounter" will let us know
                {
                    parenthesesCounter++;
                    string inParenteses = "";
                    //here will be the part which stay in parentheses

                    ++i;
                    while (i < formula.Length && parenthesesCounter > 0)
                    //going down and seek the end
                    //by the way recording the internal part
                    {
                        if (formula[i] == '(')
                        {
                            parenthesesCounter++;
                        }
                        if (formula[i] == ')')
                        {
                            parenthesesCounter--;
                        }
                        if (parenthesesCounter > 0)
                        {
                            inParenteses += formula[i];
                        }
                        i++;
                    }
                    Function FuncinParentheses = new Function(inParenteses);
                    //we need to calculate the part in parentheses earlier than any another operation
                    //so let's assume this part is independent formula
                    // and put on this place already parsed tree of it
                    parsedFormula.Add(FuncinParentheses.root);
                    i++;
                }
                else if (Char.IsDigit(formula[i]))
                //here we check if numeric value was began parsing
                //and in the same way recognise it's value and create constant, adding it to formula
                {
                    double value = 0;
                    while (i < formula.Length && Char.IsDigit(formula[i]))
                    {
                        value = value * 10 + formula[i++] - '0';
                    }
                    if (i < formula.Length && (formula[i] == '.' || formula[i] == ','))
                    {
                        ++i;
                        double divider = 10;
                        while (i < formula.Length && Char.IsDigit(formula[i]))
                        {
                            value   += (formula[i++] - '0') / divider;
                            divider *= 10;
                        }
                    }
                    parsedFormula.Add(new Const(value));
                }
                else if (Operation.CharIsOperatorPart(formula[i]))
                //if char is operator part - we need to read only one it's symbol
                //there is impossible to let the operator have two symbols by the definition
                //try to define it and push back to the parsed formula
                {
                    if (formula[i] == '-' &&
                        (parsedFormula.Count == 0 ||
                         (parsedFormula[parsedFormula.Count - 1] is Operation) &&
                         (parsedFormula[parsedFormula.Count - 1] as Operation).index < 13))
                    {
                        parsedFormula.Add(new Operation("opposite", new FormulaObject(), new FormulaObject()));
                        i++;
                    }
                    else
                    {
                        parsedFormula.Add(new Operation("" + formula[i++], new FormulaObject(), new FormulaObject()));
                    }
                    //here is solving the problem of '-' definition
                    //it can be the unary and equally likely to be binary
                    //so we need to look it's predecessor
                    //if const - only binary, else - only unary because of standart math syntax
                }
                else if (Operation.CharIsMethodPart(formula[i]))
                {
                    string formulaName = "";
                    while (i < formula.Length && Operation.CharIsMethodPart(formula[i]))
                    {
                        formulaName += formula[i++];
                    }
                    parsedFormula.Add(new Operation(formulaName, new FormulaObject(), new FormulaObject()));
                    //here we read the full operation (Method) name and push it at the end of formula
                }
                else if (formula[i++] != ' ')
                {
                    throw new Exception("Unacceptable symbol : " + formula[i]);
                }
            }
            if (parenthesesCounter != 0)
            {
                throw new Exception("Uncorrect parentheses arrangement");
            }
            //and we should check if all parentheses are correct
            //if not - stop working - the result has no matter

            for (int priority = 10; priority > 0; --priority)
            //looking for the most priority operations in funtion
            //and assign them their operands
            //there we must use field wasActivated not to let operators be assigned twice
            {
                for (int i = parsedFormula.Count - 1; i >= 0; --i)
                {
                    if (parsedFormula[i] is Operation &&
                        (parsedFormula[i] as Operation).Priority() == priority &&
                        (parsedFormula[i] as Operation).ArgumentsCount() == 1 &&
                        (parsedFormula[i] as Operation).wasActivated == false)
                    {
                        (parsedFormula[i] as Operation).right        = parsedFormula[i + 1];
                        (parsedFormula[i] as Operation).wasActivated = true;
                        parsedFormula.RemoveAt(i + 1);
                    }
                }
                //check the unary functions from right to left
                //note: to let cos cos cos cos x be computed witho
                for (int i = 0; i < parsedFormula.Count; ++i)
                {
                    if (parsedFormula[i] is Operation &&
                        (parsedFormula[i] as Operation).Priority() == priority &&
                        (parsedFormula[i] as Operation).ArgumentsCount() == 2 &&
                        (parsedFormula[i] as Operation).wasActivated == false)
                    {
                        (parsedFormula[i] as Operation).right        = parsedFormula[i + 1];
                        (parsedFormula[i] as Operation).left         = parsedFormula[i - 1];
                        (parsedFormula[i] as Operation).wasActivated = true;

                        parsedFormula.RemoveAt(i + 1);
                        parsedFormula.RemoveAt(i - 1);
                        i = 0;
                    }
                }
                //and the binary from left to right
            }
            if (parsedFormula.Count != 1)
            {
                throw new Exception("Unacceptable formula");
            }
            //check all formula was reduced up to singular tree

            root = parsedFormula[0];
        }