Parser: Boolean operations
This commit is contained in:
@@ -324,5 +324,48 @@ namespace VAR.ExpressionEvaluator.Tests
|
|||||||
|
|
||||||
#endregion Relations
|
#endregion Relations
|
||||||
|
|
||||||
|
#region BooleanOps
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void BooleanOps_And()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false and false"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false and true"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("true and false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true and true"));
|
||||||
|
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false && false"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false && true"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("true && false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true && true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void BooleanOps_Or()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false or false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("false or true"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true or false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true or true"));
|
||||||
|
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("false || false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("false || true"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true || false"));
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("true || true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod()]
|
||||||
|
public void BooleanOps_Not()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("!false"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("!true"));
|
||||||
|
|
||||||
|
Assert.AreEqual(true, Parser.EvaluateString("not false"));
|
||||||
|
Assert.AreEqual(false, Parser.EvaluateString("not true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion BooleanOps
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace VAR.ExpressionEvaluator
|
||||||
|
{
|
||||||
|
public class ExpressionBooleanAndNode : ExpressionBinaryNode
|
||||||
|
{
|
||||||
|
public ExpressionBooleanAndNode(IExpressionNode leftNode, IExpressionNode rightNode) :
|
||||||
|
base(leftNode, rightNode, BooleanAndOp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object BooleanAndOp(object leftValue, object rightValue)
|
||||||
|
{
|
||||||
|
bool bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
||||||
|
bool brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
||||||
|
return bLeftValue && brightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,5 +13,30 @@
|
|||||||
{
|
{
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ConvertToBoolean(object value)
|
||||||
|
{
|
||||||
|
if (value is bool)
|
||||||
|
{
|
||||||
|
return (bool)value;
|
||||||
|
}
|
||||||
|
if (value is decimal)
|
||||||
|
{
|
||||||
|
return (decimal)value == 0;
|
||||||
|
}
|
||||||
|
if (value is string)
|
||||||
|
{
|
||||||
|
string str = (string)value;
|
||||||
|
if (string.IsNullOrEmpty(str) || str == "0" || str.ToLower() == "false")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace VAR.ExpressionEvaluator
|
||||||
|
{
|
||||||
|
public class ExpressionBooleanNotNode : ExpressionUnaryNode
|
||||||
|
{
|
||||||
|
public ExpressionBooleanNotNode(IExpressionNode node) :
|
||||||
|
base(node, BooleanNotOp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object BooleanNotOp(object value)
|
||||||
|
{
|
||||||
|
value = ExpressionBooleanNode.ConvertToBoolean(value);
|
||||||
|
return !(bool)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace VAR.ExpressionEvaluator
|
||||||
|
{
|
||||||
|
public class ExpressionBooleanOrNode : ExpressionBinaryNode
|
||||||
|
{
|
||||||
|
public ExpressionBooleanOrNode(IExpressionNode leftNode, IExpressionNode rightNode) :
|
||||||
|
base(leftNode, rightNode, BooleanOrOp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object BooleanOrOp(object leftValue, object rightValue)
|
||||||
|
{
|
||||||
|
bool bLeftValue = ExpressionBooleanNode.ConvertToBoolean(leftValue);
|
||||||
|
bool brightValue = ExpressionBooleanNode.ConvertToBoolean(rightValue);
|
||||||
|
return bLeftValue || brightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
public IExpressionNode ParseExpression()
|
public IExpressionNode ParseExpression()
|
||||||
{
|
{
|
||||||
var expr = ParseRelations();
|
var expr = ParseBooleanOp();
|
||||||
|
|
||||||
if (_tokenizer.Token != Token.EOF)
|
if (_tokenizer.Token != Token.EOF)
|
||||||
{
|
{
|
||||||
@@ -25,6 +25,36 @@ namespace VAR.ExpressionEvaluator
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IExpressionNode ParseBooleanOp()
|
||||||
|
{
|
||||||
|
if (_tokenizer.Token == Token.Not)
|
||||||
|
{
|
||||||
|
_tokenizer.NextToken();
|
||||||
|
var node = ParseBooleanOp();
|
||||||
|
return new ExpressionBooleanNotNode(node);
|
||||||
|
}
|
||||||
|
IExpressionNode leftNode = ParseRelations();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (_tokenizer.Token == Token.And)
|
||||||
|
{
|
||||||
|
_tokenizer.NextToken();
|
||||||
|
IExpressionNode rightNode = ParseRelations();
|
||||||
|
leftNode = new ExpressionBooleanAndNode(leftNode, rightNode);
|
||||||
|
}
|
||||||
|
if (_tokenizer.Token == Token.Or)
|
||||||
|
{
|
||||||
|
_tokenizer.NextToken();
|
||||||
|
IExpressionNode rightNode = ParseRelations();
|
||||||
|
leftNode = new ExpressionBooleanOrNode(leftNode, rightNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return leftNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IExpressionNode ParseRelations()
|
private IExpressionNode ParseRelations()
|
||||||
{
|
{
|
||||||
IExpressionNode leftNode = ParsePlusAndMinus();
|
IExpressionNode leftNode = ParsePlusAndMinus();
|
||||||
@@ -99,20 +129,20 @@ namespace VAR.ExpressionEvaluator
|
|||||||
|
|
||||||
private IExpressionNode ParseMultiplyDivision()
|
private IExpressionNode ParseMultiplyDivision()
|
||||||
{
|
{
|
||||||
IExpressionNode lhs = ParseUnary();
|
IExpressionNode lhs = ParseNumericSign();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (_tokenizer.Token == Token.Multiply)
|
if (_tokenizer.Token == Token.Multiply)
|
||||||
{
|
{
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
IExpressionNode rhs = ParseUnary();
|
IExpressionNode rhs = ParseNumericSign();
|
||||||
lhs = new ExpressionMultiplyNode(lhs, rhs);
|
lhs = new ExpressionMultiplyNode(lhs, rhs);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (_tokenizer.Token == Token.Division)
|
else if (_tokenizer.Token == Token.Division)
|
||||||
{
|
{
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
IExpressionNode rhs = ParseUnary();
|
IExpressionNode rhs = ParseNumericSign();
|
||||||
lhs = new ExpressionDivisionNode(lhs, rhs);
|
lhs = new ExpressionDivisionNode(lhs, rhs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -122,17 +152,17 @@ namespace VAR.ExpressionEvaluator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IExpressionNode ParseUnary()
|
private IExpressionNode ParseNumericSign()
|
||||||
{
|
{
|
||||||
if (_tokenizer.Token == Token.Plus)
|
if (_tokenizer.Token == Token.Plus)
|
||||||
{
|
{
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
return ParseUnary();
|
return ParseNumericSign();
|
||||||
}
|
}
|
||||||
if (_tokenizer.Token == Token.Minus)
|
if (_tokenizer.Token == Token.Minus)
|
||||||
{
|
{
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
var node = ParseUnary();
|
var node = ParseNumericSign();
|
||||||
return new ExpressionNumberNegateNode(node);
|
return new ExpressionNumberNegateNode(node);
|
||||||
}
|
}
|
||||||
return ParseTerminus();
|
return ParseTerminus();
|
||||||
@@ -203,7 +233,7 @@ namespace VAR.ExpressionEvaluator
|
|||||||
if (_tokenizer.Token == Token.ParenthesisStart)
|
if (_tokenizer.Token == Token.ParenthesisStart)
|
||||||
{
|
{
|
||||||
_tokenizer.NextToken();
|
_tokenizer.NextToken();
|
||||||
IExpressionNode node = ParseRelations();
|
IExpressionNode node = ParseBooleanOp();
|
||||||
if (_tokenizer.Token != Token.ParenthesisEnd)
|
if (_tokenizer.Token != Token.ParenthesisEnd)
|
||||||
{
|
{
|
||||||
throw new Exception("Missing close parenthesis");
|
throw new Exception("Missing close parenthesis");
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
GreaterOrEqualThan,
|
GreaterOrEqualThan,
|
||||||
LessThan,
|
LessThan,
|
||||||
LessOrEqualThan,
|
LessOrEqualThan,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
Comma,
|
Comma,
|
||||||
Identifier,
|
Identifier,
|
||||||
String,
|
String,
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ namespace VAR.ExpressionEvaluator
|
|||||||
_currentToken = Token.NotEquals;
|
_currentToken = Token.NotEquals;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
NextChar();
|
NextChar();
|
||||||
_currentToken = Token.Equals;
|
_currentToken = Token.Equals;
|
||||||
@@ -124,6 +125,7 @@ namespace VAR.ExpressionEvaluator
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
NextChar();
|
NextChar();
|
||||||
_currentToken = Token.GreaterThan;
|
_currentToken = Token.GreaterThan;
|
||||||
@@ -144,6 +146,24 @@ namespace VAR.ExpressionEvaluator
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
NextChar();
|
||||||
|
_currentToken = Token.And;
|
||||||
|
while (_currentChar == '&')
|
||||||
|
{
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
NextChar();
|
||||||
|
_currentToken = Token.Or;
|
||||||
|
while (_currentChar == '|')
|
||||||
|
{
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
case ',':
|
case ',':
|
||||||
NextChar();
|
NextChar();
|
||||||
_currentToken = Token.Comma;
|
_currentToken = Token.Comma;
|
||||||
@@ -161,7 +181,23 @@ namespace VAR.ExpressionEvaluator
|
|||||||
if (_currentChar == '\0') { break; }
|
if (_currentChar == '\0') { break; }
|
||||||
}
|
}
|
||||||
_text = sb.ToString();
|
_text = sb.ToString();
|
||||||
_currentToken = Token.Identifier;
|
string textLowercase = _text.ToLower();
|
||||||
|
if (textLowercase == "and")
|
||||||
|
{
|
||||||
|
_currentToken = Token.And;
|
||||||
|
}
|
||||||
|
else if (textLowercase == "or")
|
||||||
|
{
|
||||||
|
_currentToken = Token.Or;
|
||||||
|
}
|
||||||
|
else if (textLowercase == "not")
|
||||||
|
{
|
||||||
|
_currentToken = Token.Not;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_currentToken = Token.Identifier;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="EvaluationContext.cs" />
|
<Compile Include="EvaluationContext.cs" />
|
||||||
|
<Compile Include="ExpressionNodes\ExpressionBooleanAndNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionBooleanNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionBooleanNode.cs" />
|
||||||
|
<Compile Include="ExpressionNodes\ExpressionBooleanNotNode.cs" />
|
||||||
|
<Compile Include="ExpressionNodes\ExpressionBooleanOrNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionDivisionNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionDivisionNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionEqualsNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionEqualsNode.cs" />
|
||||||
<Compile Include="ExpressionNodes\ExpressionFunctionNode.cs" />
|
<Compile Include="ExpressionNodes\ExpressionFunctionNode.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user