/// <summary> /// create a nod. /// </summary> /// <param name="name"> name.</param> /// <returns> node .</returns> private ExpressionTreeNode CreateNode(string name) { if ((name[0] >= 48 && name[0] <= 57) || (name.Length > 1 && name[0] == '-')) { /* First character is a number: Constant Node */ if (int.TryParse(name, out int value)) { return(new ConstantNode(value)); } else { return(null); } } else if (name.Length == 1 && this.IsOperator(name[0])) { /* Operator Node */ return(OperatorNodeFactory.CreateNewNode(name[0])); } else { /* Variable Node */ return(new VariableNode(name)); } }
// post: helps returns a node in the expression tree based on the given expression // int index - the index of the lowest precedence operator in the expression // string expression - the given english expression that may consist of letters, numbers, and operators private static BaseNode GetNodeHelper(int index, string expression) { if (index != -1) { BinaryOperatorNode node = OperatorNodeFactory.CreateOperatorNode(expression[index]); node.Right = GetNode(expression.Substring(index + 1)); node.Left = GetNode(expression.Substring(0, index)); return(node); } else if (index == -2) { throw new System.ArgumentException("Too many or too few parentheses", "Invalid expression"); } return(BuildVariableNode(expression)); }
/// <summary> /// Takes a valid string expression and returns a postfix ordered list of expression tree nodes. /// Uses Dijkstra's Shunting Yard algorithm. /// </summary> /// <param name="expression">Valid expression string.</param> /// <returns>Postfix ordered expression tree node list.</returns> private List <ExpressionTreeNode> GetPostfixList(string expression) { Stack <char> stack = new Stack <char>(); List <ExpressionTreeNode> postfixList = new List <ExpressionTreeNode>(); OperatorNodeFactory opFact = new OperatorNodeFactory(); char[] expressionArray = expression.ToArray <char>(); // loops over each char in expression string for (int i = 0; i < expressionArray.Length; i++) { char currChar = expressionArray[i]; // if the current char is a left parenthesis, push to stack if (currChar.Equals('(')) { stack.Push(currChar); } // if the current char is a right parenthesis else if (currChar.Equals(')')) { // while the top of the stack is not a left parenthesis, pop and add to list while (!stack.Peek().Equals('(')) { OperatorNode newOpNode = opFact.CreateOperatorNode(stack.Pop()); postfixList.Add(newOpNode); } stack.Pop(); // pop the left parenthesis from the top of the stack } // If the current char is a valid operator else if (opFact.IsValidOperator(currChar)) { // if the stack is empty or the next char is a left parenthesis if (stack.Count <= 0 || stack.Peek().Equals('(')) { stack.Push(currChar); } // otherwise the next char on the stack is an operator else { OperatorNode currOpNode = opFact.CreateOperatorNode(currChar); OperatorNode nextOpNode = opFact.CreateOperatorNode(stack.Peek()); // if curr operator has > precedence than the next operator, or equal precedence and right associativity if (currOpNode.Precedence > nextOpNode.Precedence || (currOpNode.Precedence == nextOpNode.Precedence && currOpNode.Associativity == OperatorNode.Associative.Right)) { stack.Push(currChar); // push the current operator on the stack } // if curr operator has < precedence than the next operator, or equal precedence and left associativity else { // add the next operator to the list stack.Pop(); postfixList.Add(nextOpNode); i--; } } } // if the current char is a digit (0-9) else if (char.IsDigit(currChar)) { string constantString = currChar.ToString(); for (int j = i + 1; j < expressionArray.Length; j++) { currChar = expressionArray[j]; // if the next char is a digit, append to constant string if (char.IsDigit(currChar)) { constantString += currChar.ToString(); i++; } // otherwise the next char is not part of this number else { break; } } postfixList.Add(new ConstantNode(double.Parse(constantString))); // add the complete number to the list } // if the current char is a variable else { string variable = currChar.ToString(); for (int j = i + 1; j < expressionArray.Length; j++) { currChar = expressionArray[j]; // if the next char is not an operator if (!opFact.IsValidOperator(currChar)) { variable += expressionArray[j].ToString(); i++; } // otherwise the next char is not part of this variable else { break; } } // add the complete variable to the list postfixList.Add(new VariableNode(variable, ref this.variables)); // Add the name to variabelNames list if it is not already in it. if (!this.variableNames.Contains(variable)) { this.variableNames.Add(variable); } } } // pop and add the rest of the stack to the list while (stack.Count > 0) { OperatorNode newOpNode = opFact.CreateOperatorNode(stack.Pop()); postfixList.Add(newOpNode); } return(postfixList); }