Parser: Relations

This commit is contained in:
2019-12-02 02:39:32 +01:00
parent 99ca81a968
commit 4f3e5a325e
11 changed files with 396 additions and 5 deletions

View File

@@ -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
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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");

View File

@@ -7,14 +7,16 @@
Minus,
Division,
Multiply,
ParenthesisStart,
ParenthesisEnd,
Not,
NotEquals,
Equals,
ExclusiveEquals,
GreaterThan,
GreaterOrEqualThan,
LessThan,
LessOrEqualThan,
ParenthesisStart,
ParenthesisEnd,
Comma,
Identifier,
String,

View File

@@ -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;

View File

@@ -44,8 +44,14 @@
<Compile Include="EvaluationContext.cs" />
<Compile Include="ExpressionNodes\ExpressionBooleanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionDivisionNode.cs" />
<Compile Include="ExpressionNodes\ExpressionEqualsNode.cs" />
<Compile Include="ExpressionNodes\ExpressionFunctionNode.cs" />
<Compile Include="ExpressionNodes\ExpressionGreaterOrEqualThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionGreaterThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionLessOrEqualThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionLessThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionMultiplyNode.cs" />
<Compile Include="ExpressionNodes\ExpressionNotEqualsNode.cs" />
<Compile Include="ExpressionNodes\ExpressionUnaryNode.cs" />
<Compile Include="ExpressionNodes\ExpressionBinaryNode.cs" />
<Compile Include="ExpressionNodes\ExpressionMinusNode.cs" />