public static FilterValidationInfo Validatefilter(string expression)
        {
            FilterValidationInfo info = new FilterValidationInfo();

            info.Valid = true;
            if (!string.IsNullOrEmpty(expression))
            {
                List <ExpressionInfo> expressions    = new List <ExpressionInfo>();
                ExpressionInfo        rootExpression = new ExpressionInfo();
                int left = 0;
                while (expression[left] == ' ')
                {
                    left++;
                }
                int right = expression.Length - 1;
                while (expression[right] == ' ')
                {
                    right--;
                }
                rootExpression.Expression = expression;
                rootExpression.Left       = left;
                rootExpression.Right      = right;
                expressions.Add(rootExpression);

                ExtractExpressions(expressions, info);

                if (info.Valid)
                {
                    foreach (ExpressionInfo expr in expressions)
                    {
                        string err;
                        bool   ok = IsValidExpression(expr.Expression, out err);
                        info.Valid &= ok;
                        if (!ok)
                        {
                            expr.Error = err;
                            info.IncorrectExpressions.Add(expr);
                        }
                    }
                }
            }

            return(info);
        }
        static bool Split(string op,
                          bool binary,
                          List <ExpressionInfo> expressions,
                          int idx,
                          List <Range> constants,
                          List <Range> braces,
                          FilterValidationInfo validationInfo)
        {
            ExpressionInfo parentExpression = expressions[idx];
            string         expression       = parentExpression.Expression;
            int            operatorPosition = expression.IndexOf(op, 0, StringComparison.InvariantCultureIgnoreCase);

            while (operatorPosition != -1)
            {
                Range quotes = constants.Where(R => R.Left <operatorPosition && R.Right> operatorPosition).FirstOrDefault();
                if (quotes == null)
                {
                    Range bracePair = braces.Where(R => R.Left <operatorPosition && R.Right> operatorPosition).FirstOrDefault();
                    if (bracePair == null)
                    {
                        if (!binary && operatorPosition != 0)
                        {
                            validationInfo.Valid   = false;
                            validationInfo.Message = "Operator not found";
                            return(false);
                        }
                        if (binary && operatorPosition == 0)
                        {
                            validationInfo.Valid   = false;
                            validationInfo.Message = "Operand missing";
                            return(false);
                        }
                        expressions.RemoveAt(idx);

                        if (binary)
                        {
                            string expr1 = expression.Substring(0, operatorPosition - 1).Trim();

                            ExpressionInfo info1 = new ExpressionInfo();
                            info1.Expression = expr1;
                            int left = 0;
                            while (expression[left] == ' ')
                            {
                                left++;
                            }
                            info1.Left  = parentExpression.Left + left;
                            info1.Right = info1.Left + expr1.Length;
                            expressions.Add(info1);
                        }

                        {
                            string         expr2 = expression.Substring(operatorPosition + op.Length).Trim();
                            ExpressionInfo info2 = new ExpressionInfo();
                            info2.Expression = expr2;
                            int left = operatorPosition + op.Length;
                            while (expression[left] == ' ')
                            {
                                left++;
                            }
                            info2.Left  = parentExpression.Left + left;
                            info2.Right = info2.Left + info2.Expression.Length;
                            expressions.Add(info2);
                        }
                        return(true);
                    }
                }

                operatorPosition = expression.IndexOf(op, operatorPosition + 1, StringComparison.InvariantCultureIgnoreCase);
            }

            return(false);
        }
        static bool ParseNextExpression(int idx, List <ExpressionInfo> expressions, FilterValidationInfo validationInfo)
        {
            ExpressionInfo parentExpression = expressions[idx];
            string         expression       = expressions[idx].Expression.Trim();

            List <Range> constants = new List <Range>();
            List <Range> braces    = new List <Range>();
            bool         started   = false;

            {
                int quotePosition = -1;

                Range range = null;
                while ((quotePosition = expression.IndexOf('"', quotePosition + 1)) != -1)
                {
                    started = !started;
                    if (started)
                    {
                        range      = new Range();
                        range.Left = quotePosition;
                    }
                    else
                    {
                        range.Right = quotePosition;
                        constants.Add(range);
                    }
                }
            }
            if (started)
            {
                validationInfo.Valid   = false;
                validationInfo.Message = "Constant not terminated";
                return(false);
            }

            // braces
            int depth             = 0;
            int lastPoint         = 0;
            int leftBracePosition = -1;

            while (true)
            {
                int nextLeft  = expression.IndexOf('(', lastPoint);
                int nextRight = expression.IndexOf(')', lastPoint);
                if (nextLeft == -1 && nextRight == -1)
                {
                    break;
                }

                if (nextLeft < nextRight && nextLeft != -1)
                {
                    if (depth == 0)
                    {
                        leftBracePosition = nextLeft;
                    }
                    lastPoint = nextLeft + 1;
                    depth++;
                }
                else
                {
                    depth--;
                    if (depth == 0)
                    {
                        Range range = new Range()
                        {
                            Left = leftBracePosition, Right = nextRight
                        };
                        braces.Add(range);
                    }
                    lastPoint = nextRight + 1;
                }
            }

            if (depth != 0)
            {
                validationInfo.Valid   = false;
                validationInfo.Message = "Bracket expected";
                return(false);
            }

            Range enclosing = braces.Where(R => R.Left == 0 && R.Right == expression.Length - 1).FirstOrDefault();

            if (enclosing != null)
            {
                expressions.RemoveAt(idx);
                string         expr2 = expression.Substring(1, expression.Length - 2).Trim();
                ExpressionInfo info  = new ExpressionInfo();
                info.Expression = expr2;
                int left = 1;
                while (expression[left] == ' ')
                {
                    left++;
                }
                info.Left = parentExpression.Left + left;
                int right = 1;
                while (expression[expression.Length - right] == ' ')
                {
                    right++;
                }
                info.Right = parentExpression.Right - right;

                expressions.Add(info);

                return(true);
            }


            {
                if (Split("or", true, expressions, idx, constants, braces, validationInfo))
                {
                    return(true);
                }
            }

            {
                if (Split("and", true, expressions, idx, constants, braces, validationInfo))
                {
                    return(true);
                }
            }

            {
                if (Split("not", false, expressions, idx, constants, braces, validationInfo))
                {
                    return(true);
                }
                if (!validationInfo.Valid)
                {
                    return(false);
                }
            }

            return(false);
        }