/// <summary>
        /// Parses and extracts a numeric value at the current position.
        /// </summary>
        /// <param name="parser">Current parsing helper object.</param>
        /// <returns>The extracted number token string.</returns>
        private Variable ParseNumber(ParsingHelper parser)
        {
            Debug.Assert(IsNumberChar(parser.Peek()));

            bool hasDecimal = false;
            int  start      = parser.Index;

            while (char.IsDigit(parser.Peek()) || parser.Peek() == '.')
            {
                if (parser.Peek() == '.')
                {
                    if (hasDecimal)
                    {
                        throw new ExpressionException(ErrMultipleDecimalPoints, parser.Index);
                    }
                    hasDecimal = true;
                }
                parser++;
            }
            // Extract token
            string token = parser.Extract(start, parser.Index);

            if (token == ".")
            {
                throw new ExpressionException(ErrInvalidOperand, parser.Index - 1);
            }

            if (hasDecimal)
            {
                return(new Variable(double.Parse(token)));
            }
            return(new Variable(int.Parse(token)));
        }
 /// <summary>
 /// Extracts and evaluates a function parameter and returns its value. If an
 /// exception occurs, it is caught and the column is adjusted to reflect the
 /// position in original string, and the exception is rethrown.
 /// </summary>
 /// <param name="parser">ParsingHelper object.</param>
 /// <param name="start">Index where current parameter starts.</param>
 /// <returns>The parameter value.</returns>
 private Variable ParseParameter(ParsingHelper parser, int start)
 {
     try
     {
         // Recursively evaluate expression
         string expression = parser.Extract(start, parser.Index);
         return(Evaluate(expression));
     }
     catch (ExpressionException ex)
     {
         // Adjust column and rethrow exception
         ex.Index += start;
         throw ex;
     }
 }