public void Add(IOperationRule rule) { if (rules == null) { rules = new List <IOperationRule>(); } rules.Add(rule); }
public void Remove(IOperationRule rule) { rules?.Remove(rule); }
/// <summary> /// Registers the specified operation rule. /// </summary> /// <param name="rule"></param> public static void RegisterOperationRule(IOperationRule rule) { ObjectManager <IOperationRule> .Instance.Register(rule); g_operationExpressionCalculator = new OperationExpressionCalculator(ObjectManager <IOperationRule> .Instance.Objects); }
/// <summary> /// Calculates result of <paramref name="expressionString"/>. /// </summary> /// <param name="expressionString"></param> /// <returns></returns> public object Compute(string expressionString) { if (string.IsNullOrWhiteSpace(expressionString)) { throw new ArgumentException("expressionString is null or empty", "expressionString"); } // check format string invalidPart = this.GetInvalidPart(expressionString); if (invalidPart.Length > 0) { throw new InvalidOperationExpressionException(string.Format("Invalid characters in operation expression: {0}", invalidPart)); } // parse brackets expressionString = this.ParseBrackets(expressionString); // analyse each operand and operator IOperationRule rule = null; Element <int, IOperationOperator> element = null; IOperationOperator currentOperator = null, previousOperator = null; OperationExpressionContext context = new OperationExpressionContext(); List <object> operands = new List <object>(); Stack <object> operandsStack = new Stack <object>(); Stack <Element <int, IOperationOperator> > operatorsStack = new Stack <Element <int, IOperationOperator> >(); foreach (Match match in this.m_expressionRegex.Matches(expressionString)) { if (this.m_rules.ContainsKey(match.Value)) { rule = this.m_rules[match.Value]; currentOperator = rule.CreateOperator(context); while (operatorsStack.Count > 0) { previousOperator = operatorsStack.Peek().Component2; if (currentOperator.Priority > previousOperator.Priority) { break; } element = operatorsStack.Pop(); if ((context.AvailableOperandCount += element.Component1) < previousOperator.OperandCount) { throw new InvalidOperationExpressionException(string.Format("{0} operator needs {1} operands.", previousOperator.OwnerRule.OperatorSymbol, previousOperator.OperandCount)); } operands.Clear(); for (int i = 0; i < previousOperator.OperandCount; i++) { operands.Add(operandsStack.Pop()); } operands.Reverse(); context.AvailableOperandCount -= previousOperator.OperandCount; operandsStack.Push(previousOperator.Compute(context, operands)); ++context.AvailableOperandCount; } operatorsStack.Push(new Element <int, IOperationOperator>(Math.Min(context.AvailableOperandCount, currentOperator.OperandCount), currentOperator)); context.AvailableOperandCount -= operatorsStack.Peek().Component1; } else { operandsStack.Push(match.Value); ++context.AvailableOperandCount; } } while (operatorsStack.Count > 0) { element = operatorsStack.Pop(); previousOperator = element.Component2; if ((context.AvailableOperandCount += element.Component1) < previousOperator.OperandCount) { throw new InvalidOperationExpressionException(string.Format("{0} operator needs {1} operands.", previousOperator.OwnerRule.OperatorSymbol, previousOperator.OperandCount)); } operands.Clear(); for (int i = 0; i < previousOperator.OperandCount; i++) { operands.Add(operandsStack.Pop()); } operands.Reverse(); context.AvailableOperandCount -= previousOperator.OperandCount; operandsStack.Push(previousOperator.Compute(context, operands)); ++context.AvailableOperandCount; } if (operandsStack.Count > 1) { throw new Exception("Logic error: more than one operand is left finally."); } object result = operandsStack.Pop(); if (result is string) { result = this.GetSingleValue(context, (string)result); } return(result); }