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); }
public Expression(ExpressionOperatorType op, object operand, object value) : this() { Operator = op; LHS = operand?.ToString(); RHS = value?.ToString(); }
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); }
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); }
/// <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); }
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()); } }
/// <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); }
/// <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; }
public Expression(ExpressionOperatorType op) : this(op, null) { }
public Expression(ExpressionOperatorType op, object value) : this(op, null, value) { }