Allow null values on nodes.
This commit is contained in:
@@ -401,5 +401,45 @@ namespace VAR.ExpressionEvaluator.Tests
|
|||||||
|
|
||||||
#endregion BooleanOps
|
#endregion BooleanOps
|
||||||
|
|
||||||
|
#region Null value
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void NullValue_NullPlusAnything_EqualsNull()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null + 1"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null + 100"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("1 + null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("100 + null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null + null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void NullValue_NullMinusAnything_EqualsNull()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null - 1"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null - 100"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("1 - null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("100 - null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null - null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void NullValue_NullByAnything_EqualsNull()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null * 1"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null * 100"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("1 * null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("100 * null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null * null"));
|
||||||
|
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null / 1"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null / 100"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("1 / null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("100 / null"));
|
||||||
|
Assert.AreEqual(null, Parser.EvaluateString("null / null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
public void SetVariable(string name, object value)
|
public void SetVariable(string name, object value)
|
||||||
{
|
{
|
||||||
|
if (value is DBNull)
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (value is DateTime)
|
if (value is DateTime)
|
||||||
{
|
{
|
||||||
value = ((DateTime)value).ToString("s");
|
value = ((DateTime)value).ToString("s");
|
||||||
@@ -60,7 +65,7 @@ namespace VAR.ExpressionEvaluator
|
|||||||
{
|
{
|
||||||
if (_variables.ContainsKey(name) == false)
|
if (_variables.ContainsKey(name) == false)
|
||||||
{
|
{
|
||||||
return null;
|
throw new Exception(string.Format("Variable {0} not found", name));
|
||||||
}
|
}
|
||||||
return _variables[name];
|
return _variables[name];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
|
|
||||||
private static object BooleanAndOp(object leftValue, object rightValue)
|
private static object BooleanAndOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
bool bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
bool? bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
||||||
bool brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
bool? brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
||||||
return bLeftValue && brightValue;
|
if (bLeftValue == null || bLeftValue == null) { return null; }
|
||||||
|
return bLeftValue.Value && brightValue.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,13 @@
|
|||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ConvertToBoolean(object value)
|
public static bool? ConvertToBoolean(object value)
|
||||||
{
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (value is bool)
|
if (value is bool)
|
||||||
{
|
{
|
||||||
return (bool)value;
|
return (bool)value;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
private static object BooleanNotOp(object value)
|
private static object BooleanNotOp(object value)
|
||||||
{
|
{
|
||||||
value = ExpressionBooleanNode.ConvertToBoolean(value);
|
value = ExpressionBooleanNode.ConvertToBoolean(value);
|
||||||
|
if (value == null) { return null; }
|
||||||
return !(bool)value;
|
return !(bool)value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
|
|
||||||
private static object BooleanOrOp(object leftValue, object rightValue)
|
private static object BooleanOrOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
bool bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
bool? bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
||||||
bool brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
bool? brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
||||||
return bLeftValue || brightValue;
|
if (bLeftValue == null || bLeftValue == null) { return null; }
|
||||||
|
return bLeftValue.Value || brightValue.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object DivisionOp(object leftValue, object rightValue)
|
private static object DivisionOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string)
|
if (leftValue is string)
|
||||||
{
|
{
|
||||||
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object EqualsOp(object leftValue, object rightValue)
|
private static object EqualsOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null && rightValue == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) == 0;
|
return string.Compare((string)leftValue, (string)rightValue) == 0;
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object GreaterOrEqualThanOp(object leftValue, object rightValue)
|
private static object GreaterOrEqualThanOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) >= 0;
|
return string.Compare((string)leftValue, (string)rightValue) >= 0;
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object GreaterThanOp(object leftValue, object rightValue)
|
private static object GreaterThanOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) > 0;
|
return string.Compare((string)leftValue, (string)rightValue) > 0;
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object LessOrEqualThanOp(object leftValue, object rightValue)
|
private static object LessOrEqualThanOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) <= 0;
|
return string.Compare((string)leftValue, (string)rightValue) <= 0;
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object LessThanOp(object leftValue, object rightValue)
|
private static object LessThanOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) < 0;
|
return string.Compare((string)leftValue, (string)rightValue) < 0;
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object MinusOp(object leftValue, object rightValue)
|
private static object MinusOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string)
|
if (leftValue is string)
|
||||||
{
|
{
|
||||||
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object MultiplyOp(object leftValue, object rightValue)
|
private static object MultiplyOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string)
|
if (leftValue is string)
|
||||||
{
|
{
|
||||||
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object NotEqualsOp(object leftValue, object rightValue)
|
private static object NotEqualsOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null && rightValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string && rightValue is string)
|
if (leftValue is string && rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Compare((string)leftValue, (string)rightValue) != 0;
|
return string.Compare((string)leftValue, (string)rightValue) != 0;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace VAR.ExpressionEvaluator
|
||||||
|
{
|
||||||
|
public class ExpressionNullNode : IExpressionNode
|
||||||
|
{
|
||||||
|
public object Eval(IEvaluationContext evaluationContext)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object NumberNegateOp(object value)
|
private static object NumberNegateOp(object value)
|
||||||
{
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (value is string)
|
if (value is string)
|
||||||
{
|
{
|
||||||
if (decimal.TryParse((string)value, out decimal dec) == false)
|
if (decimal.TryParse((string)value, out decimal dec) == false)
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private static object PlusOp(object leftValue, object rightValue)
|
private static object PlusOp(object leftValue, object rightValue)
|
||||||
{
|
{
|
||||||
|
if (leftValue == null || rightValue == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (leftValue is string || rightValue is string)
|
if (leftValue is string || rightValue is string)
|
||||||
{
|
{
|
||||||
return string.Concat(Convert.ToString(leftValue), Convert.ToString(rightValue));
|
return string.Concat(Convert.ToString(leftValue), Convert.ToString(rightValue));
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ namespace VAR.ExpressionEvaluator
|
|||||||
public object Eval(IEvaluationContext evaluationContext)
|
public object Eval(IEvaluationContext evaluationContext)
|
||||||
{
|
{
|
||||||
object value = evaluationContext.GetVariable(_name);
|
object value = evaluationContext.GetVariable(_name);
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw new Exception(string.Format("Variable {0} not found", _name));
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,11 @@ namespace VAR.ExpressionEvaluator
|
|||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
return new ExpressionBooleanNode(false);
|
return new ExpressionBooleanNode(false);
|
||||||
}
|
}
|
||||||
|
if (identifierToLower == "null")
|
||||||
|
{
|
||||||
|
_tokenizer.NextToken();
|
||||||
|
return new ExpressionNullNode();
|
||||||
|
}
|
||||||
|
|
||||||
string identifier = _tokenizer.Text;
|
string identifier = _tokenizer.Text;
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
<Compile Include="ExpressionNodes\ExpressionLessThanNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionLessThanNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionMultiplyNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionMultiplyNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionNotEqualsNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionNotEqualsNode.cs" />
|
||||||
|
<Compile Include="ExpressionNodes\ExpressionNullNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionUnaryNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionUnaryNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionBinaryNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionBinaryNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionMinusNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionMinusNode.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user