Parser: Parse number negation.

This commit is contained in:
2019-12-01 13:59:46 +01:00
parent e02a267949
commit 49941a7861
5 changed files with 101 additions and 3 deletions

View File

@@ -36,5 +36,46 @@ namespace VAR.ExpressionEvaluator.Tests
object result = Parser.EvaluateString(expression); object result = Parser.EvaluateString(expression);
Assert.AreEqual(900000m, result); Assert.AreEqual(900000m, result);
} }
[TestMethod()]
public void ParseString__MinusTen()
{
string expression = "-10";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(-10m, result);
}
[TestMethod()]
public void ParseString__PlusTen()
{
string expression = "+10";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(10m, result);
}
[TestMethod()]
public void ParseString__MinusMinusTen()
{
string expression = "--10";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(10m, result);
}
[TestMethod()]
public void ParseString__MinusPlusChainTen()
{
string expression = "--++-+-10";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(10m, result);
}
[TestMethod()]
public void ParseString__10Minus20Minus30()
{
string expression = "10 + -20 - +30";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(-40m, result);
}
} }
} }

View File

@@ -0,0 +1,15 @@
namespace VAR.ExpressionEvaluator
{
public class ExpressionNumberNegateNode : ExpressionUnaryNode
{
public ExpressionNumberNegateNode(IExpressionNode node) :
base(node, NumberNegateOp)
{
}
private static object NumberNegateOp(object value)
{
return - (decimal)value;
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
namespace VAR.ExpressionEvaluator
{
public class ExpressionUnaryNode : IExpressionNode
{
private IExpressionNode _node;
private readonly Func<object, object> _operation;
public ExpressionUnaryNode(IExpressionNode node, Func<object, object> operation)
{
_node = node;
_operation = operation;
}
public object Eval()
{
object value = _node.Eval();
object result = _operation(value);
return result;
}
}
}

View File

@@ -26,19 +26,19 @@ namespace VAR.ExpressionEvaluator
public IExpressionNode ParsePlusAndMinus() public IExpressionNode ParsePlusAndMinus()
{ {
IExpressionNode leftNode = ParseTerminus(); IExpressionNode leftNode = ParseUnary();
while (true) while (true)
{ {
if (_tokenizer.Token == Token.Plus) if (_tokenizer.Token == Token.Plus)
{ {
_tokenizer.NextToken(); _tokenizer.NextToken();
IExpressionNode rightNode = ParseTerminus(); IExpressionNode rightNode = ParseUnary();
leftNode = new ExpressionPlusNode(leftNode, rightNode); leftNode = new ExpressionPlusNode(leftNode, rightNode);
} }
else if (_tokenizer.Token == Token.Minus) else if (_tokenizer.Token == Token.Minus)
{ {
_tokenizer.NextToken(); _tokenizer.NextToken();
IExpressionNode rightNode = ParseTerminus(); IExpressionNode rightNode = ParseUnary();
leftNode = new ExpressionMinusNode(leftNode, rightNode); leftNode = new ExpressionMinusNode(leftNode, rightNode);
} }
else else
@@ -48,6 +48,22 @@ namespace VAR.ExpressionEvaluator
} }
} }
private IExpressionNode ParseUnary()
{
if (_tokenizer.Token == Token.Plus)
{
_tokenizer.NextToken();
return ParseUnary();
}
if (_tokenizer.Token == Token.Minus)
{
_tokenizer.NextToken();
var node = ParseUnary();
return new ExpressionNumberNegateNode(node);
}
return ParseTerminus();
}
private IExpressionNode ParseTerminus() private IExpressionNode ParseTerminus()
{ {
if (_tokenizer.Token == Token.Number) if (_tokenizer.Token == Token.Number)

View File

@@ -41,8 +41,10 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ExpressionUnaryNode.cs" />
<Compile Include="ExpressionBinaryNode.cs" /> <Compile Include="ExpressionBinaryNode.cs" />
<Compile Include="ExpressionMinusNode.cs" /> <Compile Include="ExpressionMinusNode.cs" />
<Compile Include="ExpressionNumberNegateNode.cs" />
<Compile Include="ExpressionPlusNode.cs" /> <Compile Include="ExpressionPlusNode.cs" />
<Compile Include="ExpressionStringNode.cs" /> <Compile Include="ExpressionStringNode.cs" />
<Compile Include="ExpressionNumberNode.cs" /> <Compile Include="ExpressionNumberNode.cs" />