예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
    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);
        }
    }
예제 #4
0
        // 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);
            }
        }
예제 #5
0
        // 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);
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
        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());
            }
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
            }
        }