// Builds the tree by pushing or popping on a stack // depending on which Node we are looking at private void BuildTree(Queue <string> output) { Stack <Node> nodes = new Stack <Node>(); Decimal num; // For every string on the output queue foreach (string s in output) { // Check if it is a number if (s.All(c => Char.IsDigit(c)) || Decimal.TryParse(s, out num)) { // Create new value node nodes.Push(new ValNode(Convert.ToDouble(s))); } // Check if it is a variable else if (Char.IsLetter(s[0])) { // Create new variable node nodes.Push(new VarNode(s)); } else { // Create new operator node, and give it the last 2 things // as it's children OpNode temp = new OpNode(Convert.ToChar(s)); temp.rightChild = nodes.Pop(); temp.leftChild = nodes.Pop(); nodes.Push(temp); } } // Pop the top of the stack and set it to root root = nodes.Pop(); }
static private void PerformOperation(OpNode operation, double val, ref double result) // Performs the operation contained in the opnode { if (operation.Value == "+") // Addition { result += val; } else if (operation.Value == "-") // Subtraction { result -= val; } else if (operation.Value == "*") // Multiplication { result *= val; } else // Division { if (val != 0) // ensures no dividing by zero { result /= val; } else // otherwise result will not change { throw new DivideByZeroException(); } } }
private double evalNode(Node node) { OpNode op_node = node as OpNode; ValueNode val_node = node as ValueNode; VarNode var_node = node as VarNode; if (null != op_node) { switch (op_node.m_op) { case '+': return(evalNode(op_node.m_left) + evalNode(op_node.m_right)); case '-': return(evalNode(op_node.m_left) - evalNode(op_node.m_right)); case '*': return(evalNode(op_node.m_left) * evalNode(op_node.m_right)); case '/': return(evalNode(op_node.m_left) / evalNode(op_node.m_right)); case '^': return(Math.Pow(evalNode(op_node.m_left), evalNode(op_node.m_right))); } } if (null != val_node)//if node is a value node, return it's value { return(val_node.m_value); } if (null != var_node) //if node is a variable, look up key in dictionary and return corresponding value { return(m_dict[var_node.m_var]); //will crash if variable isn't defined, so don't allows eval function to be called unless all variables are define. SEE allVarsDefined() function } return(0);//I don't know the how this code could get here, but the compiler wants something here }
Node ConstructTree(string expression) { double value; for (int i = expression.Length - 1; i >= 0; i--) { switch (expression[i]) { case '+': case '-': case '*': case '/': OpNode newNode = new OpNode(expression[i]); if (root == null) { root = newNode; } newNode.left = ConstructTree(expression.Substring(0, i)); newNode.right = ConstructTree(expression.Substring(i + 1)); return(newNode); } } if (Double.TryParse(expression, out value)) { return(new ValNode(value)); } else { return(new VarNode(expression)); } }
public OperationTraceCollector() { _root = new OpNode { Id = Guid.NewGuid() }; _currentNode = _root; }
bool allVarsDefinedNode(Node node) { OpNode o = node as OpNode; if (o != null)//node is an OpNode { return(allVarsDefinedNode(o.m_left) && allVarsDefinedNode(o.m_right)); } ValueNode value = node as ValueNode; if (value != null)//node is a ValueNode { return(true); } VarNode var = node as VarNode; if (var != null) //node is a VarNode { if (m_dict.ContainsKey(var.m_var)) //if key exists { return(true); } else//if key is not in dictionary { return(false); } } return(false);//Don't know how code would get here }
// Build tree function. Takes in expression and separates operators from values and variables private void BuildTree(string exp) { // Use Regex Split to go through expression string and tokenize the string into substrings // Each substring that gets split is put into a List<string> // Each substring is made sure to be not empty // Regex Expression: ([+-/*\(\)]) : Any operator or parentheses // Any variable or number will be separated by operators or parentheses. // So this makes sense to use the operators to do the splitting List <string> tokens = new List <string>(); tokens = Regex.Split(exp, @"([+-/*\(\)])").Where(s => s != String.Empty).ToList <string>(); // op [+\\-/*()\\^] // digit [\\d]+ // variable [a-zA-Z]+; // Adds all the variables to a list to be used for our dictionary of dependencies foreach (string s in tokens) { if (Char.IsUpper(s[0])) { varsForDeps.Add(s); } } // Convert from infix notation to reverse polish tokens = ToPolish(tokens); // Using a stack structure to create our tree // Operands are pushed onto the stack // Operators pop the necessary operands off the stack and set those as its children // This operator node then gets pushed onto the stack Stack <Node> stack = new Stack <Node>(); foreach (string s in tokens) { // Creates variable node. Sets default value to zero if (Char.IsLetter(s, 0)) { stack.Push(new VarNode(s)); if (!(vars.ContainsKey(s))) { SetVar(s, 0); } } else if (Char.IsDigit(s, 0)) { stack.Push(new ValNode(Convert.ToDouble(s))); } else { OpNode temp = new OpNode(s[0]); temp.rightChild = stack.Pop(); temp.leftChild = stack.Pop(); stack.Push(temp); } } root = stack.Pop(); }
internal void StartOperation(Guid id, string name, string title, string message, string methodName, long startTicks) { var node = new OpNode { Id = id, Name = name, Title = title, Message = message, MethodName = methodName, StartTicks = startTicks }; node.Parent = _currentNode; node.Parent.Children.Add(node); _currentNode = node; }
internal void EndOperation(string message, bool successful, Guid id, long finishTicks, decimal secondsElapsed) { var node = _currentNode; node.Message = message; node.Successful = successful; node.FinishTicks = finishTicks; node.Duration = secondsElapsed; _currentNode = node.Parent; }
public void WhenEvalIsCalledOnAnUnitializedOpNode_ShouldThrowInvalidOperationException() { // Arrange OpNode testOpNode = new OpNode(); // Act testOpNode.Eval(); // Assert is handled by the ExpectedException attribute on the test method. }
//Calculates an Expression Tree given it's root node private double Evaluate(Node n) { if (n == null) { return(-1); } ConstNode constTest = n as ConstNode; if (constTest != null) { return(constTest.get_val()); } VarNode varTest = n as VarNode; if (varTest != null) { try { return(vDict[n.get_name()]); } catch (Exception c) { Console.WriteLine("Key Not Found, Undefined Behavior"); } } OpNode opTest = n as OpNode; if (opTest != null) { if (opTest.get_name() == "+") { return(Evaluate(opTest.Left) + Evaluate(opTest.Right)); } else if (opTest.get_name() == "-") { return(Evaluate(opTest.Left) - Evaluate(opTest.Right)); } else if (opTest.get_name() == "*") { return(Evaluate(opTest.Left) * Evaluate(opTest.Right)); } else if (opTest.get_name() == "/") { return(Evaluate(opTest.Left) / Evaluate(opTest.Right)); } } return(0.0); //default return value }
Node ExprAdd() { Node left = ExprMul(); while (!End() && GetChar() == '+') { char op = NextChar(); Node right = ExprMul(); left = new OpNode(op, left, right); } return(left); }
public void EvalMultiplyTest() { // Arrange double testLeftValue = 11.3214; double testRightValue = 3485; ExpNode testLeftNode = new ValNode(testLeftValue); ExpNode testRightNode = new ValNode(testRightValue); OpNode testOpNode = new OpNode(ref testLeftNode, ref testRightNode, '*'); // Act and Assert Assert.AreEqual((testLeftValue * testRightValue), testOpNode.Eval()); }
public override bool Amend(out Node node) { if (!base.Amend(out var group)) { node = group; return(false); } //Magnitude of the grouped simplification node = new OpNode(Operation.Transform); node.Usurp(new FunctionNode(TransformName)); node.Append(group); return(true); }
// Compile tree Node Compile(string exp) { exp = RemoveOuterParens(exp); // get last op index int index = getOpIndex(exp); // if no op if (index == -1) { return(MakeSimple(exp)); } // create op node OpNode mroot = new OpNode(exp[index]); mroot.pRight = Compile(exp.Substring(index + 1)); mroot.pLeft = Compile(exp.Substring(0, index)); return(mroot); }
Node processMultiTokenStream(string[] tokens) { // diveide and conquer: take first toplevel operator and recurse left // and right of it. sadly this cannot take operator precedence into account, // so the user will have to use brackets for this. //i.e. a term like 4 * 5 + 7 will become: // Mul // 4 Add // 5 7 // resulting in 4 being multiplied with 12 instead of 5. int i = GetLowestPrecendeOperatorIndex(tokens); // No top level operator found? We might have to deal with a call to // an inbuilt function, e.g. Sqrt(a + 10) if (i == -1) { if (tokens[0] == "{" && tokens[tokens.Length - 1] == "}") { // this is probably a plain list. var listEntries = parseParamlist(tokens.Skip(1).Take(tokens.Length - 2)); return(new ListNode(listEntries)); } if (tokens[0] == "(" && tokens[tokens.Length - 1] == ")") { return(parseTokenStream(tokens.Skip(1).Take(tokens.Length - 2).ToArray())); } return(CreateFuncCallNode(tokens)); } // slice array.: var left = parseTokenStream(tokens.Take(i).ToArray()); var right = parseTokenStream(tokens.Skip(i + 1).ToArray()); OpNode n = CreateOpNode(tokens[i]); n.Left = left; n.Right = right; return(n); }
//description: traverse through the tree to return a hashet of the variable names //parameter: root node and hashset //return: public void GetVarsHelper(Node n, HashSet <string> vars) { if (n == null) { return; } if (n is VarNode) //if variable node add variable name to hashset { VarNode var = n as VarNode; vars.Add(var.Name); } else if (n is OpNode) //if operator node recurse into left and right node { OpNode op = n as OpNode; GetVarsHelper(op.Left, vars); GetVarsHelper(op.Right, vars); } }
static private void PerformOperation(OpNode operation, double val, ref double result) // Performs the operation contained in the opnode { if (operation.Value == "+") // Addition result += val; else if (operation.Value == "-") // Subtraction result -= val; else if (operation.Value == "*") // Multiplication result *= val; else // Division { if (val != 0) // ensures no dividing by zero result /= val; else // otherwise result will not change throw new DivideByZeroException(); } }
void walkAST(object ast_node, List <string> varstack, byte varstack_callindex) { Type t = ast_node.GetType(); if (NumericMap.ContainsKey(t)) { this.bytecodes.Add(NumericMap[t]); Dictionary <Type, NumericCovert> ConvertMap = new Dictionary <Type, NumericCovert> { { typeof(sbyte), () => BitConverter.GetBytes((sbyte)ast_node) }, { typeof(byte), () => BitConverter.GetBytes((byte)ast_node) }, { typeof(short), () => BitConverter.GetBytes((short)ast_node) }, { typeof(ushort), () => BitConverter.GetBytes((ushort)ast_node) }, { typeof(int), () => BitConverter.GetBytes((int)ast_node) }, { typeof(uint), () => BitConverter.GetBytes((uint)ast_node) }, { typeof(long), () => BitConverter.GetBytes((long)ast_node) }, { typeof(float), () => BitConverter.GetBytes((float)ast_node) }, { typeof(double), () => BitConverter.GetBytes((double)ast_node) } }; foreach (byte item in ConvertMap[t]()) { this.bytecodes.Add(item); } } else if (t == typeof(string) || t == typeof(char)) { string node = ast_node.ToString(); this.bytecodes.Add((byte)Opdata.iot); if (this.textstack_map.ContainsKey(node)) { this.walkAST(this.textstack_map[node], null, 0); } else { foreach (byte item in Encoding.Unicode.GetBytes(node)) { this.textstack_bytes.Add(item); } this.textstack_bytes.Add(Definition.EOT); this.textstack_bytes.Add(0); this.textstack_map[node] = this.textstack_index; this.walkAST(this.textstack_index, null, 0); this.textstack_index += 1; } } else if (t == typeof(OpNode)) { OpNode node = (OpNode)ast_node; if (node.opcode == (byte)Opexplicit.scope) { // node.arguments[0] is the variable name // node.arguments[1] is the content if (node.arguments.Count >= 2) { varstack.Add(node.arguments[0].ToString()); this.walkAST(node.arguments[1], varstack, varstack_callindex); this.bytecodes.Add(node.opcode); } foreach (object item in node.body) { this.walkAST(item, varstack, varstack_callindex); } if (node.arguments.Count >= 2) { varstack.RemoveAt(varstack.Count - 1); this.bytecodes.Add((byte)Opimplicit.sweep); } } else if (node.opcode == (byte)Opexplicit.get) { string name = node.body[0].ToString(); bool not_found = true; for (int l = varstack.Count; l-- != 0;) { if (name == varstack[l]) { if (l < varstack_callindex) { this.bytecodes.Add(node.opcode); this.bytecodes.Add((byte)l); } else { this.bytecodes.Add((byte)Opimplicit.localfget); this.bytecodes.Add((byte)(l - varstack_callindex)); } not_found = false; break; } } if (not_found) { throw new Exception("no variable " + name + " in scope"); } } else if (node.opcode == (byte)Opexplicit.func) { this.bytecodes.Add(node.opcode); // ======= set the length of function body ======== this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); // ======= push variables to var stack ======== int bytecodes_len = this.bytecodes.Count; this.bytecodes.Add((byte)node.arguments.Count); varstack_callindex = (byte)varstack.Count; foreach (object item in node.arguments) { varstack.Add(item.ToString()); } // ========= walk through function body ========== foreach (object item in node.body) { this.walkAST(item, varstack, varstack_callindex); } // ========= jump back to origin pc ============= this.bytecodes.Add((byte)Opimplicit.sweepn); this.bytecodes.Add((byte)Opimplicit.jump); // ========= clean up =========== int args_len = node.arguments.Count; while (args_len != 0) { args_len -= 1; varstack.RemoveAt(varstack.Count - 1); } // ========= set function body length ============ byte[] offset_bytes = BitConverter.GetBytes((uint)(this.bytecodes.Count - bytecodes_len)); this.bytecodes[bytecodes_len - 4] = offset_bytes[0]; this.bytecodes[bytecodes_len - 3] = offset_bytes[1]; this.bytecodes[bytecodes_len - 2] = offset_bytes[2]; this.bytecodes[bytecodes_len - 1] = offset_bytes[3]; } else if (node.opcode == (byte)Opexplicit.ifElse) { // push condition on stack this.walkAST(node.body[0], varstack, varstack_callindex); this.bytecodes.Add(node.opcode); // else branch addresss int else_val_address = this.bytecodes.Count; this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); // body of branch true this.walkAST(node.body[1], varstack, varstack_callindex); // exit address this.bytecodes.Add((byte)Opdata.uint32); int exit_val_address = this.bytecodes.Count; this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add(0); this.bytecodes.Add((byte)Opimplicit.jumpoffset); byte[] offset_bytes = BitConverter.GetBytes((uint)(this.bytecodes.Count - else_val_address)); this.bytecodes[else_val_address + 0] = offset_bytes[0]; this.bytecodes[else_val_address + 1] = offset_bytes[1]; this.bytecodes[else_val_address + 2] = offset_bytes[2]; this.bytecodes[else_val_address + 3] = offset_bytes[3]; // body of branch false this.walkAST(node.body[2], varstack, varstack_callindex); byte[] exit_address_bytes = BitConverter.GetBytes((uint)(this.bytecodes.Count - (exit_val_address + 5))); this.bytecodes[exit_val_address + 0] = exit_address_bytes[0]; this.bytecodes[exit_val_address + 1] = exit_address_bytes[1]; this.bytecodes[exit_val_address + 2] = exit_address_bytes[2]; this.bytecodes[exit_val_address + 3] = exit_address_bytes[3]; } else { foreach (object item in node.body) { this.walkAST(item, varstack, varstack_callindex); } this.bytecodes.Add(node.opcode); if (Enum.IsDefined(typeof(Opexplicit), node.opcode) && !Definition.OpWithTwoArgs.Contains((Opexplicit)node.opcode)) { this.bytecodes.Add((byte)node.body.Count); } } } }