public IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string opSymbol) { if (!(IsSupportedSymbol(opSymbol))) { throw new ArgumentException($"Unsupported operation ({opSymbol}) passed to Evaluate function"); } if (opSymbol.Equals(LogicalOperators.NOT)) { throw new ArgumentException($"Unary operator ({opSymbol}) passed to binary Evaluate function"); } var opProvider = new OperatorTypesProvider((LHS.ValueType, RHS.ValueType), opSymbol); if (opProvider.IsMismatch) { return(_valueFactory.CreateMismatchExpression($"{LHS.Token} {opSymbol} {RHS.Token}", Tokens.Variant)); } if (ArithmeticOperators.Includes(opSymbol)) { return(EvaluateArithmeticOp(opSymbol, LHS, RHS)); } if (RelationalOperators.Includes(opSymbol)) { return(EvaluateRelationalOp(opSymbol, LHS, RHS)); } return(EvaluateLogicalOperator(opSymbol, LHS, RHS)); }
private bool IsSupportedSymbol(string opSymbol) { return(ArithmeticOperators.Includes(opSymbol) || RelationalOperators.Includes(opSymbol) || LogicalOperators.Incudes(opSymbol)); }
private IParseTreeValue EvaluateArithmeticOp(string opSymbol, IParseTreeValue LHS, IParseTreeValue RHS) { Debug.Assert(ArithmeticOperators.Includes(opSymbol)); var opProvider = new OperatorTypesProvider((LHS.ValueType, RHS.ValueType), opSymbol); if (!(LHS.ParsesToConstantValue && RHS.ParsesToConstantValue)) { //Unable to resolve to a value, return an expression return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorDeclaredType)); } if (!LHS.TryLetCoerce(opProvider.OperatorEffectiveType, out var effLHS) || !RHS.TryLetCoerce(opProvider.OperatorEffectiveType, out var effRHS)) { return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorDeclaredType)); } if (opProvider.OperatorEffectiveType.Equals(Tokens.Date)) { if (!(LHS.TryLetCoerce(Tokens.Double, out effLHS) && RHS.TryLetCoerce(Tokens.Double, out effRHS))) { return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorEffectiveType)); } } if (opSymbol.Equals(ArithmeticOperators.MULTIPLY)) { return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a * b, (double a, double b) => a * b), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.DIVIDE)) { return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a / b, (double a, double b) => a / b), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.INTEGER_DIVIDE)) { return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, IntDivision, IntDivision), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.PLUS)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.String)) { return(_valueFactory.CreateValueType(Concatenate(LHS, RHS), opProvider.OperatorDeclaredType)); } if (opProvider.OperatorEffectiveType.Equals(Tokens.Date)) { var result = _valueFactory.CreateDeclaredType(Calculate(effLHS, effRHS, null, (double a, double b) => a + b), Tokens.Double); return(_valueFactory.CreateDate(result.AsDouble())); } return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a + b, (double a, double b) => a + b), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.MINUS)) { if (LHS.ValueType.Equals(Tokens.Date) && RHS.ValueType.Equals(Tokens.Date)) { return(_valueFactory.CreateDate(LHS.AsDouble() - RHS.AsDouble())); } return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a - b, (double a, double b) => a - b), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.EXPONENT)) { //Math.Pow only takes doubles, so the decimal conversion option is null return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, null, Math.Pow), opProvider.OperatorDeclaredType)); } if (opSymbol.Equals(ArithmeticOperators.MODULO)) { return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a % b, (double a, double b) => a % b), opProvider.OperatorDeclaredType)); } //ArithmeticOperators.AMPERSAND return(_valueFactory.CreateValueType(Concatenate(LHS, RHS), opProvider.OperatorDeclaredType)); }