Parser: Plus and Minus with numbers.

This commit is contained in:
2019-12-01 03:12:20 +01:00
parent bdf675f592
commit e02a267949
6 changed files with 151 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace VAR.ExpressionEvaluator.Tests
{
[TestClass()]
public class ParserTests
{
[TestMethod()]
public void ParseString__Ten_EqualsTen()
{
string expression = "10";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(10m, result);
}
[TestMethod()]
public void ParseString__OnePlusTwo_EqualsThree()
{
string expression = "1 + 2";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(3m, result);
}
[TestMethod()]
public void ParseString__OneMinusTwo_EqualsMinusOne()
{
string expression = "1 - 2";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(-1m, result);
}
[TestMethod()]
public void ParseString__OneMillionMinusHundredThousands_EqualsNineHundredThousands()
{
string expression = "1000000 - 100000";
object result = Parser.EvaluateString(expression);
Assert.AreEqual(900000m, result);
}
}
}

View File

@@ -54,6 +54,7 @@
<Compile Include="ExpressionBinaryNodeTests.cs" /> <Compile Include="ExpressionBinaryNodeTests.cs" />
<Compile Include="ExpressionNumberNodeTests.cs" /> <Compile Include="ExpressionNumberNodeTests.cs" />
<Compile Include="ExpressionStringNodeTests.cs" /> <Compile Include="ExpressionStringNodeTests.cs" />
<Compile Include="ParserTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TokenizerTests.cs" /> <Compile Include="TokenizerTests.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,15 @@
namespace VAR.ExpressionEvaluator
{
public class ExpressionMinusNode : ExpressionBinaryNode
{
public ExpressionMinusNode(IExpressionNode leftNode, IExpressionNode rightNode) :
base(leftNode, rightNode, MinusOp)
{
}
private static object MinusOp(object leftValue, object rightValue)
{
return (decimal)leftValue - (decimal)rightValue;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace VAR.ExpressionEvaluator
{
public class ExpressionPlusNode : ExpressionBinaryNode
{
public ExpressionPlusNode(IExpressionNode leftNode, IExpressionNode rightNode) :
base(leftNode, rightNode, PlusOp)
{
}
private static object PlusOp(object leftValue, object rightValue)
{
return (decimal)leftValue + (decimal)rightValue;
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.IO;
namespace VAR.ExpressionEvaluator
{
public class Parser
{
private ITokenizer _tokenizer;
public Parser(ITokenizer tokenizer)
{
_tokenizer = tokenizer;
}
public IExpressionNode ParseExpression()
{
var expr = ParsePlusAndMinus();
if (_tokenizer.Token != Token.EOF)
{
throw new Exception("Unexpected characters at end of expression");
}
return expr;
}
public IExpressionNode ParsePlusAndMinus()
{
IExpressionNode leftNode = ParseTerminus();
while (true)
{
if (_tokenizer.Token == Token.Plus)
{
_tokenizer.NextToken();
IExpressionNode rightNode = ParseTerminus();
leftNode = new ExpressionPlusNode(leftNode, rightNode);
}
else if (_tokenizer.Token == Token.Minus)
{
_tokenizer.NextToken();
IExpressionNode rightNode = ParseTerminus();
leftNode = new ExpressionMinusNode(leftNode, rightNode);
}
else
{
return leftNode;
}
}
}
private IExpressionNode ParseTerminus()
{
if (_tokenizer.Token == Token.Number)
{
var node = new ExpressionNumberNode(_tokenizer.Number ?? 0m);
_tokenizer.NextToken();
return node;
}
throw new Exception(string.Format("Unexpected token: {0}", _tokenizer.Token.ToString()));
}
public static IExpressionNode ParseString(string str)
{
TextReader textReader = new StringReader(str);
ITokenizer tokenizer = new Tokenizer(textReader);
Parser parser = new Parser(tokenizer);
return parser.ParseExpression();
}
public static object EvaluateString(string str)
{
IExpressionNode node = ParseString(str);
return node.Eval();
}
}
}

View File

@@ -42,10 +42,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ExpressionBinaryNode.cs" /> <Compile Include="ExpressionBinaryNode.cs" />
<Compile Include="ExpressionMinusNode.cs" />
<Compile Include="ExpressionPlusNode.cs" />
<Compile Include="ExpressionStringNode.cs" /> <Compile Include="ExpressionStringNode.cs" />
<Compile Include="ExpressionNumberNode.cs" /> <Compile Include="ExpressionNumberNode.cs" />
<Compile Include="IExpressionNode.cs" /> <Compile Include="IExpressionNode.cs" />
<Compile Include="ITokenizer.cs" /> <Compile Include="ITokenizer.cs" />
<Compile Include="Parser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Token.cs" /> <Compile Include="Token.cs" />
<Compile Include="Tokenizer.cs" /> <Compile Include="Tokenizer.cs" />