Example #1
0
        public OperandOperation(OperationBase value)
        {
            try
            {
                Type   = OperandType.Operation;
                _Value = value;
            }
            catch (Exception ex)
            {
                Log.Write(ex, MethodBase.GetCurrentMethod(), EventLogEntryType.Error);

                throw;
            }
        }
        /// <summary>
        /// Parse the string token to get an operand of type Literal, Reference, or Operation.
        /// 1) Literal operands return  the value that they contain.
        /// 2) Reference operands use their own category item criteria
        ///  to narrow down the list of cells to which the formula applies. Then the specific cell's criteria
        ///  is used to identify categories not in the criteria, and use those to narrow down to a single source cell.
        /// 3) Operation operands perform their operation and trigger the evaulation of their child operands.
        /// </summary>
        /// <param name="token"></param>
        /// <param name="operand"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        private Boolean ParseToken(String token, ref OperandBase operand, ref String errorMessage)
        {
            Boolean returnValue = default(Boolean);

            String[]      tokens          = default(String[]);
            String        leftToken       = default(String);
            String        rightToken      = default(String);
            Boolean       isFoundOperator = default(Boolean);
            OperatorBase  foundOperator   = default(OperatorBase);
            OperandBase   leftOperand     = default(OperandBase);
            OperandBase   rightOperand    = default(OperandBase);
            OperationBase operation       = default(OperationBase);

            try
            {
                //look for operators, if any, in reverse precedence order
                foreach (OperatorBase op in arithmeticOperators)
                {
                    if (token.Contains(op.Name))
                    {
                        isFoundOperator = true;
                        foundOperator   = op;

                        break;
                    }
                }

                //create an array of one or two sub-tokens
                if (isFoundOperator)
                {
                    //split into 2 parts only
                    tokens = token.Split(new Char[] { foundOperator.Name[0] }, 2);
                }
                else
                {
                    //create list with single item
                    String[] newList = { token };
                    tokens = newList;
                }

                //process sub-tokens
                if (tokens.Length == 0)
                {
                    throw new ArgumentException(String.Format("Incorrectly formatted formula; there does not appear to be an operand: '{0}'", token));
                }
                else if (tokens.Length == 1)
                {
                    //no operator; process single operand
                    leftToken = tokens[0].Trim();
                    if (!ParseOperand(leftToken, ref leftOperand, ref errorMessage))
                    {
                        throw new ApplicationException(errorMessage);
                    }
                    operand = leftOperand;

                    returnValue = true;
                }
                else if (tokens.Length == 2)
                {
                    //operator found; process dual operands with recursive call
                    leftToken = tokens[0].Trim();
                    if (!ParseToken(leftToken, ref leftOperand, ref errorMessage))
                    {
                        throw new ApplicationException(errorMessage);
                    }

                    rightToken = tokens[1].Trim();
                    if (!ParseToken(rightToken, ref rightOperand, ref errorMessage))
                    {
                        throw new ApplicationException(errorMessage);
                    }

                    //create operation from left/right operands and operator, and create OperandOperation
                    //create OperationBinary which configures 2 OperandBase dictionary entries called Left, Right.
                    operation = new OperationBinary();
                    operation.Operands["Left"]  = leftOperand;
                    operation.Operands["Right"] = rightOperand;
                    operation.Operator          = foundOperator;

                    operand = new OperandOperation(operation);

                    returnValue = true;
                }
                else if (tokens.Length > 2)
                {
                    throw new ArgumentException(String.Format("Unexpected formula format: '{0}'", token));
                }
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message;
                Log.Write(ex, MethodBase.GetCurrentMethod(), EventLogEntryType.Error);
                //throw;
            }
            return(returnValue);
        }