internal static LogicalSearchExpression Create( SearchConfigurationOptions options, SearchExpression left, SearchExpression right, Operator @operator, string text) { return(new LogicalSearchExpression(options, text) { Left = left, Right = right, Operator = @operator }); }
internal static ContainsSearchExpression Create( SearchConfigurationOptions options, SearchExpression left, SearchExpression right) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } return(new ContainsSearchExpression(options, right.Text) { Left = left, Right = right }); }
/// <summary> /// Attemps to create LogicalSearchExpressions from the given text based on /// binary operators found in the text (AND, OR, etc.). /// If it finds them it will return a LogicalSearchPression with Left and Right /// filled in and the Text will contain whatever is left over. /// If it cannot find any binary operators it will just return the original /// searchExpression. /// </summary> /// <returns></returns> private SearchExpression DecomposeLogicalOperators() { var match = _binaryOperatorsSearch.Match(Text); if (!match.Success) { // easy case first. return(this); } else { var searchExpressions = new Stack <SearchExpression>(); var operators = new Stack <Operator>(); // we go left to right through the matches. for (var i = 0; i < match.Captures.Count; i++) { var previous = i > 0 ? match.Captures[i - 1] : null; var current = match.Captures[i]; var next = i < match.Captures.Count - 1 ? match.Captures[i + 1] : null; //var nextNext = i < match.Captures.Count - 2 ? match.Captures[i + 2] : null; var leftStart = previous == null ? 0 : previous.Index + previous.Length; var leftLength = current.Index - leftStart; if (leftLength > 0) { searchExpressions.Push(SearchExpression.Create(Options, Text.Substring(leftStart, leftLength))); Operator o; var currentValue = current.Value.Trim(); if (_andOperators.Contains(currentValue, StringComparer.OrdinalIgnoreCase)) { o = Operator.And; } else if (_orOperators.Contains(currentValue, StringComparer.OrdinalIgnoreCase)) { o = Operator.Or; } else { throw new InvalidOperationException($"Unknown operator '{currentValue}'"); } operators.Push(o); } if (next == null) { // this is the last one var rightStart = current.Index + current.Length; var rightLength = Text.Length - rightStart; SearchExpression leftOver; if (rightLength <= 0) { if (searchExpressions.Count > 0) { // nothing on the right side of the AND or OR, // so we take the last left and just make it a regular SearchExpression leftOver = searchExpressions.Pop(); operators.Pop(); } else { // If here we didn't find anything at all leftOver = SearchExpression.Create(Options, string.Empty); } } else { leftOver = SearchExpression.Create(Options, Text.Substring(rightStart, rightLength).Trim()); } // now we should have one more in the searchExpressions stack than in the operators stack var searchExpressionCount = searchExpressions.Count; if (searchExpressionCount == 0) { return(leftOver); } else if (searchExpressionCount == 1) { return(LogicalSearchExpression.Create(Options, searchExpressions.Pop(), leftOver, operators.Pop(), Text)); } else { // if here there is at least 2 operators which we will make into a tree var right = searchExpressions.Pop(); var left = searchExpressions.Pop(); var op = operators.Pop(); var currentExpression = LogicalSearchExpression.Create( Options, left, right, op, text: $"{left.Text} {op} {right.Text}"); while (searchExpressions.Any()) { right = currentExpression; left = searchExpressions.Pop(); op = operators.Pop(); currentExpression = LogicalSearchExpression.Create( Options, left, right, op, text: $"{left.Text} {op} {right.Text}"); } return(currentExpression); } } } // if we get here we made a logical error in our programming throw new InvalidProgramException("Error parsing logical operators from search text"); } }