/// <summary> /// Gets the row number in the C# 4.0 spec operator precedence table. /// </summary> static int GetPrecedence(Expression expr) { // Note: the operator precedence table on MSDN is incorrect if (expr is QueryExpression) { // Not part of the table in the C# spec, but we need to ensure that queries within // primary expressions get parenthesized. return(QueryOrLambda); } UnaryOperatorExpression uoe = expr as UnaryOperatorExpression; if (uoe != null) { if (uoe.Operator == UnaryOperatorType.PostDecrement || uoe.Operator == UnaryOperatorType.PostIncrement) { return(Primary); } else { return(Unary); } } if (expr is CastExpression) { return(Unary); } BinaryOperatorExpression boe = expr as BinaryOperatorExpression; if (boe != null) { switch (boe.Operator) { case BinaryOperatorType.Multiply: case BinaryOperatorType.Divide: case BinaryOperatorType.Modulus: return(13); // multiplicative case BinaryOperatorType.Add: case BinaryOperatorType.Subtract: return(12); // additive case BinaryOperatorType.ShiftLeft: case BinaryOperatorType.ShiftRight: return(11); case BinaryOperatorType.GreaterThan: case BinaryOperatorType.GreaterThanOrEqual: case BinaryOperatorType.LessThan: case BinaryOperatorType.LessThanOrEqual: return(RelationalAndTypeTesting); case BinaryOperatorType.Equality: case BinaryOperatorType.InEquality: return(Equality); case BinaryOperatorType.BitwiseAnd: return(8); case BinaryOperatorType.ExclusiveOr: return(7); case BinaryOperatorType.BitwiseOr: return(6); case BinaryOperatorType.ConditionalAnd: return(5); case BinaryOperatorType.ConditionalOr: return(4); case BinaryOperatorType.NullCoalescing: return(3); default: throw new NotSupportedException("Invalid value for BinaryOperatorType"); } } if (expr is IsExpression || expr is AsExpression) { return(RelationalAndTypeTesting); } if (expr is ConditionalExpression) { return(Conditional); } if (expr is AssignmentExpression || expr is LambdaExpression) { return(Assignment); } // anything else: primary expression return(Primary); }
void IAstVisitor.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { Visit(EnterUnaryOperatorExpression, LeaveUnaryOperatorExpression, unaryOperatorExpression); }
public override void VisitCastExpression(CastExpression castExpression) { ParenthesizeIfRequired(castExpression.Expression, InsertParenthesesForReadability ? Primary : Unary); // There's a nasty issue in the C# grammar: cast expressions including certain operators are ambiguous in some cases // "(int)-1" is fine, but "(A)-b" is not a cast. UnaryOperatorExpression uoe = castExpression.Expression as UnaryOperatorExpression; if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not)) { if (TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { Parenthesize(castExpression.Expression); } } // The above issue can also happen with PrimitiveExpressions representing negative values: PrimitiveExpression pe = castExpression.Expression as PrimitiveExpression; if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { TypeCode typeCode = Type.GetTypeCode(pe.Value.GetType()); switch (typeCode) { case TypeCode.SByte: if ((sbyte)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Int16: if ((short)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Int32: if ((int)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Int64: if ((long)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Single: if ((float)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Double: if ((double)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; case TypeCode.Decimal: if ((decimal)pe.Value < 0) { Parenthesize(castExpression.Expression); } break; } } base.VisitCastExpression(castExpression); }