public void SetValue(string value) { //(04.07.2006 10:32) //Check for text first. if (IsText(value)) { this.m_value = GetText(value); this.m_type = NODE_TYPE.TEXT; return; } //Check for operators first. OperatorMatch opMatch = FindOperators(value, m_operatorManager); if (opMatch != null) { m_type = NODE_TYPE.OPERATOR; string leftParam = value.Substring(0, opMatch.StartIndex); string rightParam = value.Substring(opMatch.StartIndex + opMatch.Length); if (leftParam != "") m_subNodes = new ExpressionTreeNode[]{new ExpressionTreeNode(leftParam, m_column, m_operatorManager), new ExpressionTreeNode(rightParam, m_column, m_operatorManager)}; else m_subNodes = new ExpressionTreeNode[]{new ExpressionTreeNode(rightParam, m_column, m_operatorManager)}; m_value = opMatch.ExpressionOperator.FunctionName; } else if (value.IndexOf("(") != -1) { int paranStart = value.IndexOf('('); string functionName = value.Substring(0, paranStart); if (value.Length - paranStart - 2 < 0) { throw new ExpressionException("Missing ')'", m_column, value.Length); } string param = value.Substring(paranStart + 1, value.Length - paranStart - 2); if (functionName == "") { m_column += 1; SetValue(param); return; } if (param != "") { ArrayList @params = new ArrayList(); int col = m_column + paranStart + 1; int depth = 0; string par = ""; //(27.07.2006 16:24) //Detects whether we are inside a text or not. bool insideText = false; for (int i = 0; i <= param.Length - 1; i++) { char c = param[i]; if (c == '(') { depth += 1; } else if (c == ')') { depth -= 1; } else if (c == '"') { insideText = !insideText; } if (depth == 0 && c == ';' && !insideText) { @params.Add(par); par = ""; } else { par += c; } } if (par != "") { @params.Add(par); } m_subNodes = new ExpressionTreeNode[@params.Count]; for (int i = 0; i < @params.Count; i++) { m_subNodes[i] = new ExpressionTreeNode((string)@params[i], col, m_operatorManager); col += ((string)@params[i]).Length + 1; } // (23.02.2007 15:15) if (value.IndexOf(')') == -1 || depth > 0) throw new ExpressionException("Missing ')'", m_column, value.Length); else if (depth < 0) throw new ExpressionException("One ')' to much", m_column, value.Length); } else { m_subNodes = new ExpressionTreeNode[] {}; } m_value = functionName; m_type = NODE_TYPE.FUNCTION; } else { //Number or post data. m_value = value.Trim(); if (IsNumeric(m_value)) { m_type = NODE_TYPE.NUMBER; m_value = float.Parse((string)m_value); } else { m_type = NODE_TYPE.VARIABLE; } } }
//Search for all value nodes in expression. //Returns true if it is optimizable. //Return false if it is not optimizable. private bool FindDependices(string expKey, ExpressionTreeNode node, ArrayList coll, string relative, ExpressionTreeNode parent, bool slack) { if (node == null) { return true; } switch (node.NodeType) { case ExpressionTreeNode.NODE_TYPE.VARIABLE: //Detect relative dependicy. string key = (string)node.Value; //Check for relative usage of properties. //Etc. dependicy is 'line1.FromPoint' using '.ToPoint'. int propIndex = key.IndexOf(Calculator.PROPERTY_CHAR); if (propIndex != -1) { if (key.Substring(0, propIndex) == "") { //Set new key using full name. key = relative + key; propIndex += relative.Length; } //Check for slack. if (key == expKey) { //Recursive on 1 level. if (!slack) { return false; } else { //Accept slack. return true; } } //Treat sub-properties as properties. int nextPropIndex = key.IndexOf(Calculator.PROPERTY_CHAR, propIndex + 1); if (nextPropIndex != -1) { //Sub-property. //Treat as property. key = key.Substring(0, nextPropIndex); } } else { // The variable does not use a property. if (parent != null && parent.NodeType == ExpressionTreeNode.NODE_TYPE.FUNCTION) { IFunction func = m_functions.Item((string)parent.Value); //Check whether function has information //about which properties of variable that is used. if (func is IVariableReferencePropertyUsage) { IVariable var = this.m_calculator.Variable((string)node.Value); if (var != null) { IVariableReferencePropertyUsage propFunc = (IVariableReferencePropertyUsage)func; string[] propertyDependices = propFunc.GetDependices(var.GetType()); if (propertyDependices == null) { return false; } foreach (string prop in propertyDependices) { coll.Add(node.Value + "." + prop); // (04.05.2007 10:43) // Add child property dependices. if (var is IOptimizable) { PropertyDependicy[] deps = ((IOptimizable)var).PropertyDependices; if (deps != null) { foreach (PropertyDependicy dep in deps) { if (dep.ParentProperty.Equals(prop)) coll.Add(node.Value + "." + dep.ChildProperty); } } } } return true; } } } // Object reference. Not optimizable. return false; } //Detect property dependices. if (propIndex != -1) { string variableName = key.Substring(0, propIndex); IVariable var = m_calculator.Variable(variableName); if (var == null) { return false; } object obj = var; if (obj is IOptimizable) { IOptimizable opt = (IOptimizable)obj; string propName = key.Substring(propIndex + 1); if (opt.PropertyDependices != null) { foreach (PropertyDependicy propertyDep in opt.PropertyDependices) { if (propertyDep.ChildProperty == propName) { //Add dependicy for property dependicy. coll.Add(variableName + Calculator.PROPERTY_CHAR + propertyDep.ParentProperty); } } } } } coll.Add(key); return true; case ExpressionTreeNode.NODE_TYPE.FUNCTION: case ExpressionTreeNode.NODE_TYPE.OPERATOR: IFunction nodeFunction = m_functions.Item((string)node.Value); if (nodeFunction is IRandomFunction) { //Not optimizable. return false; } //Check if function is slack. bool isSlack = false; if (nodeFunction is ISlackFunction) { isSlack = true; } bool optimizable = true; bool childOptimizable = false; foreach (ExpressionTreeNode child in node.SubNodes) { childOptimizable = FindDependices(expKey, child, coll, relative, node, isSlack); optimizable = optimizable & childOptimizable; } return optimizable; default: return true; // default: // //Operator. // bool isOptimizable = true; // isOptimizable = isOptimizable & FindDependices(expKey, node.Left, coll, relative, null, false); // isOptimizable = isOptimizable & FindDependices(expKey, node.Right, coll, relative, null, false); // return isOptimizable; } }