//build the tree (bottom up) using the shuntingYard stacks private bool buildTree() { //pop operators from stack -> build tree //OpNode temp; // if (root.operationType == '_') // { root = operators.Pop(); root.right = operands.Pop(); root.left = operands.Pop(); //after building tree, operands.Push(new ValNode(root.Eval())); //evaluate, and push value to output return(true); //return true; // } //else //{ // temp = root; //hold sub-tree // //operands.Pop(); //pop the result -- right sub-tree == result // root = operators.Pop(); //grab an operator // root.right = temp; //restore sub-tree, making right-heavy tree // root.left = operands.Pop(); //if we don't push the result (leave it in tree) this works // return true; //} //int valCount = eTokens.Length; //keep #items handy //int leafVal = 0; //out variable -- required for parsing }
// Created this method to prevent bloat in code private Node formTree(Stack <Node> operands, Stack <OpNode> operators) { // While there are no OpNode on the operatorsStack, form appropriate branches and place in operands stack while (operators.Count > 0) { OpNode newParent = operators.Pop(); newParent.RightChild = operands.Pop(); newParent.LeftChild = operands.Pop(); root = newParent; operandStack.Push(newParent); } return(root); }
private double Eval(Node node) { //Evaluate based on the kind of node ConstNode constnode = node as ConstNode; if (constnode != null) { return(constnode.OpValue); } VarNode varnode = node as VarNode; if (varnode != null) { try { return(variableDict[varnode.Name]); } catch { Console.WriteLine("Variable " + varnode.Name + " has not been defined. Continuing evaluation with variable equal to 0."); } } OpNode opnode = node as OpNode; if (opnode != null) { switch (opnode.Op) { case '+': return(Eval(opnode.Left) + Eval(opnode.Right)); case '-': return(Eval(opnode.Left) - Eval(opnode.Right)); case '*': return(Eval(opnode.Left) * Eval(opnode.Right)); case '/': return(Eval(opnode.Left) / Eval(opnode.Right)); } } return(0); }
// Factory for ExpNodes to create an expression tree. protected ExpNode ConstructTreeFromTokens(List <string> expressionInPostfixNotation) { Stack <ExpNode> stack = new Stack <ExpNode>(); foreach (string tok in expressionInPostfixNotation) { if (operators.TryGetValue(tok, out OperatorToken op)) //if the token is an operator { ExpNode newrightNode = stack.Pop(); //grabs the right and left nodes from the stack ExpNode newLeftNode = stack.Pop(); ExpNode newOpNode = new OpNode(ref newLeftNode, ref newrightNode, op.Symbol[0]); // Creates an OpNode with the nodes we just popped off the stack. stack.Push(newOpNode); // Adds the new operator node to the stack. } else // if the token is an operand { stack.Push(MakeDataNode(tok)); //push the operand node on to the stack } } //when there are no more tokens. There should only be one node on the stack. return(stack.Pop()); // returns the root node of the tree. }
private double Eval(Node node) { //Evaluate based on the kind of node ConstNode constnode = node as ConstNode; if (constnode != null) { return(constnode.OpValue); } VarNode varnode = node as VarNode; if (varnode != null) { // used to be a try/catch, but now we set every new variable to 0 when the tree is made, so there will always be a value to obtain. return(variableDict[varnode.Name]); } OpNode opnode = node as OpNode; if (opnode != null) { switch (opnode.Op) { case '+': return(Eval(opnode.Left) + Eval(opnode.Right)); case '-': return(Eval(opnode.Left) - Eval(opnode.Right)); case '*': return(Eval(opnode.Left) * Eval(opnode.Right)); case '/': return(Eval(opnode.Left) / Eval(opnode.Right)); } } return(0); }
} //allow tree to tell its current expression //Expression Tree Constructor //--builds ExpTree according to given expression, with default expression if never supplied one public ExpTree(Cell c, Cell[][] spc, string expression = "4+18/(9-3)") { root = new OpNode('_'); //'_' == special marker for base tree-building case currentExpression = expression; //hold the expression -- allows re-parsing -- not needed once I build the tree for real? variables = new Dictionary <string, double>(); //create new dictionary for variableName:value mapping operands = new Stack <Node>(); //shuntingYard Operand Stack operators = new Stack <OpNode>(); //shuntingYard Operator Stack //output = new Stack<Node>(); //shuntingYard Output Stack precedence = new Dictionary <string, int>() //shuntingYard Precedence Mapping { { "(", 0 }, { ")", 3 }, { "*", 2 }, { "/", 2 }, { "+", 1 }, { "-", 1 } }; evalResult = -42.0; //make initial value an uncommon result expressionTokens = parseExp(ref c, ref spc, currentExpression); //use self-made parser, couldn't get my RegEx right.. if (expressionTokens[0] == "" || isOperator(expressionTokens[0])) { c.Text = "#REF!"; c.bgColor = "Red"; c.clearRefDict(); //clear refs so it can re-evaluate } //shuntYard(expressionTokens); //convert to RPN & build tree with Shunting Yard Algorithm }
// recursive function to set a variable node. protected void SetVarNode(ref VarNode input, OpNode node) { if (VariableNodeCompare(input, node.left)) //if the left node is a Variable node and has the same variable name { (node.left as VarNode).Value = input.Value; } else if (VariableNodeCompare(input, node.right)) //if the right node is a Variable node and has the same variable name { (node.right as VarNode).Value = input.Value; } else { if (node.right as OpNode != null) //if the right side node is an operator node { SetVarNode(ref input, node.right as OpNode); //check right subtree } if (node.left as OpNode != null) //if the right side node is an operator node { SetVarNode(ref input, node.left as OpNode); //check right subtree } } }
public ExpTree(string expression) { Stack <string> equationStack = new Stack <string>(); Stack <string> treeStack = new Stack <string>(); Stack <Node> buildTree = new Stack <Node>(); string tempString = ""; //format expression to work with parser expression = "(" + expression + ")"; char[] tokens = expression.ToCharArray(); //build stack from parsed expression - shunting yard algorithm for (int i = 0; i < tokens.Length; i++) { if (tokens[i] == '(') { equationStack.Push(tokens[i].ToString()); } else if (tokens[i] == ')') // doesn't push ")" to equation stack { while (equationStack.Peek() != "(") // pop until lhs bracket is found { treeStack.Push(equationStack.Pop()); // add right child and operator } equationStack.Pop(); // get rid of "(" } else if (operators.Contains(tokens[i].ToString())) // current token is an operator { while (equationStack.Peek() != "(" && (!operators.Contains(equationStack.Peek()) || (getPrecedence(tokens[i].ToString()) < getPrecedence(equationStack.Peek())) || /*check if stack top is operator of higher precedence*/ (getPrecedence(tokens[i].ToString()) == getPrecedence(equationStack.Peek())))) { treeStack.Push(equationStack.Pop()); } equationStack.Push(tokens[i].ToString()); } else // integer or variable { // get numbers with multiple digits (will always execute at least once) while (tokens[i] != '(' && tokens[i] != ')' && !operators.Contains(tokens[i].ToString())) { tempString += tokens[i]; i++; } if (tokens[i] == '(' || tokens[i] == ')' || operators.Contains(tokens[i].ToString())) { i--; //move back so token isn't skipped in next iteration } equationStack.Push(tempString); tempString = ""; } } equationStack.Clear(); //reverse stack to get postfix expression while (treeStack.Count != 0) { equationStack.Push(treeStack.Pop()); } //build tree while (equationStack.Count != 0) //equationStack now contains postfix expression { tempString = equationStack.Pop(); if (operators.Contains(tempString)) //make opNode { OpNode newNode = new OpNode(tempString); if (buildTree.Count >= 2) { newNode.right = buildTree.Pop(); newNode.left = buildTree.Pop(); buildTree.Push(newNode); } } else { if (tempString.All(Char.IsDigit)) //make valNode { ValNode newNode = new ValNode(tempString); buildTree.Push(newNode); } else //make varNode { char let = Char.ToUpper(tempString[0]); string row = tempString.Substring(1); tempString = let + row; if (!varDict.ContainsKey(tempString)) { varDict[tempString] = 0; //initialize all variables to 0 } VarNode newNode = new VarNode(tempString); buildTree.Push(newNode); varList.Add(tempString); //add to list of cell references } } } this.root = buildTree.Pop(); //final item in stack will be root node pointing to subtrees }
private string userInput; // Used for menu interface public ExpTree(string expression) { int operandBegin = 0; // Index of where the first character of the operand exists bool exit = false; // Used for logic with paranthesis and how they are placed onto appropriate stack bool paranthesis = false; // If true, we know that the last paranthesis was placed onto stack and we do not need to create another operand for current operator // Iterate through length of given expression for (int i = 0; i < expression.Length; i++) { char currentChar = expression[i]; // If looking at an operator if (currentChar == '+' || currentChar == '-' || currentChar == '*' || currentChar == '/') { // Create an appropriate OpNode OpNode newOp = new OpNode(currentChar.ToString()); // Last thing we looked at was not ')' if (paranthesis == false) { // Create an operand node with last operand and place onto stack Node newNode = determineNode(expression, operandBegin, i); operandStack.Push(newNode); } // We know that there is no 'new' operand to be placed on stack, sub-tree contained in () is already placed onto operand stack else { // Reset the paranthesis flag paranthesis = false; } // Next operand should begin immediately after the operator, note this would be different if urnary operators were included operandBegin = i + 1; // Determine what to do with current and previous operators if (operatorStack.Count > 0) { // Need to peak at top of operand stack, if higher precedence need to push current operand down if (operatorStack.Peek().Precedence < newOp.Precedence) { operatorStack.Push(newOp); } // If lower precedence, need to pop and form node else { OpNode newParent = operatorStack.Pop(); newParent.RightChild = operandStack.Pop(); newParent.LeftChild = operandStack.Pop(); operandStack.Push(newParent); operatorStack.Push(newOp); } } else { // If the operator stack is empty, it is essentially a sentinal like the hint paper was describing operatorStack.Push(newOp); } } else if (currentChar == '(') { // Need to form new tree ExpTree newTree = new ExpTree(expression.Substring(i + 1)); //TEST i = expression.IndexOf(')', i + 1); paranthesis = true; operandStack.Push(newTree.root); } else if (currentChar == ')') { // End new tree, pop back out Node newNode = determineNode(expression, operandBegin, i); operandStack.Push(newNode); root = formTree(operandStack, operatorStack); exit = true; break; } } // Since we are only using binary oprators, the operand stack must be even when expression is completely evaluated if (operandStack.Count > 0 & (operandStack.Count % 2 != 0) & exit == false) { Node newNode = determineNode(expression, operandBegin, expression.Length); operandStack.Push(newNode); } // Provide an entry point for outside world to access root = formTree(operandStack, operatorStack); }