private INode ParseAddSubtract() { var lhs = ParseMultiplyDivide(); while (true) { Func <double, double, double> op = null; if (tokenizer.currentToken == Token.Add) { op = (a, b) => a + b; } else if (tokenizer.currentToken == Token.Subtract) { op = (a, b) => a - b; } if (op == null) { return(lhs); } tokenizer.NextToken(); var rhs = ParseMultiplyDivide(); lhs = new NodeBinary(lhs, rhs, op); } }
private INode ParseMultiplyDivide() { var lhs = ParseExponentiation(); while (true) { Func <double, double, double> op = null; if (tokenizer.currentToken == Token.Multiply) { op = (a, b) => a * b; } else if (tokenizer.currentToken == Token.Divide) { op = (a, b) => Math.Abs(b) > divisionLimit ? a / b : double.NaN; } if (op == null) { return(lhs); } tokenizer.NextToken(); var rhs = ParseExponentiation(); lhs = new NodeBinary(lhs, rhs, op); } }
Node ParseAddSubtract() { // Parse the left hand side var lhs = ParseUnary(); while (true) { // Work out the operator Func <double, double, double> op = null; if (m_tokeniser.getToken == Token.Add) { op = (a, b) => a + b; } else if (m_tokeniser.getToken == Token.Subtract) { op = (a, b) => a - b; } // Binary operator found? if (op == null) { return(lhs); // no } // Skip the operator m_tokeniser.NextToken(); // Parse the right hand side of the expression var rhs = ParseUnary(); // Create a binary node and use it as the left-hand side from now on lhs = new NodeBinary(lhs, rhs, op); } }
// ParseAddSubtract is the least prioritized and thererfore called first. Node ParseAddSubtract() { // The lefthand side of the operation is parsed with the next higher prioritized operation. // Multiplication and division is a priority level above addition and subtraction. var lhs = ParseUnary(); // The while loop below contiues infinitely until no more operations are to be parsed. while (true) { // The operation (add/sub) is determined by the symbol. Func <int, int, int> op = null; if (fCurrentToken.Equals(TokenType.Symbol, "+")) { op = (a, b) => a + b; } else if (fCurrentToken.Equals(TokenType.Symbol, "-")) { op = (a, b) => a - b; } // If there are no further operations the lefthand side is returned. if (op == null) { return(lhs); } // The operator is skipped. ReadNextToken(); // Now the righthand side of the operation is parsed for the operation of the higher priority level. var rhs = ParseUnary(); // The lefthand side value is updated with the computed operation value. lhs = new NodeBinary(lhs, rhs, op); } }
// ParseMultiplyDivide is of the next level of priority. // The general structure of this method is the same as for addition and subtraction, // except the method now calls the next priority level above which are exponents. Node ParseMultiplyDivide() { var lhs = ParseExponent(); while (true) { Func <int, int, int> op = null; if (fCurrentToken.Equals(TokenType.Symbol, "*")) { op = (a, b) => a * b; } else if (fCurrentToken.Equals(TokenType.Symbol, "/")) { op = (a, b) => a / b; } if (op == null) { return(lhs); } ReadNextToken(); // The righthandside is now parsed of any exponents. var rhs = ParseExponent(); lhs = new NodeBinary(lhs, rhs, op); } }
private INode ParsePowAndRootSquare() { var leftOperationNode = ParseMultiplyAndDivide(); while (true) { //_tokenizer.Next(); Func <double, double, double> op = null; if (_tokenizer.Token == Token.Pow) { op = (a, b) => Math.Pow(a, b); } else if (_tokenizer.Token == Token.SquareRoot) { throw new NotImplementedException(); } if (op == null) { return(leftOperationNode); } var rigthOperationNode = ParseMultiplyAndDivide(); leftOperationNode = new NodeBinary(leftOperationNode, rigthOperationNode, op); } }
private INode ParseAddAndSubstract() { var leftOperationNode = ParsePowAndRootSquare(); while (true) { Func <double, double, double> op = null; if (_tokenizer.Token == Token.Add) { op = (a, b) => a + b; } else if (_tokenizer.Token == Token.Subtract) { op = (a, b) => a - b; } if (op == null) { return(leftOperationNode); } var rigthOperationNode = ParsePowAndRootSquare(); leftOperationNode = new NodeBinary(leftOperationNode, rigthOperationNode, op); } }
private INode ParseMultiplyAndDivide() { var leftOperationNode = ParseUnary(); while (true) { _tokenizer.Next(); Func <double, double, double> op = null; if (_tokenizer.Token == Token.Multiply) { op = (a, b) => a * b; } else if (_tokenizer.Token == Token.Divide) { op = (a, b) => a / b; } if (op == null) { return(leftOperationNode); } var rigthOperationNode = ParseUnary(); leftOperationNode = new NodeBinary(leftOperationNode, rigthOperationNode, op); } }
private static NodeBinary RotateRight(NodeBinary nodeBinary) { switch (nodeBinary.Operation) { case Operation.Add: case Operation.Subtract: { if (nodeBinary.Left is NodeBinary leftBinary && leftBinary.Operation == Operation.Add) { nodeBinary.Left = leftBinary.Right; leftBinary.Right = nodeBinary; return(leftBinary); } break; } case Operation.Minus: throw new InvalidOperationException($"Invalid operation {nodeBinary.Operation}"); break; case Operation.Multiply: { if (nodeBinary.Left is NodeBinary leftBinary && leftBinary.Operation == Operation.Multiply) { nodeBinary.Left = leftBinary.Right; leftBinary.Right = nodeBinary; return(leftBinary); } break; } case Operation.Divide: { if (nodeBinary.Left is NodeBinary leftBinary && leftBinary.Operation == Operation.Divide) { nodeBinary.Left = leftBinary.Right; nodeBinary.Operation = Operation.Multiply; leftBinary.Right = nodeBinary; return(leftBinary); } break; } default: throw new ArgumentOutOfRangeException(); } return(nodeBinary); }
public void Test() { var expresion = new NodeBinary( new NodeNumber(50), new NodeNumber(25), (n1, n2) => n1 + n2 ); Assert.AreEqual(75d, expresion.Eval()); foreach (var expr in _expresionsToTest) { var parser = new Parser(expr.Key); Assert.AreEqual(expr.Value, parser.GetExpresionTree().Eval()); } }
public void EvalThroughFunction() { var nodeMockReturns = _fixture.Create <double>(); var nodeMockLeft = new Mock <Node>(); var nodeMockRight = new Mock <Node>(); nodeMockLeft.Setup(_ => _.Eval(It.IsAny <IContext>())).Returns(nodeMockReturns).Verifiable(); nodeMockRight.Setup(_ => _.Eval(It.IsAny <IContext>())).Returns(nodeMockReturns).Verifiable(); var functionMockReturns = _fixture.Create <double>(); var functionMock = new Mock <Func <double, double, double> >(); // настраиваем Mock функции - при вызове функции с аргументом nodeMockReurns, возвращаем functionMockReturns, также помечаем Verifiable. functionMock.Setup(_ => _(nodeMockReturns, nodeMockReturns)).Returns(functionMockReturns).Verifiable(); var sut = new NodeBinary(nodeMockLeft.Object, nodeMockRight.Object, functionMock.Object); var result = sut.Eval(null); // знаем, что IContext игнорируется - порицаем Assert.Equal(functionMockReturns, result); // ждем что результат будет равен, тому что вернет функция. Первым передается ожидаемое значение, вторым проверяемое. Mock.Verify(nodeMockLeft, nodeMockRight, functionMock); }
private INode ParseExponentiation() { var lhs = ParseUnary(); while (true) { Func <double, double, double> op = null; if (tokenizer.currentToken == Token.Exponentiation) { op = (a, b) => Math.Pow(a, b); } if (op == null) { return(lhs); } tokenizer.NextToken(); var rhs = ParseUnary(); lhs = new NodeBinary(lhs, rhs, op); } }