diff --git a/VAR.ExpressionEvaluator.Tests/ParserTests.cs b/VAR.ExpressionEvaluator.Tests/ParserTests.cs index 2f49d42..eaa747f 100644 --- a/VAR.ExpressionEvaluator.Tests/ParserTests.cs +++ b/VAR.ExpressionEvaluator.Tests/ParserTests.cs @@ -5,6 +5,8 @@ namespace VAR.ExpressionEvaluator.Tests [TestClass()] public class ParserTests { + #region Plus and Minus + [TestMethod()] public void ParseString__Ten_EqualsTen() { @@ -37,6 +39,10 @@ namespace VAR.ExpressionEvaluator.Tests Assert.AreEqual(900000m, result); } + #endregion Plus and minus + + #region Number signs + [TestMethod()] public void ParseString__MinusTen() { @@ -77,5 +83,67 @@ namespace VAR.ExpressionEvaluator.Tests Assert.AreEqual(-40m, result); } + #endregion Number signs + + #region Multiplication and division + + [TestMethod()] + public void ParseString__10MutiplyBy2() + { + string expression = "10 * 2"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(20m, result); + } + + [TestMethod()] + public void ParseString__10DividedBy2() + { + string expression = "10 / 2"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(5m, result); + } + + [TestMethod()] + public void ParseString__5DividedBy2() + { + string expression = "5 / 2"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(2.5m, result); + } + + [TestMethod()] + public void ParseString__5DividedBy2Plus1() + { + string expression = "5 / 2 + 1"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(3.5m, result); + } + + [TestMethod()] + public void ParseString__1Plus5DividedBy2() + { + string expression = "1 + 5 / 2"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(3.5m, result); + } + + [TestMethod()] + public void ParseString__5DividedByParen1Plus1() + { + string expression = "5 / (1 + 1)"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(2.5m, result); + } + + [TestMethod()] + public void ParseString__Paren2Plus2DividedByParen1Plus1() + { + string expression = "(2 + 2) / (1 + 1)"; + object result = Parser.EvaluateString(expression); + Assert.AreEqual(2m, result); + } + + #endregion Multiplication and division + } } \ No newline at end of file diff --git a/VAR.ExpressionEvaluator.Tests/TokenizerTests.cs b/VAR.ExpressionEvaluator.Tests/TokenizerTests.cs index fc6205b..24224c3 100644 --- a/VAR.ExpressionEvaluator.Tests/TokenizerTests.cs +++ b/VAR.ExpressionEvaluator.Tests/TokenizerTests.cs @@ -120,7 +120,7 @@ namespace VAR.ExpressionEvaluator.Tests var t = new Tokenizer(new StringReader(testString)); // "(" - Assert.AreEqual(t.Token, Token.ParentesisStart); + Assert.AreEqual(t.Token, Token.ParenthesisStart); t.NextToken(); // "10" @@ -138,7 +138,7 @@ namespace VAR.ExpressionEvaluator.Tests t.NextToken(); // ")" - Assert.AreEqual(t.Token, Token.ParentesisEnd); + Assert.AreEqual(t.Token, Token.ParenthesisEnd); t.NextToken(); // "*" diff --git a/VAR.ExpressionEvaluator/ExpressionDivisionNode.cs b/VAR.ExpressionEvaluator/ExpressionDivisionNode.cs new file mode 100644 index 0000000..babf853 --- /dev/null +++ b/VAR.ExpressionEvaluator/ExpressionDivisionNode.cs @@ -0,0 +1,15 @@ +namespace VAR.ExpressionEvaluator +{ + public class ExpressionDivisionNode : ExpressionBinaryNode + { + public ExpressionDivisionNode(IExpressionNode leftNode, IExpressionNode rightNode) : + base(leftNode, rightNode, DivisionOp) + { + } + + private static object DivisionOp(object leftValue, object rightValue) + { + return (decimal)leftValue / (decimal)rightValue; + } + } +} diff --git a/VAR.ExpressionEvaluator/ExpressionMultiplyNode.cs b/VAR.ExpressionEvaluator/ExpressionMultiplyNode.cs new file mode 100644 index 0000000..fed99db --- /dev/null +++ b/VAR.ExpressionEvaluator/ExpressionMultiplyNode.cs @@ -0,0 +1,15 @@ +namespace VAR.ExpressionEvaluator +{ + public class ExpressionMultiplyNode : ExpressionBinaryNode + { + public ExpressionMultiplyNode(IExpressionNode leftNode, IExpressionNode rightNode) : + base(leftNode, rightNode, MultiplyOp) + { + } + + private static object MultiplyOp(object leftValue, object rightValue) + { + return (decimal)leftValue * (decimal)rightValue; + } + } +} diff --git a/VAR.ExpressionEvaluator/Parser.cs b/VAR.ExpressionEvaluator/Parser.cs index e1088db..dbf6f4b 100644 --- a/VAR.ExpressionEvaluator/Parser.cs +++ b/VAR.ExpressionEvaluator/Parser.cs @@ -26,19 +26,19 @@ namespace VAR.ExpressionEvaluator public IExpressionNode ParsePlusAndMinus() { - IExpressionNode leftNode = ParseUnary(); + IExpressionNode leftNode = ParseMultiplyDivision(); while (true) { if (_tokenizer.Token == Token.Plus) { _tokenizer.NextToken(); - IExpressionNode rightNode = ParseUnary(); + IExpressionNode rightNode = ParseMultiplyDivision(); leftNode = new ExpressionPlusNode(leftNode, rightNode); } else if (_tokenizer.Token == Token.Minus) { _tokenizer.NextToken(); - IExpressionNode rightNode = ParseUnary(); + IExpressionNode rightNode = ParseMultiplyDivision(); leftNode = new ExpressionMinusNode(leftNode, rightNode); } else @@ -48,6 +48,31 @@ namespace VAR.ExpressionEvaluator } } + private IExpressionNode ParseMultiplyDivision() + { + IExpressionNode lhs = ParseUnary(); + while (true) + { + if (_tokenizer.Token == Token.Multiply) + { + _tokenizer.NextToken(); + IExpressionNode rhs = ParseUnary(); + lhs = new ExpressionMultiplyNode(lhs, rhs); + + } + else if (_tokenizer.Token == Token.Division) + { + _tokenizer.NextToken(); + IExpressionNode rhs = ParseUnary(); + lhs = new ExpressionDivisionNode(lhs, rhs); + } + else + { + return lhs; + } + } + } + private IExpressionNode ParseUnary() { if (_tokenizer.Token == Token.Plus) @@ -73,6 +98,18 @@ namespace VAR.ExpressionEvaluator return node; } + if (_tokenizer.Token == Token.ParenthesisStart) + { + _tokenizer.NextToken(); + var node = ParsePlusAndMinus(); + if (_tokenizer.Token != Token.ParenthesisEnd) + { + throw new Exception("Missing close parenthesis"); + } + _tokenizer.NextToken(); + return node; + } + throw new Exception(string.Format("Unexpected token: {0}", _tokenizer.Token.ToString())); } diff --git a/VAR.ExpressionEvaluator/Token.cs b/VAR.ExpressionEvaluator/Token.cs index abc5f1b..0f58508 100644 --- a/VAR.ExpressionEvaluator/Token.cs +++ b/VAR.ExpressionEvaluator/Token.cs @@ -13,8 +13,8 @@ GreaterOrEqualThan, LessThan, LessOrEqualThan, - ParentesisStart, - ParentesisEnd, + ParenthesisStart, + ParenthesisEnd, Keyword, String, Number, diff --git a/VAR.ExpressionEvaluator/Tokenizer.cs b/VAR.ExpressionEvaluator/Tokenizer.cs index 57f9e8b..8f942c3 100644 --- a/VAR.ExpressionEvaluator/Tokenizer.cs +++ b/VAR.ExpressionEvaluator/Tokenizer.cs @@ -93,12 +93,12 @@ namespace VAR.ExpressionEvaluator case '(': NextChar(); - _currentToken = Token.ParentesisStart; + _currentToken = Token.ParenthesisStart; return; case ')': NextChar(); - _currentToken = Token.ParentesisEnd; + _currentToken = Token.ParenthesisEnd; return; case '=': diff --git a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj index 02cb27b..95f1893 100644 --- a/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj +++ b/VAR.ExpressionEvaluator/VAR.ExpressionEvaluator.csproj @@ -41,6 +41,8 @@ + +