private void Compile(string exp) { // tokenize the expression using 3 regex capture groups: // ([A-Za-z]+\d*) : at least one alpha character followed by 0 or more digits // ([-/\+\*\(\)]) : any of the +, -, *, / operators or parens // (\d+\.?\d+) : a constant number that may contain a decimal number // // after tokenizing make sure that the resulting token list doesnt // contain any empty strings and then listify the enumerable var tokens = Regex.Split(exp, @"([A-Za-z]+\d*)|([-/\+\*\(\)])|(\d+\.?\d+)") .Where(s => s != String.Empty) .ToList <string>(); // convert token list to prefix expression which is then trivial to iterate through // and linearly build the expression tree var nodeStack = new Stack <Node>(); foreach (var tok in InfixToPrefix(tokens)) { if (Char.IsLetter(tok[0])) { nodeStack.Push(new VarNode(tok)); /* * if(!vars.ContainsKey(tok)) * vars[tok] = 0; // default value of 0 */ locals.Add(tok); } else if (Char.IsDigit(tok[0])) { nodeStack.Push(new ConstNode(Double.Parse(tok))); } else { var on = new OpNode(tok[0]); on.right = nodeStack.Pop(); on.left = nodeStack.Pop(); nodeStack.Push(on); } } root = nodeStack.Pop(); }
// This is a compile utility function that will serve as a recursive call for compile // it will take an expression and an operator to return a branch node of the expression private Node Compile(string expression, char operation) { bool flag = false; // we want to read from the right to find the rightmost lowest precedence operator int i = expression.Length - 1; int pCounter = 0; while (!flag) { // increment parenthesis counter if (expression[i] == '(') { pCounter++; } // decrement parenthesis counter else if (expression[i] == ')') { pCounter--; } if (pCounter == 0 && expression[i] == operation) // when we reach an operator, evaluate expression { // create and return subtree with current operation being the root node // and the left and right expressions as their own compiled subtrees OpNode opNode = new OpNode(operation); // left subtree is the beginning of the string to the current index opNode.L = Compile(expression.Substring(0, i)); // right subtree is the next index to the end of the string opNode.R = Compile(expression.Substring(i + 1)); return(opNode); } else { if (i == 0) // reached the left end of the expression - terminate { flag = true; } i--; // continue reading the next part of the expression to the left } } return(null); }
// private Eval helper function for public Eval() // takes input node argument and evaluates it private double Eval(Node NodeArg) { ConstantNode cNode = NodeArg as ConstantNode; if (cNode != null) { return(cNode.m_constant); } VarNode vNode = NodeArg as VarNode; if (vNode != null) { return(VarDictionary[vNode.m_var]); } // if node is operator, recursively evaluate left and right subtrees // and perform respective operations on them OpNode oNode = NodeArg as OpNode; if (oNode != null) { switch (oNode.m_operand) // evalutate the left subtree and then right subtree { case '+': return(Eval(oNode.L) + Eval(oNode.R)); case '-': return(Eval(oNode.L) - Eval(oNode.R)); case '*': return(Eval(oNode.L) * Eval(oNode.R)); case '/': return(Eval(oNode.L) / Eval(oNode.R)); } } return(0); }