From e02a2679491f70370047f14822c8036818cc02e6 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R" Date: Sun, 1 Dec 2019 03:12:20 +0100 Subject: [PATCH] Parser: Plus and Minus with numbers. --- VAR.ExpressionEvaluator.Tests/ParserTests.cs | 40 ++++++++++ .../VAR.ExpressionEvaluator.Tests.csproj | 1 + .../ExpressionMinusNode.cs | 15 ++++ VAR.ExpressionEvaluator/ExpressionPlusNode.cs | 15 ++++ VAR.ExpressionEvaluator/Parser.cs | 77 +++++++++++++++++++ .../VAR.ExpressionEvaluator.csproj | 3 + 6 files changed, 151 insertions(+) create mode 100644 VAR.ExpressionEvaluator.Tests/ParserTests.cs create mode 100644 VAR.ExpressionEvaluator/ExpressionMinusNode.cs create mode 100644 VAR.ExpressionEvaluator/ExpressionPlusNode.cs create mode 100644 VAR.ExpressionEvaluator/Parser.cs diff --git a/VAR.ExpressionEvaluator.Tests/ParserTests.cs b/VAR.ExpressionEvaluator.Tests/ParserTests.cs new file mode 100644 index 0000000..e2b348b --- /dev/null +++ b/VAR.ExpressionEvaluator.Tests/ParserTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/VAR.ExpressionEvaluator.Tests/VAR.ExpressionEvaluator.Tests.csproj b/VAR.ExpressionEvaluator.Tests/VAR.ExpressionEvaluator.Tests.csproj index b0f1dfe..0c66a37 100644 --- a/VAR.ExpressionEvaluator.Tests/VAR.ExpressionEvaluator.Tests.csproj +++ b/VAR.ExpressionEvaluator.Tests/VAR.ExpressionEvaluator.Tests.csproj @@ -54,6 +54,7 @@ + diff --git a/VAR.ExpressionEvaluator/ExpressionMinusNode.cs b/VAR.ExpressionEvaluator/ExpressionMinusNode.cs new file mode 100644 index 0000000..30e0c81 --- /dev/null +++ b/VAR.ExpressionEvaluator/ExpressionMinusNode.cs @@ -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; + } + } +} diff --git a/VAR.ExpressionEvaluator/ExpressionPlusNode.cs b/VAR.ExpressionEvaluator/ExpressionPlusNode.cs new file mode 100644 index 0000000..9adb6c3 --- /dev/null +++ b/VAR.ExpressionEvaluator/ExpressionPlusNode.cs @@ -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; + } + } +} diff --git a/VAR.ExpressionEvaluator/Parser.cs b/VAR.ExpressionEvaluator/Parser.cs new file mode 100644 index 0000000..922f3fd --- /dev/null +++ b/VAR.ExpressionEvaluator/Parser.cs @@ -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(); + } + } +} diff --git a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj index 6495ec0..cbd95dd 100644 --- a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj +++ b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj @@ -42,10 +42,13 @@ + + +