Esempio n. 1
0
        private static ExpressionChain CombineHighestPriorityLogicalOperatorsIntoSubExpressions(ExpressionChain expressionChain)
        {
            var operatorPriorities      = expressionChain.Operators.Select(GetLogicalOperatorPriority).ToList();
            var highestOperatorPriority = operatorPriorities.Max();
            var newExpressions          = new List <ISearchExpression>();
            var newOperators            = new List <string>();
            var leftExpression          = expressionChain.Expressions[0];

            for (var operatorIndex = 0; operatorIndex < expressionChain.Operators.Count; operatorIndex++)
            {
                var logicalOperator  = expressionChain.Operators[operatorIndex];
                var operatorPriority = GetLogicalOperatorPriority(logicalOperator);
                var rightExpression  = expressionChain.Expressions[operatorIndex + 1];
                if (operatorPriority == highestOperatorPriority)
                {
                    leftExpression = CombineExpressions(leftExpression, logicalOperator, rightExpression);
                }
                else
                {
                    newExpressions.Add(leftExpression);
                    newOperators.Add(logicalOperator);
                    leftExpression = rightExpression;
                }
            }
            newExpressions.Add(leftExpression);
            return(new ExpressionChain(newExpressions, newOperators));
        }
Esempio n. 2
0
        public ExpressionChain SplitIntoExpressions(string stripped, string[] keywords)
        {
            var          topLevelClause       = string.Empty;
            var          subExpressions       = new List <SubSearchExpression>();
            var          openParenthesisCount = 0;
            var          currentSubExpression = string.Empty;
            const string SubExpressionKeyword = "subexpression";
            var          subexpressionPattern = $@"\[{SubExpressionKeyword}(?<idx>[0-9]+)\]";

            if (Regex.IsMatch(stripped, $".*{subexpressionPattern}.*"))
            {
                throw new FormatException(); // Query contains our magic subexpression keyword
            }
            foreach (var c in stripped)
            {
                if (c == '(')
                {
                    openParenthesisCount++;
                    if (openParenthesisCount == 1)
                    {
                        continue;
                    }
                }
                if (c == ')')
                {
                    openParenthesisCount--;
                    if (openParenthesisCount == 0)
                    {
                        topLevelClause += $"[{SubExpressionKeyword}{subExpressions.Count}]";
                        subExpressions.Add(new SubSearchExpression(currentSubExpression));
                        currentSubExpression = string.Empty;
                        continue;
                    }
                }
                var isSubExpression = openParenthesisCount > 0;
                if (isSubExpression)
                {
                    currentSubExpression += c;
                }
                else
                {
                    topLevelClause += c;
                }
            }

            var topLevelExpressions = topLevelClause.Split(keywords, StringSplitOptions.None).Select(x => x.Trim()).ToList();
            var expressions         = new List <ISearchExpression>();

            foreach (var topLevelExpression in topLevelExpressions)
            {
                var pureSubExpressionMatch = Regex.Match(topLevelExpression, $"^{subexpressionPattern}$");
                if (pureSubExpressionMatch.Success)
                {
                    var subExpressionIdx = int.Parse(pureSubExpressionMatch.Groups["idx"].Value);
                    expressions.Add(subExpressions[subExpressionIdx]);
                }
                else
                {
                    var partialSubExpressionMatch = Regex.Match(topLevelExpression, subexpressionPattern);
                    if (partialSubExpressionMatch.Success)
                    {
                        var subExpressionIdx      = int.Parse(partialSubExpressionMatch.Groups["idx"].Value);
                        var subExpression         = subExpressions[subExpressionIdx];
                        var subExpressionReplaced = Regex.Replace(
                            topLevelExpression,
                            subexpressionPattern,
                            $"({subExpression.Value})");
                        expressions.Add(new SearchExpression(subExpressionReplaced));
                    }
                    else
                    {
                        expressions.Add(new SearchExpression(topLevelExpression));
                    }
                }
            }

            var detectedKeywords = keywords
                                   .SelectMany(keyword => topLevelClause.AllIndicesOf(keyword).Select(idx => new
            {
                Keyword = keyword.Trim(),
                Index   = idx
            }))
                                   .OrderBy(x => x.Index)
                                   .Select(x => x.Keyword)
                                   .ToList();
            var candidateChain = new ExpressionChain(expressions, detectedKeywords);

            if (!candidateChain.Operators.Any() &&
                candidateChain.Expressions.Count == 1 &&
                candidateChain.Expressions.Single() is SubSearchExpression)
            {
                return(SplitIntoExpressions(candidateChain.Expressions.Single().Value, DataApiSqlOperators.LogicalOperators));
            }
            return(candidateChain);
        }