/// <summary> /// Create a new filter expression 'Or'ing 'this' with 'filter'. /// </summary> private FilterExpression Or(FilterExpression filter) { return(new FilterExpression(this, filter, false)); }
/// <summary> /// Return FilterExpression after parsing the given filter expression. /// </summary> internal static FilterExpression Parse(string filterString) { ValidateArg.NotNull(filterString, "filterString"); // below parsing doesn't error out on pattern (), so explicitly search for that (empty parethesis). var invalidInput = Regex.Match(filterString, @"\(\s*\)"); if (invalidInput.Success) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, CommonResources.TestCaseFilterFormatException, CommonResources.EmptyParenthesis)); } var tokens = Regex.Split(filterString, filterExpressionSeperatorString); var operatorStack = new Stack <Operator>(); var filterStack = new Stack <FilterExpression>(); // This is based on standard parsing of inorder expression using two stacks (operand stack and operator stack) // Predence(And) > Predence(Or) foreach (var inputToken in tokens) { var token = inputToken.Trim(); if (string.IsNullOrEmpty(token)) { // ignore empty tokens continue; } switch (token) { case "&": case "|": Operator currentOperator = Operator.And; if (string.Equals("|", token)) { currentOperator = Operator.Or; } // Always put only higher priority operator on stack. // if lesser prioriy -- pop up the stack and process the operator to maintain operator precedence. // if equal priority -- pop up the stack and process the operator to maintain operator associativity. // OpenBrace is special condition. & or | can come on top of OpenBrace for case like ((a=b)&c=d) while (true) { bool isEmpty = operatorStack.Count == 0; Operator stackTopOperator = isEmpty ? Operator.None : operatorStack.Peek(); if (isEmpty || stackTopOperator == Operator.OpenBrace || stackTopOperator < currentOperator) { operatorStack.Push(currentOperator); break; } stackTopOperator = operatorStack.Pop(); ProcessOperator(filterStack, stackTopOperator); } break; case "(": operatorStack.Push(Operator.OpenBrace); break; case ")": // process operators from the stack till OpenBrace is found. // If stack is empty at any time, than matching OpenBrace is missing from the expression. if (operatorStack.Count == 0) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, CommonResources.TestCaseFilterFormatException, CommonResources.MissingOpenParenthesis)); } Operator temp = operatorStack.Pop(); while (temp != Operator.OpenBrace) { ProcessOperator(filterStack, temp); if (operatorStack.Count == 0) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, CommonResources.TestCaseFilterFormatException, CommonResources.MissingOpenParenthesis)); } temp = operatorStack.Pop(); } break; default: // push the operand to the operand stack. Condition condition = Condition.Parse(token); FilterExpression filter = new FilterExpression(condition); filterStack.Push(filter); break; } } while (operatorStack.Count != 0) { Operator temp = operatorStack.Pop(); ProcessOperator(filterStack, temp); } if (filterStack.Count != 1) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, CommonResources.TestCaseFilterFormatException, CommonResources.MissingOperator)); } return(filterStack.Pop()); }
/// <summary> /// Create a new filter expression 'And'ing 'this' with 'filter'. /// </summary> private FilterExpression And(FilterExpression filter) { return(new FilterExpression(this, filter, true)); }