Пример #1
0
        [Fact] public void HierarchyOutput()
        {
            var node4  = new RankedNode();
            var node5  = new RankedNode(node4);
            var node6  = new ValueNode <int>(node5, 9);
            var node7  = new ValueNode <int>(node5, 7);
            var node1  = new RankedNode(node4);
            var node2  = new ValueNode <int>(node1, 6);
            var node3  = new ValueNode <int>(node1, 3);
            var node8  = new RankedNode(node4);
            var node9  = new ValueNode <int>(node8, 5);
            var node10 = new ValueNode <int>(node8, 2);
            var hier   = new Hierarchy <int>(node4);

            // T.FileWriter.SetDirAndFile("Tests", nameof(hier), ".txt");
            // T.FileWriter.WriteLine(hier);
            hier.MakeTopNode(node5);
            // T.FileWriter.WriteLine(hier);
            hier.MakeTopNode(node4);
            // T.FileWriter.WriteLine(hier);
            // T.FileWriter.Flush();
            var strw = new StringWriter();

            strw.Write <int>(hier);
            Assert.True(strw.ToString() == "{{9, 7}, {6, 3}, {5, 2}}");
        }
Пример #2
0
        /// <summary>Attempts to read a data stream fed by a text reader as a hierarchy. Throws an exception if the data is not convertible to a hierarchy.</summary>
        /// <param name="tr">Text reader such as FileReader.</param>
        /// <typeparam name="τ">Type of Hierarchy elements.</typeparam>
        public static Hierarchy <τ>?ReadHierarchy <τ>(this TextReader tr)
            where τ : IEquatable <τ>, new()
        {
            var nFI = new NumberFormatInfo();

            nFI.NumberDecimalSeparator = ".";
            var types       = new Type[] { typeof(string), typeof(IFormatProvider) };
            var parseMethod = typeof(τ).GetMethod("Parse", types);

            if (parseMethod == null)
            {
                throw new NullReferenceException("Parse method not found.");
            }
            var parse = (Func <string, IFormatProvider, τ>)Delegate.CreateDelegate(
                typeof(Func <string, IFormatProvider, τ>), parseMethod);

            var wholeStr = tr.ReadToEnd();
            var sb       = new StringBuilder(@"(\w+\.?\w*|", 300);

            sb.Append(@"\{                     ");
            sb.Append(@"  (?>                  ");
            sb.Append(@"      [^{}]+           ");
            sb.Append(@"    |                  ");
            sb.Append(@"      \{ (?<DEPTH>)    ");
            sb.Append(@"    |                  ");
            sb.Append(@"      }  (?<-DEPTH>)   ");
            sb.Append(@"  )*                   ");
            sb.Append(@"  (?(DEPTH)(?!))       ");
            sb.Append(@"}                      ");
            sb.Append(@")");                              // The end of an alternator from first line.
            var matcher = new Regex(sb.ToString(), RegexOptions.IgnorePatternWhitespace,
                                    new TimeSpan(0, 0, 1));
            var firstMatch = matcher.Match(wholeStr);

            if (firstMatch.Success)                                // Now check elements inside it.
            {
                var topNode = new RankedNode();
                var hier    = new Hierarchy <τ>(topNode);
                Recursion(firstMatch.Value, topNode);
                return(hier);
            }
            else
            {
                return(null);
            }

            void Recursion(string prevMatched, RankedNode nodeAbove)
            {
                var sb2 = new StringBuilder(prevMatched, 300);

                sb2.Remove(prevMatched.Length - 1, 1).Remove(0, 1); // Strip it of outer braces.
                prevMatched = sb2.ToString();                       // Now it is without outer braces.
                Match newMatch = matcher.Match(prevMatched);        // Match either first value or braces

                while (newMatch.Success)                            // If there was anything inside at all.
                {
                    if (newMatch.Value[0] == '{')                   // If it was a non-value node.
                    {
                        Recursion(newMatch.Value, new RankedNode(nodeAbove));
                    }
                    else                                                            // If it was a value node.
                    {
                        new ValueNode <τ>(nodeAbove, parse(newMatch.Value, nFI));
                    }
                    newMatch = newMatch.NextMatch();
                }
            }
        }