Пример #1
0
        private int Test <TLetter>(string pattern, bool caseSensitive, IUnicodeMapper <TLetter> mapper, TLetter?eof, RangeSet <TLetter> validRanges, out AlphabetBuilder <TLetter> builder)
            where TLetter : struct, IEquatable <TLetter>, IComparable <TLetter>
        {
            this.output.WriteLine("Input regex (Case Sensitive: {0}, EOF letter: {1}):", caseSensitive, eof.HasValue);
            this.output.WriteLine(pattern);
            var provider = new UnicodeCharSetProvider();
            var regex    = RegexParser.Parse(pattern, null).ToInvariant(mapper, provider, caseSensitive);

            this.output.WriteLine("");
            this.output.WriteLine("{0} regex:", typeof(TLetter).Name);
            this.output.WriteLine(regex.ToString());
            builder = new AlphabetBuilder <TLetter>(regex, eof, validRanges);
            this.output.WriteLine("");
            this.output.WriteLine("Generated letter mapping:");
            foreach (var pair in builder.AlphabetById)
            {
                this.output.WriteLine("{0}: {1} ({2})", pair.Key, pair.Value, pair.Value.Count);
            }
            this.output.WriteLine("");
            this.output.WriteLine("Letter Regex:");
            this.output.WriteLine(builder.Expression.ToString());
            this.output.WriteLine("");
            this.output.WriteLine("Mapping function pseudocode:");
            var inSwitch = false;

            foreach (var grouping in builder
                     .AlphabetById
                     .SelectMany(p => p.Value.Select(r => new KeyValuePair <Range <TLetter>, LetterId>(r, p.Key)))
                     .GroupBy(p => new {
                Range = (!typeof(TLetter).IsPrimitive) || p.Key.Expand().Skip(2).Any(),
                LetterId = p.Value
            }, p => p.Key)
                     .OrderBy(p => p.Key.Range)
                     .ThenBy(p => p.Key.LetterId))
            {
                if (grouping.Key.Range)
                {
                    if (inSwitch)
                    {
                        this.output.WriteLine("}");
                        inSwitch = false;
                    }
                    this.output.WriteLine("if ({0}) return {1}", string.Join(" ||" + Environment.NewLine + "    ", grouping.OrderBy(r => r.From).Select(r => r.From.CompareTo(r.To) == 0 ? $"(v == '{r.From}')" : $"(v >= '{r.From}' && v <= '{r.To}')")), grouping.Key.LetterId);
                }
                else
                {
                    if (!inSwitch)
                    {
                        this.output.WriteLine("switch (v) {");
                        inSwitch = true;
                    }
                    this.output.WriteLine("{0}" + Environment.NewLine + "        return {1}", string.Join(Environment.NewLine, grouping.SelectMany(g => g.Expand()).OrderBy(r => r).Select(r => $"    case '{r}':")), grouping.Key.LetterId);
                }
            }
            if (inSwitch)
            {
                this.output.WriteLine("}");
            }
            return(builder.AlphabetById.Count);
        }
        public static Expression <Func <TLetter, LetterId> > CreateExpression(AlphabetBuilder <TLetter> builder, LetterId?defaultLetter = null)
        {
            var ranges            = builder.AlphabetById.SelectMany(p => p.Value.Select(r => new KeyValuePair <Range <TLetter>, LetterId>(r, p.Key))).Where(p => p.Value != defaultLetter).OrderBy(p => p.Key.From).ToList();
            var paramValue        = Expression.Parameter(typeof(TLetter), "value");
            var defaultExpression = defaultLetter.HasValue
                                        ? (Expression)Expression.Constant(defaultLetter.Value.ToInt32())
                                        : Expression.Throw(
                Expression.New(
                    Reflect.GetConstructor(() => new InvalidOperationException())), typeof(int));
            var body = Expression.New(LetterId_Ctor, BinaryCompare(ranges, 0, ranges.Count, paramValue, defaultExpression));

            return(Expression.Lambda <Func <TLetter, LetterId> >(body, paramValue));
        }