public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression(binaryOperatorExpression); // Looking for patterns like: // // (x - 2) - 2 // (x / 2) / 2 // (x - 2) + 4 // (x * 2) / 3 var pattern = new BinaryOperatorExpression { Left = new ParenthesizedExpression { Expression = new BinaryOperatorExpression { Left = new AnyNode("left"), Operator = BinaryOperatorType.Any, Right = new AnyNode("rightA") } }, Operator = BinaryOperatorType.Any, Right = new AnyNode("rightB") }; if (binaryOperatorExpression.Operator != BinaryOperatorType.Add && binaryOperatorExpression.Operator != BinaryOperatorType.Subtract && binaryOperatorExpression.Operator != BinaryOperatorType.Multiply && binaryOperatorExpression.Operator != BinaryOperatorType.Divide) { return; } if (pattern.IsMatch(binaryOperatorExpression)) { var match = pattern.Match(binaryOperatorExpression); var outerOperator = binaryOperatorExpression.Operator; var innerOperator = (BinaryOperatorType)((dynamic)binaryOperatorExpression.Left).Expression.Operator; var innerValue = AstHelpers.GetValueFromExpression((Expression)match.Get("rightA").First()); var outerValue = AstHelpers.GetValueFromExpression((Expression)match.Get("rightB").First()); if (innerValue == null && outerValue == null) return; // If the operators are equal, then we handle expression like (x - 2) - 4. if (innerOperator == outerOperator) { dynamic resultValue; switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: case BinaryOperatorType.Subtract: resultValue = innerValue + outerValue; break; case BinaryOperatorType.Multiply: case BinaryOperatorType.Divide: resultValue = innerValue * outerValue; break; default: return; } binaryOperatorExpression.ReplaceWith(new BinaryOperatorExpression( (match.Get("left").First() as Expression).Clone(), binaryOperatorExpression.Operator, new PrimitiveExpression(resultValue))); return; } // Otherwise handle the slightly more complex cases. PrimitiveExpression result = null; switch (innerOperator) { case BinaryOperatorType.Add: switch (outerOperator) { case BinaryOperatorType.Subtract: result = new PrimitiveExpression(innerValue - outerValue); break; } break; case BinaryOperatorType.Subtract: switch (outerOperator) { case BinaryOperatorType.Add: result = new PrimitiveExpression(innerValue - outerValue); break; } break; } if (result != null) { binaryOperatorExpression.ReplaceWith(new BinaryOperatorExpression( (match.Get("left").First() as Expression).Clone(), binaryOperatorExpression.Operator, result)); } } }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression(binaryOperatorExpression); // Looking for patterns like: // // (x - 2) - x var pattern = new BinaryOperatorExpression { Left = new ParenthesizedExpression { Expression = new BinaryOperatorExpression { Left = new NamedNode( "ident", new IdentifierExpression { Identifier = Pattern.AnyString }), Operator = BinaryOperatorType.Any, Right = new AnyNode("other") } }, Operator = BinaryOperatorType.Any, Right = new IdentifierExpressionBackreference("ident") }; if (pattern.IsMatch(binaryOperatorExpression)) { var match = pattern.Match(binaryOperatorExpression); var innerOperator = (BinaryOperatorType)((dynamic)binaryOperatorExpression).Left.Expression.Operator; var outerOperator = binaryOperatorExpression.Operator; switch (outerOperator) { case BinaryOperatorType.Subtract: switch (innerOperator) { case BinaryOperatorType.Add: binaryOperatorExpression.ReplaceWith(((AstNode)match.Get("other").First()).Clone()); return; case BinaryOperatorType.Subtract: binaryOperatorExpression.ReplaceWith(new UnaryOperatorExpression( UnaryOperatorType.Minus, ((Expression)match.Get("other").First()).Clone())); return; } break; } } // Looking for patterns like: // // (2 - x) + x pattern = new BinaryOperatorExpression { Left = new ParenthesizedExpression { Expression = new BinaryOperatorExpression { Left = new AnyNode("other"), Operator = BinaryOperatorType.Any, Right = new NamedNode( "ident", new IdentifierExpression { Identifier = Pattern.AnyString }) } }, Operator = BinaryOperatorType.Any, Right = new IdentifierExpressionBackreference("ident") }; if (pattern.IsMatch(binaryOperatorExpression)) { var match = pattern.Match(binaryOperatorExpression); var innerOperator = (BinaryOperatorType)((dynamic) binaryOperatorExpression).Left.Expression.Operator; var outerOperator = binaryOperatorExpression.Operator; switch (outerOperator) { case BinaryOperatorType.Add: switch (innerOperator) { case BinaryOperatorType.Subtract: binaryOperatorExpression.ReplaceWith(((AstNode)match.Get("other").First()).Clone()); return; } break; case BinaryOperatorType.Subtract: switch (innerOperator) { case BinaryOperatorType.Add: binaryOperatorExpression.ReplaceWith(((AstNode)match.Get("other").First()).Clone()); return; } break; } } // Looking for patterns like: // // (x - (2 + x)) pattern = new BinaryOperatorExpression { Left = new NamedNode("ident", new IdentifierExpression { Identifier = Pattern.AnyString }), Operator = BinaryOperatorType.Any, Right = new ParenthesizedExpression { Expression = new BinaryOperatorExpression { Left = new AnyNode("other"), Operator = BinaryOperatorType.Any, Right = new IdentifierExpressionBackreference("ident") } } }; if (pattern.IsMatch(binaryOperatorExpression)) { var match = pattern.Match(binaryOperatorExpression); var innerOperator = (BinaryOperatorType)((dynamic)binaryOperatorExpression).Right.Expression.Operator; var outerOperator = binaryOperatorExpression.Operator; switch (outerOperator) { case BinaryOperatorType.Subtract: switch (innerOperator) { case BinaryOperatorType.Add: binaryOperatorExpression.ReplaceWith(((AstNode)match.Get("other").First()).Clone()); return; } break; } } // Looking for patterns like: // // (x - (x - 2)) pattern = new BinaryOperatorExpression { Left = new NamedNode( "ident", new IdentifierExpression { Identifier = Pattern.AnyString }), Operator = BinaryOperatorType.Any, Right = new ParenthesizedExpression { Expression = new BinaryOperatorExpression { Left = new IdentifierExpressionBackreference("ident"), Operator = BinaryOperatorType.Any, Right = new AnyNode("other") } } }; if (pattern.IsMatch(binaryOperatorExpression)) { var match = pattern.Match(binaryOperatorExpression); var innerOperator = (BinaryOperatorType)((dynamic) binaryOperatorExpression).Right.Expression.Operator; var outerOperator = binaryOperatorExpression.Operator; switch (outerOperator) { case BinaryOperatorType.Subtract: switch (innerOperator) { case BinaryOperatorType.Subtract: binaryOperatorExpression.ReplaceWith(((AstNode)match.Get("other").First()).Clone()); return; } break; } } }