Пример #1
0
        internal bool Expression(out QueryExpression op)
        {
            if (++_depth > 128)
            {
                ThrowQueryException("Query is too complex, over 128 nested clauses are not allowed");
            }
            if (Scanner.Position != _statePos)
            {
                _statePos = Scanner.Position;
                _state    = NextTokenOptions.Parenthesis;
            }
            var result = Binary(out op);

            _depth--;
            return(result);
        }
Пример #2
0
        private bool Parenthesis(out QueryExpression op)
        {
            if (Scanner.TryScan('(') == false)
            {
                _state = NextTokenOptions.BinaryOp;
                return(Binary(out op));
            }

            if (Expression(out op) == false)
            {
                return(false);
            }

            if (Scanner.TryScan(')') == false)
            {
                ThrowParseException("Unmatched parenthesis, expected ')'");
            }
            return(true);
        }
Пример #3
0
        private bool Binary(out QueryExpression op)
        {
            switch (_state)
            {
            case NextTokenOptions.Parenthesis:
                if (Parenthesis(out op) == false)
                {
                    return(false);
                }
                break;

            case NextTokenOptions.BinaryOp:
                _state = NextTokenOptions.Parenthesis;
                if (Operator(true, out op) == false)
                {
                    return(false);
                }
                break;

            default:
                op = null;
                return(false);
            }


            if (Scanner.TryScan(BinaryOperators, out var found) == false)
            {
                return(true); // found simple
            }
            var negate = Scanner.TryScan("NOT");
            var type   = found == "OR"
                ? OperatorType.Or
                : OperatorType.And;

            _state = NextTokenOptions.Parenthesis;

            var parenthesis = Scanner.TryPeek('(');

            if (Binary(out var right) == false)
            {
                ThrowParseException($"Failed to find second part of {type} expression");
            }

            if (parenthesis == false)
            {
                if (negate)
                {
                    right = NegateExpressionWithoutParenthesis(right);
                }

                // if the other arg isn't parenthesis, use operator precedence rules
                // to re-write the query
                switch (type)
                {
                case OperatorType.And:
                    if (right is BinaryExpression rightOp)
                    {
                        switch (rightOp.Operator)
                        {
                        case OperatorType.Or:
                        case OperatorType.And:

                            rightOp.Left = new BinaryExpression(op, rightOp.Left, type);
                            op           = right;
                            return(true);
                        }
                    }
                    break;
                }
            }
            else if (negate)
            {
                right = new NegatedExpression(right);
            }

            op = new BinaryExpression(op, right, type)
            {
                Parenthesis = parenthesis
            };

            return(true);
        }
Пример #4
0
        private bool Binary(out QueryExpression op)
        {
            switch (_state)
            {
            case NextTokenOptions.Parenthesis:
                if (Parenthesis(out op) == false)
                {
                    return(false);
                }
                break;

            case NextTokenOptions.BinaryOp:
                _state = NextTokenOptions.Parenthesis;
                if (Operator(true, out op) == false)
                {
                    return(false);
                }
                break;

            default:
                op = null;
                return(false);
            }


            if (Scanner.TryScan(BinaryOperators, out var found) == false)
            {
                return(true); // found simple
            }
            var negate = Scanner.TryScan("NOT");
            var type   = found == "OR"
                ? (negate ? OperatorType.OrNot : OperatorType.Or)
                : (negate ? OperatorType.AndNot : OperatorType.And);

            _state = NextTokenOptions.Parenthesis;

            var parenthesis = Scanner.TryPeek('(');

            if (Binary(out var right) == false)
            {
                ThrowParseException($"Failed to find second part of {type} expression");
            }

            if (parenthesis == false)
            {
                // if the other arg isn't parenthesis, use operator precedence rules
                // to re-write the query
                switch (type)
                {
                case OperatorType.And:
                case OperatorType.AndNot:
                    switch (right.Type)
                    {
                    case OperatorType.AndNot:
                    case OperatorType.OrNot:
                    case OperatorType.Or:
                    case OperatorType.And:

                        right.Left = new QueryExpression
                        {
                            Left  = op,
                            Right = right.Left,
                            Type  = type
                        };
                        op = right;
                        return(true);
                    }

                    break;
                }
            }


            op = new QueryExpression
            {
                Type  = type,
                Left  = op,
                Right = right
            };

            return(true);
        }