Exemplo n.º 1
0
        public IOperand Parse <T>(string text) where T : IConvertible
        {
            IsTyped = typeof(T) != typeof(IConvertible);
            scanner = Scanner.Create(text);

            Clause = IsTyped ?
                     new Sum <T>() :
                     new Sum();

            // it could have just one operand
            IOperand lastOperand = GetOperand <T>();

            Clause.AddOperand(lastOperand);
            IOperation working     = Clause;
            IOperand   nextOperand = null;

            while (!ParseEnd)
            {
                IOperator op = GetOperation();

                nextOperand = GetOperand <T>();
                IOperation newOp;

                if (op.AssociationType == working.AssociationType)
                {
                    // working can only be sum/product
                    working.AddOperand(nextOperand, op.IsInverted);
                }
                else
                {
                    switch (op.AssociationType)
                    {
                    case AssociationType.Addition:
                        // always return to the root when adding
                        if (!ReferenceEquals(working, Clause))
                        {
                            working = Clause;
                        }
                        working.AddOperand(nextOperand, op.IsInverted);
                        break;

                    case AssociationType.Multiplicaton:
                        //"steal" last operand from Clause, and change working to the new op
                        newOp = op.GetFunction();

                        newOp.AddOperand(lastOperand);
                        newOp.AddOperand(nextOperand, op.IsInverted);
                        Clause.ReplaceLastOperand(newOp);
                        working = newOp;
                        break;

                    case AssociationType.Power:
                        // Similar to Multiplication, but does not change the active chain to the new operation. It can never be added to.
                        newOp = op.GetFunction();

                        newOp.AddOperand(lastOperand);
                        newOp.AddOperand(nextOperand, op.IsInverted);
                        Clause.ReplaceLastOperand(newOp);
                        break;

                    case AssociationType.Function:
                        // Similar to Multiplication, but does not change the active chain to the new operation. It can never be added to.
                        newOp = op.GetFunction();
                        newOp.AddOperand(nextOperand, op.IsInverted);
                        Clause.ReplaceLastOperand(newOp);
                        break;

                    default:
                        throw new NotImplementedException("Unknown association type.");
                    }
                }
                lastOperand = nextOperand;
            }
            Error = "";

            return((IOperand)Clause);
        }