/// <summary> /// This function is used to find the evaluation plan for the Query /// - It avoids multiple recalculations /// - It provides a step by step method for evaluating the Query /// - It is a modified form of the original text-book evaluator /// - My algorithm gets the plan without completely converting the expression to postfix /// </summary> /// <returns>A dictionary with the evaluation plan</returns> public Dictionary<string, Field> FindEvalPlan() { //Required for getting the plan without having to convert to postfix Stack<char> boolOpr = new Stack<char>(); Stack<string> boolOpd = new Stack<string>(); //Stores the evaluation plan as a <key, value> pair for easy access EvalPlan = new Dictionary<string, Field>(); //Check every element in the Query foreach (var i in Query) { if (i != ' ') { //Checking between operator and operand if (prec.Contains<char>(i) == false) { //Operands are pushed into the operand queue boolOpd.Push(i.ToString()); //The first occurances are used for generating test-cases //So, they form a part of the evaluation plan Field columnField = new Field(); if (boolOpd.Count != 0 && EvalPlan.Keys.Contains(boolOpd.Peek()) == false) { EvalPlan.Add(boolOpd.Peek(), columnField); } } else { //If the character is a valid symbol at a valid position if (i != '(' && (boolOpr.Peek() != '(' || FindPrec(boolOpr.Peek()) <= FindPrec(i))) { //when the precedance becomes less then do evaluation plan generation while (boolOpr.Peek() != '(' && FindPrec(boolOpr.Peek()) <= FindPrec(i)) { //Get the plan according to the operator Field columnField = new Field(); if (boolOpr.Peek() == '¬') { columnField.rightOpd = boolOpd.Pop(); columnField.fieldOpr = boolOpr.Pop(); boolOpd.Push("(" + " " + columnField.fieldOpr + " " + columnField.rightOpd + " " + ")"); } else { columnField.rightOpd = boolOpd.Pop(); columnField.fieldOpr = boolOpr.Pop(); columnField.leftOpd = boolOpd.Pop(); boolOpd.Push("(" + " " + columnField.leftOpd + " " + columnField.fieldOpr + " " + columnField.rightOpd + " " + ")"); } //If the plan was not already generated then add it //Otherwise, discard to avoid redundancy if (boolOpd.Count != 0 && EvalPlan.Keys.Contains(boolOpd.Peek()) == false) { EvalPlan.Add(boolOpd.Peek(), columnField); } } //If the character is ')' remove its corresponding '(' to balance the equation if (i == ')') { boolOpr.Pop(); } else { boolOpr.Push(i); } } else { boolOpr.Push(i); } //Operators with higher precedance are simpley pushed into the operator stack } } } return EvalPlan; }
/// <summary> /// This constructor initializes the class /// </summary> /// <param name="data">The data for the nodes from the evalPlan</param> /// <param name="result">This is a string that represents the result of the nodes operation</param> /// <param name="yOffset">The yOffset from the top that indicates the depth of the node</param> /// <param name="xOffset">The position of the node along the x - axis</param> public TreeNode(Field data, string result, int yOffset, int xOffset) { this.data = data; this.result = result; this.yOffset = yOffset; this.xOffset = xOffset; InitializeGraphics(); }