private static double Calculate(ExpressionOperand root, Dictionary <string, double> varValues) { if (root.IsConstant) { return(root.ConstantValue); } if (root.IsVariable) { double result; if (!varValues.TryGetValue(root.VariableName, out result)) { throw new Exception(string.Format("Переменная \"{0}\" не определена", root.VariableName)); } return(result); } var valLeft = root.OperandLeft == null ? 0 : Calculate(root.OperandLeft, varValues); var valRight = root.OperandRight == null ? 0 : Calculate(root.OperandRight, varValues); return(CalculateOperator(root.Operator, valLeft, valRight)); }
private static void GetVariableNames(ExpressionOperand root, List <string> vars) { if (root == null) { return; } if (root.IsVariable) { vars.Add(root.VariableName); } else { if (root.OperandLeft != null) { GetVariableNames(root.OperandLeft, vars); } if (root.OperandRight != null) { GetVariableNames(root.OperandRight, vars); } } }
private static void BuildOperandTree(ref ExpressionOperand root, string formula, List <ExpressionOperatorEntry> operators) { if (string.IsNullOrEmpty(formula)) { throw new ArgumentException("BuildOperandTree() - formula пуста", "formula"); } // освободить формулу от обрамляющих скобок, если имеются while (true) { if (HasRedundantBraces(formula)) { formula = formula.Substring(1, formula.Length - 2); foreach (var op in operators) { op.start -= 1; op.end -= 1; } } else { break; } } if (string.IsNullOrEmpty(formula)) { throw new ArgumentException("BuildOperandTree() - formula пуста", "formula"); } if (operators.Count == 0) {// либо константа, либо - переменная var constVal = formula.ToDoubleUniformSafe(); if (constVal.HasValue) { root = new ExpressionOperand { IsConstant = true, ConstantValue = constVal.Value }; return; } // будем считать переменной root = new ExpressionOperand { IsVariable = true, VariableName = formula }; return; } root = new ExpressionOperand(); // найти самый низко-приоритетный оператор var minPrior = operators.Min(op => op.priority); var firstOper = operators.Last(op => op.priority == minPrior); root.Operator = firstOper.oper; // получить левый и правый (если есть) операнды // есть левый операнд if (firstOper.start > 0) { var leftOpers = new List <ExpressionOperatorEntry>(); foreach (var op in operators) { if (op.start >= firstOper.start) { continue; } leftOpers.Add(new ExpressionOperatorEntry(op.oper, op.start, op.end) { priority = op.priority }); } var partLeft = formula.Substring(0, firstOper.start); ExpressionOperand leftRoot = null; BuildOperandTree(ref leftRoot, partLeft, leftOpers); root.OperandLeft = leftRoot; } // есть правый операнд if (firstOper.end < formula.Length) { var rightOpers = new List <ExpressionOperatorEntry>(); foreach (var op in operators) { if (op.start <= firstOper.start) { continue; } rightOpers.Add(new ExpressionOperatorEntry(op.oper, op.start - firstOper.end, op.end - firstOper.end) { priority = op.priority }); } var partRight = formula.Substring(firstOper.end); ExpressionOperand rightRoot = null; BuildOperandTree(ref rightRoot, partRight, rightOpers); root.OperandRight = rightRoot; } }
private static bool ParseSimpleFormulaBranch(ExpressionOperand root, List<Cortege3<PerformerStatField, ExpressionOperator, double>> filters) { if (root.Operator == ExpressionOperator.And) { if (root.OperandLeft.IsConstant || root.OperandLeft.IsConstant) return false; if (root.OperandRight.IsConstant || root.OperandRight.IsConstant) return false; if (!ParseSimpleFormulaBranch(root.OperandLeft, filters)) return false; if (!ParseSimpleFormulaBranch(root.OperandRight, filters)) return false; return true; } if (root.Operator == ExpressionOperator.Greater || root.Operator == ExpressionOperator.Lower || root.Operator == ExpressionOperator.Equal) { if (!root.OperandLeft.IsVariable) return false; if (!root.OperandRight.IsConstant) return false; var field = fields.FirstOrDefault(f => f.ExpressionParamName != null && f.ExpressionParamName.Equals(root.OperandLeft.VariableName, StringComparison.OrdinalIgnoreCase)); if (field == null) return false; filters.Add(new Cortege3<PerformerStatField, ExpressionOperator, double>(field, root.Operator, root.OperandRight.ConstantValue)); return true; } return false; }
private static void BuildOperandTree(ref ExpressionOperand root, string formula, List<ExpressionOperatorEntry> operators) { if (string.IsNullOrEmpty(formula)) throw new ArgumentException("BuildOperandTree() - formula пуста", "formula"); // освободить формулу от обрамляющих скобок, если имеются while (true) { if (HasRedundantBraces(formula)) { formula = formula.Substring(1, formula.Length - 2); foreach (var op in operators) { op.start -= 1; op.end -= 1; } } else break; } if (string.IsNullOrEmpty(formula)) throw new ArgumentException("BuildOperandTree() - formula пуста", "formula"); if (operators.Count == 0) {// либо константа, либо - переменная var constVal = formula.ToDoubleUniformSafe(); if (constVal.HasValue) { root = new ExpressionOperand { IsConstant = true, ConstantValue = constVal.Value }; return; } // будем считать переменной root = new ExpressionOperand { IsVariable = true, VariableName = formula }; return; } root = new ExpressionOperand(); // найти самый низко-приоритетный оператор var minPrior = operators.Min(op => op.priority); var firstOper = operators.Last(op => op.priority == minPrior); root.Operator = firstOper.oper; // получить левый и правый (если есть) операнды // есть левый операнд if (firstOper.start > 0) { var leftOpers = new List<ExpressionOperatorEntry>(); foreach (var op in operators) { if (op.start >= firstOper.start) continue; leftOpers.Add(new ExpressionOperatorEntry(op.oper, op.start, op.end) { priority = op.priority }); } var partLeft = formula.Substring(0, firstOper.start); ExpressionOperand leftRoot = null; BuildOperandTree(ref leftRoot, partLeft, leftOpers); root.OperandLeft = leftRoot; } // есть правый операнд if (firstOper.end < formula.Length) { var rightOpers = new List<ExpressionOperatorEntry>(); foreach (var op in operators) { if (op.start <= firstOper.start) continue; rightOpers.Add(new ExpressionOperatorEntry(op.oper, op.start - firstOper.end, op.end - firstOper.end) { priority = op.priority }); } var partRight = formula.Substring(firstOper.end); ExpressionOperand rightRoot = null; BuildOperandTree(ref rightRoot, partRight, rightOpers); root.OperandRight = rightRoot; } }
private static double Calculate(ExpressionOperand root, Dictionary<string, double> varValues) { if (root.IsConstant) return root.ConstantValue; if (root.IsVariable) { double result; if (!varValues.TryGetValue(root.VariableName, out result)) throw new Exception(string.Format("Переменная \"{0}\" не определена", root.VariableName)); return result; } var valLeft = root.OperandLeft == null ? 0 : Calculate(root.OperandLeft, varValues); var valRight = root.OperandRight == null ? 0 : Calculate(root.OperandRight, varValues); return CalculateOperator(root.Operator, valLeft, valRight); }
private static void GetVariableNames(ExpressionOperand root, List<string> vars) { if (root == null) return; if (root.IsVariable) vars.Add(root.VariableName); else { if (root.OperandLeft != null) GetVariableNames(root.OperandLeft, vars); if (root.OperandRight != null) GetVariableNames(root.OperandRight, vars); } }