Example #1
0
        private static void ReadType(StringProcessor parser, string @namespace, ProgressiveLookup <string, Type> lookup, bool includeNamespace)
        {
            var typeName = string.Empty;

            while (true)
            {
                typeName += parser.ReadWhile(char.IsLetterOrDigit);
                if (parser.Read("_"))
                {
                    typeName += "_";
                }
                else
                {
                    break;
                }
            }
            var generic = parser.Read("<");

            if (generic)
            {
                var genericArgsCount = parser.ReadUntil(">").CountItemsWhere(chr => chr == ',') + 1;
                parser.Read(">");
                if (includeNamespace)
                {
                    ProcessType($"{@namespace}.{typeName}`{genericArgsCount}", lookup);
                }
            }
            else
            {
                if (includeNamespace)
                {
                    ProcessType($"{@namespace}.{typeName}", lookup);
                }
            }
        }
Example #2
0
        internal static bool ParseNumber(StringProcessor reader, NumberStyles options, BigNumberBuffer number, NumberFormatInfo info)
        {
            if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
            {
                var allowLeadingWhite  = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
                var allowTrailingWhite = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;

                /*
                 * // Assume validated
                 * if (
                 *  (options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None
                 || (options & NumberStyles.AllowLeadingSign) != NumberStyles.None
                 || (options & NumberStyles.AllowParentheses) != NumberStyles.None
                 || (options & NumberStyles.AllowThousands) != NumberStyles.None
                 || (options & NumberStyles.AllowExponent) != NumberStyles.None
                 || (options & NumberStyles.AllowTrailingSign) != NumberStyles.None
                 || )
                 ||{
                 || return false;
                 ||}*/
                number.Negative = false;
                if (allowLeadingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                while (true)
                {
                    var input =
                        reader.ReadWhile
                        (
                            new[]
                    {
                        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C',
                        'D', 'E', 'F'
                    }
                        );
                    if (input.Length == 0)
                    {
                        break;
                    }

                    number.Scale += input.Length;
                    number.Digits.Append(input.ToUpperInvariant());
                }

                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                return(reader.EndOfString);
            }
            else
            {
                var allowCurrencySymbol = (options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None;
                var allowLeadingWhite   = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
                var allowLeadingSign    = (options & NumberStyles.AllowLeadingSign) != NumberStyles.None;
                var allowParentheses    = (options & NumberStyles.AllowParentheses) != NumberStyles.None;
                var allowThousands      = (options & NumberStyles.AllowThousands) != NumberStyles.None;
                var allowExponent       = (options & NumberStyles.AllowExponent) != NumberStyles.None;
                var allowTrailingWhite  = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;
                var allowTrailingSign   = (options & NumberStyles.AllowTrailingSign) != NumberStyles.None;
                var allowDecimalPoint   = (options & NumberStyles.AllowDecimalPoint) != NumberStyles.None;

                var isCurrency = false;
                number.Negative = false;
                var waitingParentheses = false;
                var positive           = false;
                // [ws][$][sign][digits,]digits[E[sign]exponential_digits][ws]
                if (allowLeadingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                // Percent intentionally not supported
                // After testing with .NET the patterns are ignored... all patterns are welcome

                var currencySymbol = info.CurrencySymbol;
                // [$][sign][digits,]digits[E[sign]exponential_digits][ws]
                if (allowCurrencySymbol && reader.Read(currencySymbol))
                {
                    isCurrency = true;
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                var positiveSign = info.PositiveSign;
                var negativeSign = info.NegativeSign;
                // [sign][digits,]digits[E[sign]exponential_digits][ws
                if (allowLeadingSign)
                {
                    number.Negative |= reader.Read(negativeSign);
                    if (!number.Negative)
                    {
                        positive |= reader.Read(positiveSign);
                    }
                }

                if (!number.Negative && allowParentheses && reader.Read('('))
                {
                    // Testing on .NET show that $(n) is allowed, even tho there is no CurrencyNegativePattern for it
                    number.Negative    = true;
                    waitingParentheses = true;
                }

                // ---
                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
                {
                    isCurrency = true;
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                // [digits,]digits[E[sign]exponential_digits][ws]
                var failure      = true;
                var digits       = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                var decimalFound = false;
                while (true)
                {
                    var input = reader.ReadWhile(digits);
                    if (input.Length == 0)
                    {
                        if (allowDecimalPoint && !decimalFound)
                        {
                            if (reader.Read(info.CurrencyDecimalSeparator))
                            {
                                decimalFound = true;
                                continue;
                            }

                            if (reader.Read(info.NumberDecimalSeparator))
                            {
                                if (isCurrency)
                                {
                                    return(false);
                                }

                                decimalFound = true;
                                continue;
                            }
                        }

                        break;
                    }

                    failure = false;
                    if (!decimalFound)
                    {
                        number.Scale += input.Length;
                    }

                    number.Digits.Append(input);
                    if (!allowThousands)
                    {
                        continue;
                    }

                    var currencyGroupSeparator = info.CurrencyGroupSeparator.ToCharArray();
                    // Testing on .NET show that combining currency and number group separators is allowed
                    // But not if the currency symbol has already appeared
                    reader.SkipWhile(currencyGroupSeparator);
                    if (isCurrency)
                    {
                        continue;
                    }

                    var numberGroupSeparator = info.NumberGroupSeparator.ToCharArray();
                    reader.SkipWhile(numberGroupSeparator);
                }

                if (failure)
                {
                    return(false);
                }

                // [E[sign]exponential_digits][ws]
                if (allowExponent && (reader.Read('E') || reader.Read('e')))
                {
                    // [sign]exponential_digits
                    // Testing on .NET show that no pattern is used here, also no parentheses nor group separators supported
                    // The exponent can be big - but anything beyond 9999 is ignored
                    var exponentNegative = reader.Read(negativeSign);
                    if (!exponentNegative)
                    {
                        reader.Read(positiveSign);
                    }

                    var input             = reader.ReadWhile(digits);
                    var exponentMagnitude = int.Parse(input, CultureInfo.InvariantCulture);
                    number.Scale += (exponentNegative ? -1 : 1) * (input.Length > 4 ? 9999 : exponentMagnitude);
                    if (number.Scale < 0)
                    {
                        return(false);
                    }
                }

                // ---
                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol))
                {
                    isCurrency = true;
                }

                // ---
                if (!number.Negative && !positive && allowTrailingSign)
                {
                    number.Negative |= reader.Read(negativeSign);
                    if (!number.Negative)
                    {
                        reader.Read(positiveSign);
                    }
                }

                if (waitingParentheses && !reader.Read(')'))
                {
                    return(false);
                }

                // ---
                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
                {
                    /*isCurrency = true; // For completeness sake*/
                }

                // [ws]
                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }

                return(reader.EndOfString);
            }
        }
Example #3
0
        public static void Test()
        {
            var version           = "2.1";
            var skippedNamespaces = new []
            {
                "System.Xml",
                "System.Data",
                "System.Net",
                "System.IO",
                "System.Drawing",
                "System.Runtime.Serialization",
                "System.Security.Cryptography"
            };
            // ---
            var url      = $"https://raw.githubusercontent.com/dotnet/standard/master/docs/versions/netstandard{version}_ref.md";
            var text     = new WebClient().DownloadString(url);
            var parser   = new StringProcessor(text);
            var keywords = new []
            {
                "class",
                "static class",
                "abstract class",
                "sealed class",
                "struct",
                "enum",
                "interface"
            };
            var entryAssembly        = typeof(ApiListTest).Assembly;
            var entryAssemblyName    = entryAssembly.GetName();
            var assemblyNameComparer = new CustomEqualityComparer <AssemblyName>
                                       (
                (left, right) => left.FullName == right.FullName,
                name => name.FullName.GetHashCode()
                                       );
            var assemblyDictionary = new Dictionary <AssemblyName, Assembly>(assemblyNameComparer)
            {
                { entryAssemblyName, entryAssembly }
            };
            var loadedAssemblies = GraphHelper.ExploreBreadthFirstGraph
                                   (
                entryAssemblyName,
                assemblyName =>
            {
                Assembly assembly = GetAssembly(assemblyName, assemblyDictionary);
                return(assembly.GetReferencedAssemblies());
            },
                assemblyNameComparer
                                   );
            var types = loadedAssemblies.SelectMany
                        (
                assemblyName => GetAssembly(assemblyName, assemblyDictionary).GetTypes()
                        );
            var lookup = new ProgressiveLookup <string, Type>(types.GroupProgressiveBy(type => type.FullName));

            parser.SkipUntilAfter("```C#");
            while (!parser.EndOfString)
            {
                parser.SkipWhile(CharHelper.IsClassicWhitespace);
                if (parser.Read("namespace"))
                {
                    parser.SkipWhile(CharHelper.IsClassicWhitespace);
                    var @namespace       = parser.ReadUntil(CharHelper.IsClassicWhitespace);
                    var includeNamespace = true;
                    foreach (var skippedNamespace in skippedNamespaces)
                    {
                        if (@namespace.StartsWith(skippedNamespace))
                        {
                            includeNamespace = false;
                            break;
                        }
                    }
                    parser.SkipWhile(CharHelper.IsClassicWhitespace);
                    parser.Read("{");
                    parser.SkipWhile(CharHelper.IsClassicWhitespace);
                    while (true)
                    {
                        if (parser.Read("public"))
                        {
                            parser.SkipWhile(CharHelper.IsClassicWhitespace);
                            if (parser.Read("delegate"))
                            {
                                parser.SkipWhile(CharHelper.IsClassicWhitespace);
                                parser.SkipUntil(CharHelper.IsClassicWhitespace);
                                parser.SkipWhile(CharHelper.IsClassicWhitespace);
                                ReadType(parser, @namespace, lookup, includeNamespace);
                                parser.ReadUntil(new[] { '\n', '\r', '{' });
                                if (parser.Peek('\n') || parser.Peek('\r'))
                                {
                                    continue;
                                }
                            }
                            else if (parser.Read(keywords) != null)
                            {
                                parser.SkipWhile(CharHelper.IsClassicWhitespace);
                                ReadType(parser, @namespace, lookup, includeNamespace);
                            }
                            var count = 0;
                            do
                            {
                                if (parser.ReadUntil(new[] { '{', '}' }) == null)
                                {
                                    break;
                                }
                                if (parser.Read() == '{')
                                {
                                    count++;
                                }
                                else
                                {
                                    count--;
                                }
                            } while (count != 0);
                        }
                        parser.SkipWhile(CharHelper.IsClassicWhitespace);
                        if (parser.Read("}"))
                        {
                            break;
                        }
                    }
                }
                parser.Read("```");
            }
        }