コード例 #1
0
        private static Expression ArithmeticExpression(Expression expr1, ExpressionOperatorType @operator, Expression expr2)
        {
            Expression rdo;

            switch (@operator)
            {
            case ExpressionOperatorType.Add:
                rdo = Expression.Add(expr1, expr2);
                break;

            case ExpressionOperatorType.Substract:
                rdo = Expression.Subtract(expr1, expr2);
                break;

            case ExpressionOperatorType.Multiply:
                rdo = Expression.Multiply(expr1, expr2);
                break;

            case ExpressionOperatorType.Divide:
                rdo = Expression.Divide(expr1, expr2);
                break;

            case ExpressionOperatorType.Modulo:
                rdo = Expression.Modulo(expr1, expr2);
                break;

            case ExpressionOperatorType.Power:
                rdo = Expression.Power(expr1, expr2);
                break;

            default:
                throw new InvalidOperationException(@operator.ToString());     // TODO: Mejorar error.
            }
            return(rdo);
        }
コード例 #2
0
 public Expression(ExpressionOperatorType op, object operand, object value)
     : this()
 {
     Operator = op;
     LHS      = operand?.ToString();
     RHS      = value?.ToString();
 }
コード例 #3
0
        private static Expression RelationalExpression(Expression expr1, ExpressionOperatorType @operator, Expression expr2)
        {
            Expression rdo;
            var        masterExpr = GetMasterOrSlaveExpression(expr1, expr2, master: true);
            var        slaveExpr  = GetMasterOrSlaveExpression(expr1, expr2, master: false);

            // Obtener la parte de la expressión que debería adaptar su tipo a la principal.
            if (masterExpr.Type != slaveExpr.Type)
            {
                if (expr1 == slaveExpr)
                {
                    expr1 = Expression.Convert(slaveExpr, masterExpr.Type);
                }
                else
                {
                    expr2 = Expression.Convert(slaveExpr, masterExpr.Type);
                }
            }

            switch (@operator)
            {
            case ExpressionOperatorType.Equals:
                rdo = Expression.Equal(expr1, expr2);
                break;

            case ExpressionOperatorType.NotEqual:
                rdo = Expression.NotEqual(expr1, expr2);
                break;

            case ExpressionOperatorType.GreaterThan:
                rdo = Expression.GreaterThan(expr1, expr2);
                break;

            case ExpressionOperatorType.GreaterThanOrEqual:
                rdo = Expression.GreaterThanOrEqual(expr1, expr2);
                break;

            case ExpressionOperatorType.LessThan:
                rdo = Expression.LessThan(expr1, expr2);
                break;

            case ExpressionOperatorType.LessThanOrEqual:
                rdo = Expression.LessThanOrEqual(expr1, expr2);
                break;

            case ExpressionOperatorType.Like:
                throw new NotImplementedException(@operator.ToString());

            default:
                throw new InvalidOperationException(@operator.ToString());     // TODO: Mejorar error.
            }
            return(rdo);
        }
コード例 #4
0
ファイル: ExpressionString.cs プロジェクト: hfrances/qckdev
        private void ProcessBufferArithmeticOperator(ref ExpressionNode currentNode, ExpressionOperatorType @operator)
        {
            bool isValidNode(ExpressionNodeType type)
            {
                return(type.In(ExpressionNodeType.ArithmeticOperator, ExpressionNodeType.Default) || IsValueNode(type));
            }

            // Buscar el nodo donde se puede aplicar el operador.
            currentNode = FindNodeForOperator(currentNode, @operator, isValidNode, GetArithmeticOperator);

            // Las operaciones se van solapando.
            ApplyParentNode(currentNode, ExpressionNodeType.ArithmeticOperator, @operator);
        }
コード例 #5
0
ファイル: ExpressionString.cs プロジェクト: hfrances/qckdev
        /// <summary>
        /// Devuelve la prioridad de cálculo del operador de menor a mayor.
        /// Esto permite hacer las multiplicaciones antes que las sumas, las potencias antes que las multiplicaciones, los AND antes que los OR, etc.
        /// </summary>
        /// <param name="operator">Operador a validar.</param>
        /// <returns>La prioridad de cálculo del operador, de menor a mayor.</returns>
        /// <remarks>
        /// <seealso href="https://stackoverflow.com/questions/1241142/sql-logic-operator-precedence-and-and-or"/>
        /// <seealso href="https://docs.microsoft.com/en-us/sql/t-sql/language-elements/operator-precedence-transact-sql?view=sql-server-2017"/>
        /// </remarks>
        private static int GetOperatorPriority(ExpressionOperatorType @operator)
        {
            int rdo;

            switch (@operator)
            {
            case ExpressionOperatorType.Like:
            case ExpressionOperatorType.In:
            case ExpressionOperatorType.Or:
                rdo = 1;
                break;

            case ExpressionOperatorType.And:
                rdo = 2;
                break;

            case ExpressionOperatorType.Not:
                rdo = 3;
                break;

            case ExpressionOperatorType.Equals:
            case ExpressionOperatorType.NotEqual:
            case ExpressionOperatorType.GreaterThan:
            case ExpressionOperatorType.GreaterThanOrEqual:
            case ExpressionOperatorType.LessThan:
            case ExpressionOperatorType.LessThanOrEqual:
                rdo = 4;
                break;

            case ExpressionOperatorType.Add:
            case ExpressionOperatorType.Substract:
                rdo = 5;
                break;

            case ExpressionOperatorType.Multiply:
            case ExpressionOperatorType.Divide:
            case ExpressionOperatorType.Modulo:
                rdo = 6;
                break;

            case ExpressionOperatorType.Power:
                rdo = 7;
                break;

            default:
                rdo = 0;
                break;
            }
            return(rdo);
        }
コード例 #6
0
ファイル: ExpressionString.cs プロジェクト: hfrances/qckdev
        private void ProcessOperator(ref ExpressionNode current, ExpressionOperatorType @operator, int charIndex)
        {
            switch (@operator)
            {
            case ExpressionOperatorType.Add:
            case ExpressionOperatorType.Substract:
            case ExpressionOperatorType.Multiply:
            case ExpressionOperatorType.Divide:
            case ExpressionOperatorType.Modulo:
            case ExpressionOperatorType.Power:
                ProcessBufferArithmeticOperator(ref current, @operator);
                break;

            case ExpressionOperatorType.And:
            case ExpressionOperatorType.Or:
                ProcessBufferLogicOperator(ref current, @operator);
                break;

            case ExpressionOperatorType.Not:
                ProcessBufferLogicOperatorNot(ref current, charIndex);
                break;

            case ExpressionOperatorType.Equals:
            case ExpressionOperatorType.NotEqual:
            case ExpressionOperatorType.GreaterThan:
            case ExpressionOperatorType.GreaterThanOrEqual:
            case ExpressionOperatorType.LessThan:
            case ExpressionOperatorType.LessThanOrEqual:
            case ExpressionOperatorType.Like:
            case ExpressionOperatorType.In:
                ProcessBufferRelationalOperator(ref current, @operator);
                break;

            default:
                throw new NotImplementedException(@operator.ToString());
            }
        }
コード例 #7
0
ファイル: ExpressionString.cs プロジェクト: hfrances/qckdev
        /// <summary>
        /// Devuelve el nodo más próximo a <paramref name="currentNode"/> al que se le pueda asignar la operación especificada.
        /// </summary>
        /// <param name="currentNode">Nodo de inicio de búsqueda.</param>
        /// <param name="operator">Operador que se desea aplicar.</param>
        /// <param name="isValidNodeFunc">Función que valida los nodos sobre los que puede buscar.</param>
        /// <param name="getOperatorFunc">Función que devuelve el tipo de operador del nodo durante las búsquedas.</param>
        /// <returns>El nodo más próximo al que se le pueda asignar la operación especificada.</returns>
        private static ExpressionNode FindNodeForOperator(ExpressionNode currentNode, ExpressionOperatorType @operator,
                                                          Func <ExpressionNodeType, bool> isValidNodeFunc, Func <ExpressionNode, ExpressionOperatorType> getOperatorFunc)
        {
            ExpressionNode rdo;
            var            repeat          = true;
            var            newPriority     = GetOperatorPriority(@operator);
            var            currentOperator = getOperatorFunc(currentNode);
            var            currentPriority = GetOperatorPriority(currentOperator);

            rdo = currentNode;
            if (isValidNodeFunc(rdo.Type) && newPriority > currentPriority)
            {
                repeat = false; // Puesto que la operación anterior es de menor prioridad, este es el nivel correcto.
            }

            while (repeat)
            {
                var parentNode = rdo.ParentNode;

                if (parentNode == null)
                {
                    repeat = false; // Top level, no se puede ir más arriba.
                }
                else if (parentNode.Locked || !isValidNodeFunc(parentNode.Type))
                {
                    // A partir de la primera vez, si el nodo está bloqueado, ya no se podrá subir más hacia arriba
                    // (el nodo inicial puede ser de paréntesis, pero está fuera de é).
                    repeat = false;
                }
                else
                {
                    var parentOperator = getOperatorFunc(parentNode);
                    var parentPriority = GetOperatorPriority(parentOperator);

                    if (isValidNodeFunc(rdo.Type) && newPriority > parentPriority)
                    {
                        repeat = false; // Puesto que la operación de nivel superior es de menor prioridad, este es el nivel correcto.
                    }
                    else
                    {
                        rdo = parentNode; // Probar suerte con el padre.
                    }
                }
            }
            return(rdo);
        }
コード例 #8
0
ファイル: ExpressionString.cs プロジェクト: hfrances/qckdev
        /// <summary>
        /// Modifica la expresión del parámetro <paramref name="node"/> añadiendo primero los datos actuales a un nodo inferior.
        /// </summary>
        /// <param name="node">Nodo a modificar.</param>
        /// <param name="parentType">Nuevo tipo</param>
        /// <param name="parentOperator">Nuevo operador.</param>
        private static void ApplyParentNode(ExpressionNode node, ExpressionNodeType parentType, ExpressionOperatorType parentOperator)
        {
            var rdo = new ExpressionNode(node.ExpressionTree)
            {
                // Mover la expresión debajo del operador.
                Type          = node.Type,
                Operator      = node.Operator,
                StartIndex    = node.StartIndex,
                EndIndex      = node.EndIndex,
                FormattedText = node.FormattedText,
                Locked        = node.Locked,
            };

            rdo.Nodes.AddRange(node.Nodes);

            node.Nodes.Clear();
            node.Nodes.Add(rdo);
            node.Type          = parentType;
            node.Operator      = parentOperator;
            node.EndIndex      = null;
            node.FormattedText = null;
            node.Locked        = false;
        }
コード例 #9
0
 public Expression(ExpressionOperatorType op)
     : this(op, null)
 {
 }
コード例 #10
0
 public Expression(ExpressionOperatorType op, object value)
     : this(op, null, value)
 {
 }