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); }
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); }
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); }
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); }