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; } } }
/// <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); }
/// <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. } }
public void TestDivisionPrecedence() { ExpressionTree tree = new ExpressionTree("5+10/2+5-2"); Assert.AreEqual("13", tree.Evaluate().ToString()); }
public void TestParentheses() { ExpressionTree tree = new ExpressionTree("((9+2)-(1+(6-1)))"); Assert.AreEqual("5", tree.Evaluate().ToString()); }
public void TestExpressionTreeConstructorWithAString() { ExpressionTree tree = new ExpressionTree("A1+B1"); Assert.AreEqual(tree.InFixExpression, "A1+B1"); }
public void TestExpressionTreeWithCombinationOfOperators() { ExpressionTree tree = new ExpressionTree("(2+3)*6-3/2"); Assert.AreEqual("28.5", tree.Evaluate().ToString()); }
public void TestForNewVaraibleException() { ExpressionTree tree = new ExpressionTree("x"); Assert.AreEqual("0", tree.Evaluate().ToString()); }
public void TestExpressionTreeConstructor() { ExpressionTree expression = new ExpressionTree("8"); Assert.AreEqual("8", expression.InFixExpression.ToString()); }
public void TestMultiplyByZeroEvaluateMethod() { ExpressionTree tree = new ExpressionTree("3*4*3*99*7*0"); Assert.AreEqual("0", tree.Evaluate().ToString()); }
// 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 } }
public void TestParenthesisPrecedenceOverMultiplicationOperator() { ExpressionTree tree = new ExpressionTree("((3+3)*2)"); Assert.AreEqual("12", tree.Evaluate().ToString()); }
public void TestParenthesisPrecedence() { ExpressionTree tree = new ExpressionTree("((1+2)+(6+3)-6)"); Assert.AreEqual("6", tree.Evaluate().ToString()); }
public void TestMultiplicationPrecedenceProperty() { ExpressionTree tree = new ExpressionTree("3+4*3+4"); Assert.AreEqual("19", tree.Evaluate().ToString()); }
public void TestSetVariableMethodException() { ExpressionTree tree = new ExpressionTree("10+x+y"); Assert.AreEqual("10", tree.Evaluate().ToString()); }
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 } }
public void TestOperatorPrecedence() { ExpressionTree tree = new ExpressionTree("3+4*3+14/7"); Assert.AreEqual("17", tree.Evaluate().ToString()); }
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)); } } }