Exemple #1
0
        public void SetVariableMethod()
        {
            ExpressionTree tree = new ExpressionTree("x+y");

            tree.SetVariable("x", 5.0);
            tree.SetVariable("y", 4.0);

            Assert.AreEqual("9", tree.Evaluate().ToString());
        }
        /// <summary>
        /// this is a main method which has direct interaction  with the user.
        /// </summary>
        /// <param name="args"> args.</param>
        public static void Main(string[] args)
        {
            string expression = "x+y";

            // create an instance of ExpressionTree class.
            ExpressionTree tree = new ExpressionTree(expression);

            // set varname and varVal to empty.
            string varName = string.Empty;
            string varVal  = string.Empty;

            do
            {
                Console.WriteLine("Menu (current expression =" + tree.InFixExpression + ")");
                MenuOption();
                string userInput = Console.ReadLine();
                Console.WriteLine();
                switch (userInput)
                {
                case "1":
                    // get a new expression and display the new expression
                    Console.WriteLine("Enter new epression: ");
                    tree = new ExpressionTree(Console.ReadLine());
                    break;

                case "2":
                    // reads the vraible name and varible value.
                    Console.WriteLine("Enter variable name:");
                    varName = Console.ReadLine();
                    Console.WriteLine("Enter variable value:");
                    string varValue = Console.ReadLine();

                    // if variable name is in the dictionary set new value to that otherwise add variable
                    // name and value pair in the dictionary
                    tree.SetVariable(varName, Convert.ToDouble(varValue));
                    break;

                case "3":
                    // evaluate the result of the expression.
                    Console.WriteLine(tree.Evaluate());
                    break;

                case "4":
                    System.Environment.Exit(0);
                    break;

                default:
                    Console.WriteLine("Invalid option. Try again");
                    break;
                }
            }while (true);
        }
        // post: displays a menu of options for the user to evaluate a given expression or enter their own
        public static void Main(string[] args)
        {
            string userInput = "0";

            ExpressionTree tree = new ExpressionTree("A1-12-C1");

            while (userInput != "4")
            {
                StringBuilder menu = new StringBuilder();
                menu.AppendLine("Menu (current expression = \"" + tree.expression + "\")");
                menu.AppendLine("   1 = Enter a new expression");
                menu.AppendLine("   2 = Set a variable value");
                menu.AppendLine("   3 = Evaluate Tree");
                menu.AppendLine("   4 = Quit");

                Console.WriteLine(menu);

                userInput = Console.ReadLine();

                switch (userInput)
                {
                case "1":
                    Console.WriteLine("Enter new expression: ");
                    string expression = Console.ReadLine();
                    tree = new ExpressionTree(expression);
                    break;

                case "2":
                    Console.Write("Enter variable name: ");
                    string varName = Console.ReadLine();
                    Console.Write("Enter variable value: ");
                    string varValue = Console.ReadLine();
                    double num;

                    while (!double.TryParse(varValue, out num))
                    {
                        Console.Write("Enter variable value: ");
                        varValue = Console.ReadLine();
                    }

                    tree.SetVariable(varName, num);
                    break;

                case "3":
                    Console.WriteLine(tree.Evaluate());
                    break;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Checks for a circular reference.
        /// </summary>
        /// <returns>Returns true if a circular reference is detected, false otherwise.</returns>
        private bool CircularReferenceCheck(Cell current, Cell other)
        {
            // Circular reference found!
            if (current.Equals(other))
            {
                return(true);
            }

            // Check that the expression includes an equals sign.
            string         otherText = other.Text;
            ExpressionTree et        = new ExpressionTree(otherText);

            if (otherText.StartsWith("="))
            {
                otherText = otherText.Substring(1);
            }

            // Split the string on operators and check for variables.
            bool        result   = false;
            List <Cell> cellList = new List <Cell>();

            foreach (string s in otherText.Split(et.Operators, StringSplitOptions.None))
            {
                if (!s.Equals(string.Empty))
                {
                    foreach (char c in s)
                    {
                        if (c < 48 || c > 57)
                        {
                            cellList.Add(this.GetCell(s));
                        }
                    }
                }
            }

            // Check that all variables within the list do not contain circular references, recursively.
            foreach (Cell c in cellList)
            {
                result = result || this.CircularReferenceCheck(current, c);
            }

            return(result);
        }
Exemple #5
0
        /// <summary>
        /// Updates the spreadsheet.
        /// </summary>
        /// <param name="sender">The sending object.</param>
        /// <param name="e">A property changed event arguments.</param>
        private void Sheet_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            try
            {
                if (!e.PropertyName.Contains("bgcolor"))
                {
                    int  row    = Convert.ToInt32(e.PropertyName.Split(' ')[0]);
                    int  column = Convert.ToInt32(e.PropertyName.Split(' ')[1]);
                    Cell cell   = this.Cells[row, column];

                    // Check to see if cell evaluation is necessary.
                    if (cell.Text.StartsWith("="))
                    {
                        // Check for a self-reference.
                        if (cell.Text.Contains(((char)(column + 65)).ToString() + (row + 1)) || cell.Text.Contains(((char)(column + 97)).ToString() + (row + 1)))
                        {
                            this.CellPropertyChanged.Invoke(this, new PropertyChangedEventArgs(e.PropertyName + " SELF_REFERENCE")); // Call CellPropertyChanged methods in Form1.
                            return;
                        }

                        string         expression = cell.Text.Substring(1);
                        ExpressionTree et         = new ExpressionTree(expression);
                        et = new ExpressionTree(expression);
                        string[] expArr = expression.Split(et.Operators, StringSplitOptions.None);

                        // Check the length of the expression array.
                        if (expArr.Length == 1)
                        {
                            if (this.CircularReferenceCheck(this.GetCell(row, column), this.GetCell(expArr[0])))
                            {
                                this.CellPropertyChanged.Invoke(this, new PropertyChangedEventArgs(e.PropertyName + " CIRCULAR_REFERENCE"));
                                return;
                            }

                            this.GetCell(expArr[0]).DependencyChanged += this.Dependency_PropertyChanged;
                            this.GetCell(expArr[0]).AddDependency(cell);
                            cell.Value = this.GetCell(expArr[0]).Value;
                        }
                        else
                        {
                            foreach (string s in expArr)
                            {
                                foreach (char c in s)
                                {
                                    if (c < 48 || c > 57)
                                    {
                                        if (this.CircularReferenceCheck(this.GetCell(row, column), this.GetCell(s)))
                                        {
                                            this.CellPropertyChanged.Invoke(this, new PropertyChangedEventArgs(e.PropertyName + " CIRCULAR_REFERENCE"));
                                            return;
                                        }

                                        et.SetVariable(s, Convert.ToDouble(this.GetCell(s).Value));
                                        if (!e.PropertyName.Contains("RESET"))
                                        {
                                            this.GetCell(s).DependencyChanged += this.Dependency_PropertyChanged;
                                            this.GetCell(s).AddDependency(cell);
                                        }

                                        break;
                                    }
                                }
                            }

                            cell.Value = et.Evaluate().ToString();
                        }
                    }
                    else
                    {
                        cell.Value = cell.Text;
                    }
                }

                this.CellPropertyChanged.Invoke(this, e); // Call CellPropertyChanged methods in Form1.
            }
            catch (Exception)
            {
                // Bad reference detected!
                this.CellPropertyChanged.Invoke(this, new PropertyChangedEventArgs(e.PropertyName + " BAD_REFERENCE")); // Call CellPropertyChanged methods in Form1.
            }
        }
Exemple #6
0
        public void TestDivisionPrecedence()
        {
            ExpressionTree tree = new ExpressionTree("5+10/2+5-2");

            Assert.AreEqual("13", tree.Evaluate().ToString());
        }
Exemple #7
0
        public void TestParentheses()
        {
            ExpressionTree tree = new ExpressionTree("((9+2)-(1+(6-1)))");

            Assert.AreEqual("5", tree.Evaluate().ToString());
        }
Exemple #8
0
        public void TestExpressionTreeConstructorWithAString()
        {
            ExpressionTree tree = new ExpressionTree("A1+B1");

            Assert.AreEqual(tree.InFixExpression, "A1+B1");
        }
Exemple #9
0
        public void TestExpressionTreeWithCombinationOfOperators()
        {
            ExpressionTree tree = new ExpressionTree("(2+3)*6-3/2");

            Assert.AreEqual("28.5", tree.Evaluate().ToString());
        }
Exemple #10
0
        public void TestForNewVaraibleException()
        {
            ExpressionTree tree = new ExpressionTree("x");

            Assert.AreEqual("0", tree.Evaluate().ToString());
        }
Exemple #11
0
        public void TestExpressionTreeConstructor()
        {
            ExpressionTree expression = new ExpressionTree("8");

            Assert.AreEqual("8", expression.InFixExpression.ToString());
        }
Exemple #12
0
        public void TestMultiplyByZeroEvaluateMethod()
        {
            ExpressionTree tree = new ExpressionTree("3*4*3*99*7*0");

            Assert.AreEqual("0", tree.Evaluate().ToString());
        }
Exemple #13
0
        // tells spreadsheet what to do when a cell is changed
        public void CellTextChanged(object sender)
        {
            SpreadsheetCell cell = sender as SpreadsheetCell;

            alteredCell = cell; // set alteredCell to current cell value (allows spreadsheet graphic to view this cell to know what to change)

            // determines what the cell's value should be set to based on its text attribute
            if (cell.Text == string.Empty || cell.Text == null)
            {
                cell.Value     = string.Empty;
                cell.Variables = null;
            }
            else if (cell.Text[0] == '=')
            {
                cell.PreviousVariables = cell.Variables;
                string expression = cell.Text.Substring(1);                 // grab expression from cell

                ExpressionTree tree = new ExpressionTree(expression);       // create new expression tree based on expression in cell

                List <string> var  = tree.Variables.Keys.ToList <string>(); // create list of variables needing values
                List <Cell>   var2 = new List <Cell>();

                for (int k = 0; k < var.Count; k++)
                {
                    if (GetCell(var[k]) != null)
                    {
                        var2.Add(GetCell(var[k])); // create list of cells that this cell depends on
                    }
                }

                cell.Variables = var2; // set cell's variable list

                if (cell.PreviousVariables.Count != 0)
                {
                    List <Cell> difference = cell.PreviousVariables.Except(var2).ToList(); // find difference between what variables are in current expression and what was in expression before

                    if (difference.Count > 0)
                    {
                        for (int t = 0; t < difference.Count; t++)
                        {
                            cell.CellDependencies.Remove(difference[t]); // removes cell from dependency list
                        }
                    }
                }

                // if there are variables in the expression tree, then set the cells with the names of the variables to have this cell as a dependent cell
                if (var.Count != 0)
                {
                    for (int i = 0; i < var.Count; i++)
                    {
                        // check to see if this cell is already a dependent of the variable cell
                        if (GetCell(var[i]) != null)
                        {
                            if (!GetCell(var[i]).CellDependencies.Contains(cell))
                            {
                                GetCell(var[i]).CellDependencies.Add(cell); // add to cell dependency if the current cell is not already there
                            }
                        }
                    }
                }

                // if there is only a single variable and the expression is comprised of only this variable, then copy the value of the variable over to the value of this cell
                // otherwise, evaluate the expression tree and set this evaluated value as the value for this cell
                if (tree.Variables.Count == 1 && expression.Length == var[0].Length)
                {
                    if (GetCell(expression) == null)
                    {
                        cell.Value = "!(bad reference)"; // set to bad reference if cell cannot be found in spreadsheet
                    }
                    else if (GetCell(expression).Value == "!(self reference)")
                    {
                        cell.Value = "!(bad reference)"; // if cell being referred to has a self reference, then set to bad reference
                    }
                    else
                    {
                        bool error = IsReferenced(cell.Variables, cell); // check for circular reference

                        if (cell.CellDependencies.Contains(cell))
                        {
                            cell.Value = "!(self reference)"; // set to self reference if variables in cell includes itself
                        }
                        else if (error == true)
                        {
                            cell.Value = "!(circular reference)"; // sets circular reference if one is found
                        }
                        else if (GetCell(expression).Value == "!(self reference)" || GetCell(expression).Value == "!(bad reference)")
                        {
                            cell.Value = "!(bad reference)"; // sets bad reference if variable in cell is either self referenced or also has a bad reference
                        }
                        else
                        {
                            cell.Value = GetCell(expression).Value;
                        }
                    }
                }
                else
                {
                    bool   error  = tree.SetVariables(this, var); // set variables based on cell values
                    string name   = string.Empty;
                    char   column = (char)(cell.ColumnIndex + 65);
                    string row    = (cell.RowIndex + 1).ToString();
                    name = name + column;
                    name = name + row;

                    bool refError = IsReferenced(cell.Variables, cell);

                    if (GetCell(name).Variables.Contains(GetCell(name)))
                    {
                        cell.Value = "!(self reference)"; // sets self referenced if cell references itself
                    }
                    else if (refError == true)
                    {
                        cell.Value = "!(circular reference)"; // sets circular reference if one is found
                    }
                    else if (error == true)
                    {
                        cell.Value = "!(bad reference)"; // sets bad reference if one is found
                    }
                    else
                    {
                        cell.Value = tree.Evaluate().ToString(); // evaluate tree and set cell's value
                    }
                }
            }
            else
            {
                // if we changed from an expression containing '=' to one that does not, then remove this cell from all
                // dependency lists of other cells that were previously variables in this cell's expression
                if (cell.PreviousVariables.Count > 0)
                {
                    for (int i = 0; i < cell.PreviousVariables.Count; i++)
                    {
                        cell.PreviousVariables[i].CellDependencies.Remove(cell);
                    }
                }

                cell.Variables = new List <Cell>(); // clear variable list

                cell.Value = cell.Text;             // set this cell's value to its text
            }

            if (TextChange != null)
            {
                TextChange(this); // notify spreadsheet graphic of change in cell
            }
        }
Exemple #14
0
        public void TestParenthesisPrecedenceOverMultiplicationOperator()
        {
            ExpressionTree tree = new ExpressionTree("((3+3)*2)");

            Assert.AreEqual("12", tree.Evaluate().ToString());
        }
Exemple #15
0
        public void TestParenthesisPrecedence()
        {
            ExpressionTree tree = new ExpressionTree("((1+2)+(6+3)-6)");

            Assert.AreEqual("6", tree.Evaluate().ToString());
        }
Exemple #16
0
        public void TestMultiplicationPrecedenceProperty()
        {
            ExpressionTree tree = new ExpressionTree("3+4*3+4");

            Assert.AreEqual("19", tree.Evaluate().ToString());
        }
Exemple #17
0
        public void TestSetVariableMethodException()
        {
            ExpressionTree tree = new ExpressionTree("10+x+y");

            Assert.AreEqual("10", tree.Evaluate().ToString());
        }
Exemple #18
0
        public void CellValueChanged(object sender)
        {
            SpreadsheetCell cell = sender as SpreadsheetCell;
            double          parsed;

            // if the value of this cell was changed, and there are other cells that depend on it, and its value is able to be parsed into a double,
            // then update the cells that depended on its value
            if (cell.CellDependencies.Count > 0 && double.TryParse(cell.Value, out parsed) == true)
            {
                Cell updateCell;

                for (int i = 0; i < cell.CellDependencies.Count; i++)
                {
                    updateCell = cell.CellDependencies[i];

                    string expression = updateCell.Text.Substring(1);          // grab expression from cell

                    ExpressionTree tree = new ExpressionTree(expression);      // create new expression tree based on expression in cell

                    List <string> var = tree.Variables.Keys.ToList <string>(); // create list of variables needing values

                    if (tree.Variables.Count == 1 && expression.Length == var[0].Length)
                    {
                        bool error = IsReferenced(updateCell.Variables, updateCell); // checks for a circular reference

                        if (error == true)
                        {
                            updateCell.Value = "!(self reference)"; // sets self reference if circular reference is returned
                        }
                        else if (GetCell(expression).Value == "!(self reference)" || GetCell(expression).Value == "!(bad reference)")
                        {
                            updateCell.Value = "!(bad reference)"; // sets bad reference if variable in cell has self or bad reference
                        }
                        else
                        {
                            updateCell.Value = GetCell(expression).Value;
                        }
                    }
                    else
                    {
                        bool error = IsReferenced(updateCell.Variables, updateCell);

                        if (error == true)
                        {
                            updateCell.Value = "!(bad reference)"; // sets bad reference if circular reference is found
                        }
                        else
                        {
                            tree.SetVariables(this, var);                  // set variables based on cell values

                            updateCell.Value = tree.Evaluate().ToString(); // evaluate tree and set cell's value
                        }
                    }

                    alteredCell = updateCell;
                    if (ValueChange != null)
                    {
                        ValueChange(this);
                    }
                }
            }
            else if (cell.CellDependencies.Count > 0 && (cell.Value == "!(bad reference)" || cell.Value == "!(self reference)"))
            {
                for (int i = 0; i < cell.CellDependencies.Count; i++)
                {
                    if (cell.CellDependencies[i] != cell)
                    {
                        cell.CellDependencies[i].Value = "!(bad reference)"; // sets bad reference to all dependent cells if this cell has self or bad reference
                    }
                    else
                    {
                        cell.CellDependencies[i].Value = "!(self reference)"; // sets self reference if cell finds itself in its dependent cells
                    }
                }
            }
            else if (cell.Variables != null && cell.CellDependencies.Count > 0)
            {
                for (int i = 0; i < cell.Variables.Count; i++)
                {
                    if (IsReferenced(cell.Variables[i].Variables, cell.Variables[i]))
                    {
                        cell.Value = "!(circular reference)"; // sets circular reference if found
                    }
                }
            }

            alteredCell = cell;

            if (ValueChange != null)
            {
                ValueChange(this); // notify spreadsheet graphic of change in cell
            }
        }
Exemple #19
0
        public void TestOperatorPrecedence()
        {
            ExpressionTree tree = new ExpressionTree("3+4*3+14/7");

            Assert.AreEqual("17", tree.Evaluate().ToString());
        }
Exemple #20
0
        public void TestExpressionTreeWithNumbersAndVariables()
        {
            ExpressionTree tree = new ExpressionTree("w-5+y+3");

            Assert.AreEqual("-2", tree.Evaluate().ToString());
        }
        //helper function to evaluate the text value of a cell to determine the value value
        private void EvaluateCell(Cell cell)
        {
            //make BasicCell to evaluate the cell
            BasicCell evalCell = cell as BasicCell;

            //variable for errors, if true, we have an error and should just return null
            bool error = false;

            //First check to see if it's empty
            if (string.IsNullOrWhiteSpace(evalCell.Text))
            {
                //if text is empty, the value should be empty
                evalCell.setValue("");
                CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));
            }

            //next check to see if there is an '=' to make it a formula (and that it's more than just the =...
            else if (evalCell.Text.Length > 1 && evalCell.Text[0] == '=')
            {
                //first get rid of the = at (0)
                string text = evalCell.Text.Substring(1);

                //create an expression tree!
                ExpressionTree evalTree = new ExpressionTree(text);
                // get the variables from the tree
                string[] variables = evalTree.GetVariables();

                //go through each variable. They are the locations of each cell needed for the formula.
                foreach (string variableName in variables)
                {
                    //First check to make sure that there is even a value to reference (call our new GetCell)
                    if (GetCell(variableName) == null)
                    {
                        //there was nothing to reference. Tell the user through the cell and cell prop changed
                        CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));

                        //break out of the loop & set error to true
                        error = true;
                        break;
                    }

                    // We have determine that the cell reference is valid. Set the variable to the expTree variable
                    //get the cell we need to edit
                    Cell   variableCell = GetCell(variableName);
                    double variableValue;

                    //We will need to chck to make sure it work
                    //if the cell's value is empty, set the variable to 0.
                    if (string.IsNullOrEmpty(variableCell.Value))
                    {
                        evalTree.SetVar(variableName, 0);
                    }
                    //if the value of the cell is not a number, set to 0
                    else if (!double.TryParse(variableCell.Value, out variableValue))
                    {
                        evalTree.SetVar(variableName, 0);
                    }
                    //ELSE: should be valid! Set to the value!
                    else
                    {
                        evalTree.SetVar(variableName, variableValue);
                    }

                    //Don't have to worry about circular references, but self references could be bad here
                    string cellToEval = evalCell.ColumnIndex.ToString() + evalCell.RowIndex.ToString();
                    if (variableName == cellToEval)
                    {
                        evalCell.setValue("!(Self Reference)");
                        CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));

                        error = true;
                        break;
                    }
                }

                //if there is an error, stop here and return
                if (error)
                {
                    return;
                }

                //CIRCULAR REFERENCES - CASE 3 (HW 10)
                //check each variable in the cell's list of variables
                foreach (string variableName in variables)
                {
                    //Check for circular references
                    if (IsCircularReference(variableName, evalCell.GetCellName()))
                    {
                        evalCell.setValue("!(Circular Reference)");
                        CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));

                        //if we find the circular reference we have an error and do not need to check further.
                        error = true;
                        break;
                    }
                }

                //Again, if there is an error, stop and return.
                if (error)
                {
                    return;
                }

                //Now, all variables should be set and we can evaluate the formula using the expression tree
                evalCell.setValue(evalTree.Eval().ToString());
                CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));
            }

            //last if it's neither of the above, it's not an formula, just test the value to the text of the original cell
            else
            {
                evalCell.setValue(evalCell.Text);
                CellPropertyChanged(cell, new PropertyChangedEventArgs("Value"));
            }

            //VERY LAST THING WE NEED IS TO UPDATE DEPENDENCIES! And evaluate all cells that were dependent on the one we just changed.
            string cellName = evalCell.GetCellName();

            if (dependencyDict.ContainsKey(cellName))
            {
                foreach (string dependentCell in dependencyDict[cellName])
                {
                    EvaluateCell(GetCell(dependentCell));
                }
            }
        }