public IEnumerable <VariablesExpression> SearchGroups(string validatedFormula) { if (string.IsNullOrWhiteSpace(validatedFormula)) { throw new InvalidFormulaException(validatedFormula, "formula is null or whitespace"); } if (validatedFormula.IndexOf('=') < 0) { throw new InvalidFormulaException(validatedFormula, "must contain '=' sign"); } var state = new SearchState(_pool.Get(), _expressionFactory, validatedFormula); var formulaBuilder = _pool.Get().Append(validatedFormula); try { for (int i = 0; i < formulaBuilder.Length; i++) { if (formulaBuilder[i] == ' ') { formulaBuilder.Remove(i--, 1); continue; } var currentChar = formulaBuilder[i]; if (currentChar == '=') { // (x= var hasOpenedGroup = state.OperatorsStack.Contains('('); // x=x= var hasAnotherEqualSign = state.OperatorsStack.Contains('='); // =x var noLeftSideVariables = state.VariableBuilder.Length == 0 && state.ExpressionsStack.Count == 0; // x+=; length is important : x= (builder == x, operators stack is empty) var hasOpenedOperator = state.VariableBuilder.Length == 0 && state.ExpressionsStack.Count > 0; if (hasOpenedGroup || hasAnotherEqualSign || noLeftSideVariables) { throw new InvalidFormulaException(validatedFormula, "'=' operator should be single and follow ')' or variable"); } } switch (currentChar) { case '=': case '-' when i == 0 || formulaBuilder[i - 1] != '^': case '+': { state.CheckAndAddNilElement(currentChar); if (state.OperatorsStack.Count > 0) { var prevOperator = state.OperatorsStack.Peek(); if (prevOperator == '-' || prevOperator == '+') { state.ApplyTopOperator(); } } state.PushOperator(currentChar, i); } break; case '(': state.PushOperator(currentChar, i); break; case ')': state.ApplyParenthesis(); break; default: state.VariableBuilder.Append(currentChar); break; } } while (state.OperatorsStack.Count > 0) { state.ApplyTopOperator(); } if (state.ExpressionsStack.Count > 1) { throw new InvalidFormulaException(validatedFormula, "cannot transform formula to single expression"); } return(state.ExpressionsStack.Pop().Expressions); } finally { _pool.Return(state.VariableBuilder); _pool.Return(formulaBuilder); } }