static int ScanHexBin <T>(int i,
                                      IParserSupport <T> p, int maxDigits,
                                      HexBinParser <T> parser)
            {
                string expr = p.Expression;

                T   value = default(T);
                int begin = i;

                for (; i < expr.Length; i++)
                {
                    if (!parser(expr[i], ref value))
                    {
                        break;
                    }
                }

                int len = i - begin;

                if (len == 0)
                {
                    p.ParsedValue = value;
                    return(1);
                }

                if (len > maxDigits)
                {
                    throw p.InvalidNumberFormat(
                              Resource.errNumberOverflow,
                              Substring(i, p), null);
                }

                p.ParsedValue = value;
                return(len + 2);
            }
            public int TryParse(int i, IParserSupport <long> p)
            {
                string expr = p.Expression;

                if (expr[i] < '0' || expr[i] > '9')
                {
                    return(-1);
                }

                return(Parse(i, p, Int64.Parse, ScanInt64Hex, ScanInt64Bin));
            }
            public int TryParse(int i, IParserSupport <decimal> p)
            {
                string expr = p.Expression;

                if ((expr[i] < '0' || expr[i] > '9') &&
                    expr[i] != p.DecimalDot)
                {
                    return(-1);
                }

                return(Parse(i, p, Decimal.Parse));
            }
 static int ScanInt64Bin(int i, IParserSupport <long> p)
 {
     return(ScanHexBin(i, p, 64,
                       (char c, ref long x) =>
     {
         if (c == '0')
         {
             x <<= 1; return true;
         }
         if (c == '1')
         {
             x <<= 1; x |= 1; return true;
         }
         return false;
     }));
 }
            static int ScanInt64Hex(int i, IParserSupport <long> p)
            {
                return(ScanHexBin(i, p, 16,
                                  (char c, ref long x) =>
                {
                    int digit = HexDigit(c);
                    if (digit < 0)
                    {
                        return false;
                    }

                    x *= 0x10;
                    x += digit;
                    return true;
                }));
            }
 static int ScanInt32Bin(int i, IParserSupport <int> p)
 {
     return(ScanHexBin(i, p, 32,
                       (char c, ref int x) =>
     {
         if (c == '0')
         {
             x <<= 1; return true;
         }
         if (c == '1')
         {
             x <<= 1; x |= 1; return true;
         }
         return false;
     }));
 }
            static int ScanInt32Hex(int i, IParserSupport <int> p)
            {
                return(ScanHexBin(i, p, 8,
                                  (char c, ref int x) =>
                {
                    int digit = HexDigit(c);
                    if (digit < 0)
                    {
                        return false;
                    }

                    x *= 0x10;
                    x += digit;
                    return true;
                }));
            }
            static int Parse <T>(int i, IParserSupport <T> p, Parser <T> parser)
            {
                var str = ScanNumber(i, p);

                if (str == null)
                {
                    return(-1);
                }

                bool neg = p.DiscardNegate();

                try
                {
                    if (neg)
                    {
                        p.ParsedValue = parser(
                            p.NumberFormat.NegativeSign + str,
                            NumberStyles.AllowLeadingSign |
                            NumberStyles.AllowDecimalPoint |
                            NumberStyles.AllowExponent,
                            p.NumberFormat);
                    }
                    else
                    {
                        p.ParsedValue = parser(str,
                                               NumberStyles.AllowDecimalPoint |
                                               NumberStyles.AllowExponent,
                                               p.NumberFormat);
                    }

                    return(str.Length);
                }
                catch (FormatException e)
                {
                    throw p.InvalidNumberFormat(
                              Resource.errNumberFormat, str, e);
                }
                catch (OverflowException e)
                {
                    throw p.InvalidNumberFormat(
                              Resource.errNumberOverflow, str, e);
                }
            }
 static string Substring <T>(int i, IParserSupport <T> p)
 {
     return(p.Expression.Substring(
                p.BeginPos, i - p.BeginPos));
 }
 public int TryParse(int i, IParserSupport <T> p)
 {
     return(-1);
 }
            static int Parse <T>(
                int i, IParserSupport <T> p, Parser <T> parser,
                HexBinScan <T> hex, HexBinScan <T> bin)
            {
                string expr = p.Expression;

                if (expr[i] < '0' || expr[i] > '9')
                {
                    return(-1);
                }

                // hex/bin literal support:
                if (expr[i] == '0' && i + 1 < expr.Length)
                {
                    i++;
                    char c = expr[i++];
                    if (c == 'x' || c == 'X')
                    {
                        return(hex(i, p));
                    }
                    if (c == 'b' || c == 'B')
                    {
                        return(bin(i, p));
                    }

                    p.ParsedValue = default(T);
                    return(1);
                }

                // skip digits and parse:
                while (IsDigit(expr, i))
                {
                    i++;
                }

                string str = Substring(i, p);
                bool   neg = p.DiscardNegate();

                try
                {
                    if (neg)
                    {
                        p.ParsedValue = parser(
                            p.NumberFormat.NegativeSign + str,
                            NumberStyles.AllowLeadingSign |
                            NumberStyles.AllowDecimalPoint |
                            NumberStyles.AllowExponent,
                            p.NumberFormat);
                    }
                    else
                    {
                        p.ParsedValue = parser(str,
                                               NumberStyles.AllowDecimalPoint |
                                               NumberStyles.AllowExponent,
                                               p.NumberFormat);
                    }

                    return(str.Length);
                }
                catch (FormatException e)
                {
                    throw p.InvalidNumberFormat(
                              Resource.errNumberFormat, str, e);
                }
                catch (OverflowException e)
                {
                    throw p.InvalidNumberFormat(
                              Resource.errNumberOverflow, str, e);
                }
            }
            static string ScanNumber <T>(int i, IParserSupport <T> p)
            {
                string expr = p.Expression;

                // Fractal part: ==========================

                // numbers not like ".123":
                if (expr[i] != p.DecimalDot)
                {
                    // skip digits and decimal point:
                    for (; i < expr.Length; i++)
                    {
                        if (expr[i] >= '0' && expr[i] <= '9')
                        {
                            continue;
                        }
                        if (expr[i] == p.DecimalDot)
                        {
                            i++;
                        }
                        break;
                    }
                }
                else
                {
                    if (!IsDigit(expr, ++i))
                    {
                        return(null);
                    }
                }

                // skip digits:
                while (IsDigit(expr, i))
                {
                    i++;
                }

                // Exponental part: =======================

                // at least 2 chars:
                if (i + 1 < expr.Length)
                {
                    // E character:
                    char c = expr[i];
                    if (c == 'e' || c == 'E')
                    {
                        int j = i;

                        // exponetal sign:
                        c = expr[++j];
                        if (c == '-' || c == '+')
                        {
                            j++;
                        }

                        // exponental value:
                        if (IsDigit(expr, j++))
                        {
                            while (IsDigit(expr, j))
                            {
                                j++;
                            }
                            i = j;
                        }
                    }
                }

                return(expr.Substring(p.BeginPos, i - p.BeginPos));
            }