diff --git a/VAR.ExpressionEvaluator.Tests/ParserTests.cs b/VAR.ExpressionEvaluator.Tests/ParserTests.cs
index d4d9000..19e70c5 100644
--- a/VAR.ExpressionEvaluator.Tests/ParserTests.cs
+++ b/VAR.ExpressionEvaluator.Tests/ParserTests.cs
@@ -256,5 +256,73 @@ namespace VAR.ExpressionEvaluator.Tests
#endregion Strings
+ #region Relations
+
+ [TestMethod()]
+ public void Relations_1GreatherThan2_EqualsFalse()
+ {
+ string expression = "1>2";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(false, result);
+ }
+
+ [TestMethod()]
+ public void Relations_1Equals1_EqualsTrue()
+ {
+ string expression = "1=1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(true, result);
+ }
+
+ [TestMethod()]
+ public void Relations_10NotEquals1_EqualsTrue()
+ {
+ string expression = "10!=1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(true, result);
+ }
+
+ [TestMethod()]
+ public void Relations_10LessThan1_EqualsFalse()
+ {
+ string expression = "10<1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(false, result);
+ }
+
+ [TestMethod()]
+ public void Relations_1GreaterOrEqualThan1_EqualsTrue()
+ {
+ string expression = "1>=1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(true, result);
+ }
+
+ [TestMethod()]
+ public void Relations_1LessOrEqualThan1_EqualsTrue()
+ {
+ string expression = "1<=1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(true, result);
+ }
+
+ [TestMethod()]
+ public void Relations_1GreaterOrEqualThan10_EqualsFalse()
+ {
+ string expression = "1>=10";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(false, result);
+ }
+
+ [TestMethod()]
+ public void Relations_10LessOrEqualThan1_EqualsFalse()
+ {
+ string expression = "10<=1";
+ object result = Parser.EvaluateString(expression);
+ Assert.AreEqual(false, result);
+ }
+
+ #endregion Relations
+
}
}
\ No newline at end of file
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionEqualsNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionEqualsNode.cs
new file mode 100644
index 0000000..3ed90a7
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionEqualsNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionEqualsNode : ExpressionBinaryNode
+ {
+ public ExpressionEqualsNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, EqualsOp)
+ {
+ }
+
+ private static object EqualsOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) == 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't compare non decimal values");
+ }
+ return (decimal)leftValue == (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterOrEqualThanNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterOrEqualThanNode.cs
new file mode 100644
index 0000000..7fd26dc
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterOrEqualThanNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionGreaterOrEqualThanNode : ExpressionBinaryNode
+ {
+ public ExpressionGreaterOrEqualThanNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, GreaterOrEqualThanOp)
+ {
+ }
+
+ private static object GreaterOrEqualThanOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) >= 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't compare non decimal values");
+ }
+ return (decimal)leftValue >= (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterThanNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterThanNode.cs
new file mode 100644
index 0000000..d7a0fb9
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionGreaterThanNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionGreaterThanNode : ExpressionBinaryNode
+ {
+ public ExpressionGreaterThanNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, GreaterThanOp)
+ {
+ }
+
+ private static object GreaterThanOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) > 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't compare non decimal values");
+ }
+ return (decimal)leftValue > (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessOrEqualThanNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessOrEqualThanNode.cs
new file mode 100644
index 0000000..8028d70
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessOrEqualThanNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionLessOrEqualThanNode : ExpressionBinaryNode
+ {
+ public ExpressionLessOrEqualThanNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, LessOrEqualThanOp)
+ {
+ }
+
+ private static object LessOrEqualThanOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) <= 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't substract non decimal values");
+ }
+ return (decimal)leftValue <= (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessThanNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessThanNode.cs
new file mode 100644
index 0000000..6d38cbb
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionLessThanNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionLessThanNode : ExpressionBinaryNode
+ {
+ public ExpressionLessThanNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, LessThanOp)
+ {
+ }
+
+ private static object LessThanOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) < 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't compare non decimal values");
+ }
+ return (decimal)leftValue < (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionNotEqualsNode.cs b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionNotEqualsNode.cs
new file mode 100644
index 0000000..e1f5b88
--- /dev/null
+++ b/VAR.ExpressionEvaluator/ExpressionNodes/ExpressionNotEqualsNode.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace VAR.ExpressionEvaluator
+{
+ public class ExpressionNotEqualsNode : ExpressionBinaryNode
+ {
+ public ExpressionNotEqualsNode(IExpressionNode leftNode, IExpressionNode rightNode) :
+ base(leftNode, rightNode, NotEqualsOp)
+ {
+ }
+
+ private static object NotEqualsOp(object leftValue, object rightValue)
+ {
+ if (leftValue is string && rightValue is string)
+ {
+ return string.Compare((string)leftValue, (string)rightValue) != 0;
+ }
+
+ if (leftValue is string)
+ {
+ if (decimal.TryParse((string)leftValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
+ }
+ leftValue = dec;
+ }
+ if (rightValue is string)
+ {
+ if (decimal.TryParse((string)rightValue, out decimal dec) == false)
+ {
+ throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
+ }
+ rightValue = dec;
+ }
+
+ if ((leftValue is decimal) == false || (rightValue is decimal) == false)
+ {
+ throw new Exception("Can't compare non decimal values");
+ }
+ return (decimal)leftValue != (decimal)rightValue;
+ }
+ }
+}
diff --git a/VAR.ExpressionEvaluator/Parser.cs b/VAR.ExpressionEvaluator/Parser.cs
index d764be0..9a489b3 100644
--- a/VAR.ExpressionEvaluator/Parser.cs
+++ b/VAR.ExpressionEvaluator/Parser.cs
@@ -15,7 +15,7 @@ namespace VAR.ExpressionEvaluator
public IExpressionNode ParseExpression()
{
- var expr = ParsePlusAndMinus();
+ var expr = ParseRelations();
if (_tokenizer.Token != Token.EOF)
{
@@ -25,7 +25,55 @@ namespace VAR.ExpressionEvaluator
return expr;
}
- public IExpressionNode ParsePlusAndMinus()
+ private IExpressionNode ParseRelations()
+ {
+ IExpressionNode leftNode = ParsePlusAndMinus();
+ while (true)
+ {
+ if (_tokenizer.Token == Token.Equals || _tokenizer.Token == Token.ExclusiveEquals)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionEqualsNode(leftNode, rightNode);
+ }
+ else if (_tokenizer.Token == Token.NotEquals)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionNotEqualsNode(leftNode, rightNode);
+ }
+ else if (_tokenizer.Token == Token.LessThan)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionLessThanNode(leftNode, rightNode);
+ }
+ else if (_tokenizer.Token == Token.LessOrEqualThan)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionLessOrEqualThanNode(leftNode, rightNode);
+ }
+ else if (_tokenizer.Token == Token.GreaterThan)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionGreaterThanNode(leftNode, rightNode);
+ }
+ else if (_tokenizer.Token == Token.GreaterOrEqualThan)
+ {
+ _tokenizer.NextToken();
+ IExpressionNode rightNode = ParsePlusAndMinus();
+ leftNode = new ExpressionGreaterOrEqualThanNode(leftNode, rightNode);
+ }
+ else
+ {
+ return leftNode;
+ }
+ }
+ }
+
+ private IExpressionNode ParsePlusAndMinus()
{
IExpressionNode leftNode = ParseMultiplyDivision();
while (true)
@@ -155,7 +203,7 @@ namespace VAR.ExpressionEvaluator
if (_tokenizer.Token == Token.ParenthesisStart)
{
_tokenizer.NextToken();
- IExpressionNode node = ParsePlusAndMinus();
+ IExpressionNode node = ParseRelations();
if (_tokenizer.Token != Token.ParenthesisEnd)
{
throw new Exception("Missing close parenthesis");
diff --git a/VAR.ExpressionEvaluator/Token.cs b/VAR.ExpressionEvaluator/Token.cs
index 8e51910..3d39201 100644
--- a/VAR.ExpressionEvaluator/Token.cs
+++ b/VAR.ExpressionEvaluator/Token.cs
@@ -7,14 +7,16 @@
Minus,
Division,
Multiply,
+ ParenthesisStart,
+ ParenthesisEnd,
+ Not,
+ NotEquals,
Equals,
ExclusiveEquals,
GreaterThan,
GreaterOrEqualThan,
LessThan,
LessOrEqualThan,
- ParenthesisStart,
- ParenthesisEnd,
Comma,
Identifier,
String,
diff --git a/VAR.ExpressionEvaluator/Tokenizer.cs b/VAR.ExpressionEvaluator/Tokenizer.cs
index a2506b1..ac7bb84 100644
--- a/VAR.ExpressionEvaluator/Tokenizer.cs
+++ b/VAR.ExpressionEvaluator/Tokenizer.cs
@@ -101,6 +101,15 @@ namespace VAR.ExpressionEvaluator
_currentToken = Token.ParenthesisEnd;
return;
+ case '!':
+ NextChar();
+ _currentToken = Token.Not;
+ if (_currentChar == '=')
+ {
+ NextChar();
+ _currentToken = Token.NotEquals;
+ }
+ return;
case '=':
NextChar();
_currentToken = Token.Equals;
diff --git a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj
index 08ac712..978cbbb 100644
--- a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj
+++ b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj
@@ -44,8 +44,14 @@
+
+
+
+
+
+