Пример #1
0
        private void GenerateGo()
        {
            using (Writer.Method("protected override void Go()"))
            {
                #if DEBUG_OUTPUT
                Writer.Write($@"Debug.WriteLine($""Executing engine starting at {{{runtextpos}.ToString(CultureInfo.InvariantCulture)}}"")");
                Writer.Write($@"Debug.WriteLine("""")");
                #endif

                var culture = DeclareCulture();
                foreach (var operation in Operations)
                {
                    using (Writer.OpenScope($"{operation.Label}: // {operation.CodeName}({string.Join(", ", operation.Operands.Select(o => CSharpWriter.ConvertFormatArgument(o)))})", requireBraces: true, clearLine: true))
                    {
                        CurrentOperation = operation;

                        #if DEBUG_OUTPUT
                        Writer.Write($"DumpState()");
                        Writer.Write($@"Debug.WriteLine(""       {Code.OpcodeDescription(operation.Index)}"")");
                        Writer.Write($@"Debug.WriteLine("""")");
                        #endif

                        Writer.Write($"CheckTimeout()");
                        GenerateOpCode(culture);
                    }
                }

                if (BacktrackOperations.Any())
                {
                    using (Writer.OpenScope("backtrack:"))
                    {
                        Writer.Write($"{EnsureStorage}()");
                        using (Writer.Switch($"{runtrack}[{runtrackpos}++]"))
                        {
                            foreach (var operation in BacktrackOperations)
                            {
                                var summary = operation.Operation.Id >= 0
                                    ? $"{operation.Operation.Label}, {operation.CodeName} ({(!operation.IsBack2 ? "Back" : "Back2")})"
                                    : $"{operation.CodeName} ({(!operation.IsBack2 ? "Back" : "Back2")})";
                                using (Writer.OpenScope($"case {operation.Id}: // {summary}"))
                                {
                                    CurrentOperation = operation.Operation;

                                    #if DEBUG_OUTPUT
                                    if (operation.IsBack2)
                                    {
                                        Writer.Write($@"Debug.WriteLine(""       Backtracking (back2) to code position {operation.Operation.Index}"")");
                                    }
                                    else
                                    {
                                        Writer.Write($@"Debug.WriteLine(""       Backtracking to code position {operation.Operation.Index}"")");
                                    }

                                    Writer.Write($"DumpState()");
                                    Writer.Write($@"Debug.WriteLine(""       {Code.OpcodeDescription(operation.Operation.Index)} {(operation.IsBack2 ? "Back2" : "Back")}"")");
                                    Writer.Write($@"Debug.WriteLine("""")");
                                    #endif

                                    GenerateBacktrackOpCode(operation, culture);
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        private void GenerateBoyerMoorePrefixScan(Field boyerMooreCulture)
        {
            var positive      = Writer.DeclareField($"private static readonly int[] positive = new int[] {{ {string.Join(", ", BoyerMoorePrefix.Positive.Select(i => CSharpWriter.ConvertFormatArgument(i)))} }};");
            var negativeAscii = Writer.DeclareField($"private static readonly int[] negativeAscii = new int[] {{ {string.Join(", ", BoyerMoorePrefix.NegativeASCII.Select(i => CSharpWriter.ConvertFormatArgument(i)))} }};");

            Field negativeUnicode = default;

            if (BoyerMoorePrefix.NegativeUnicode != null)
            {
                var values = string.Join(", ", BoyerMoorePrefix.NegativeUnicode.Select(arr =>
                {
                    return(arr == null
                        ? "null"
                        : $"new int[] {{ {string.Join(", ", arr.Select(i => CSharpWriter.ConvertFormatArgument(i)))} }}");
                }));
                negativeUnicode = Writer.DeclareField($"private static readonly int[][] negativeUnicode = new int[][] {{ {values} }};");
            }

            using (Writer.Method($"private int {BoyerMoorePrefixScan}()"))
            {
                var text     = Writer.DeclareLocal($"var text = {runtext};");
                var index    = Writer.DeclareLocal($"var index = {runtextpos};");
                var beglimit = Writer.DeclareLocal($"var beglimit = {runtextbeg};");
                var endlimit = Writer.DeclareLocal($"var endlimit = {runtextend};");

                var pattern = Writer.DeclareLocal($@"var pattern = ""{BoyerMoorePrefix.Pattern}"";");

                var defadv = !IsRightToLeft
                    ? Writer.DeclareLocal($"var defadv = {BoyerMoorePrefix.Pattern.Length};")
                    : Writer.DeclareLocal($"var defadv = -{BoyerMoorePrefix.Pattern.Length};");

                var startMatch = !IsRightToLeft
                    ? Writer.DeclareLocal($"var startMatch = {BoyerMoorePrefix.Pattern.Length - 1};")
                    : Writer.DeclareLocal($"var startMatch = 0;");

                var endMatch = !IsRightToLeft
                    ? Writer.DeclareLocal($"var endMatch = 0;")
                    : Writer.DeclareLocal($"var endMatch = -{defadv} - 1;");

                var test = !IsRightToLeft
                    ? Writer.DeclareLocal($"var test = {index} + {defadv} - 1;")
                    : Writer.DeclareLocal($"var test = {index} + {defadv};");

                var chMatch = !IsRightToLeft
                    ? Writer.DeclareLocal($"char chMatch = '{BoyerMoorePrefix.Pattern[BoyerMoorePrefix.Pattern.Length - 1]}';")
                    : Writer.DeclareLocal($"char chMatch = '{BoyerMoorePrefix.Pattern[0]}';");

                var chTest        = Writer.DeclareLocal($"char chTest;");
                var test2         = Writer.DeclareLocal($"int test2;");
                var match         = Writer.DeclareLocal($"int match;");
                var advance       = Writer.DeclareLocal($"int advance;");
                var unicodeLookup = negativeUnicode != null
                    ? Writer.DeclareLocal($"int[] unicodeLookup;")
                    : null;

                using (Writer.For($";;"))
                {
                    using (Writer.If($"{test} >= {endlimit} || {test} < {beglimit}"))
                        Writer.Write($"return -1");

                    if (!IsCaseInsensitive)
                    {
                        Writer.Write($"{chTest} = {text}[{test}]");
                    }
                    else
                    {
                        Writer.Write($"{chTest} = {boyerMooreCulture}.TextInfo.ToLower({text}[{test}])");
                    }

                    using (Writer.If($"{chTest} != {chMatch}"))
                    {
                        using (Writer.If($"{chTest} < 128"))
                            Writer.Write($"{advance} = {negativeAscii}[{chTest}]");
                        if (negativeUnicode != null)
                        {
                            using (Writer.ElseIf($"null != ({unicodeLookup} = {negativeUnicode}[{chTest} >> 8])"))
                                Writer.Write($"{advance} = {unicodeLookup}[{chTest} & 0xFF]");
                        }
                        using (Writer.Else())
                            Writer.Write($"{advance} = {defadv}");

                        Writer.Write($"{test} += {advance}");
                    }
                    using (Writer.Else())
                    {
                        Writer.Write($"{test2} = {test}");
                        Writer.Write($"{match} = {startMatch}");

                        using (Writer.For($";;"))
                        {
                            using (Writer.If($"{match} == {endMatch}"))
                            {
                                if (IsRightToLeft)
                                {
                                    Writer.Write($"return {test2} + 1");
                                }
                                else
                                {
                                    Writer.Write($"return {test2}");
                                }
                            }

                            Writer.Write($"{match} -= {Bump()}");
                            Writer.Write($"{test2} -= {Bump()}");

                            if (!IsCaseInsensitive)
                            {
                                Writer.Write($"{chTest} = {text}[{test2}]");
                            }
                            else
                            {
                                Writer.Write($"{chTest} = {boyerMooreCulture}.TextInfo.ToLower({text}[{test2}])");
                            }

                            using (Writer.If($"{chTest} != {pattern}[{match}]"))
                            {
                                Writer.Write($"{advance} = {positive}[{match}]");
                                using (Writer.If($"({chTest} & 0xFF80) == 0"))
                                    Writer.Write($"{test2} = ({match} - {startMatch}) + {negativeAscii}[{chTest}]");
                                if (negativeUnicode != null)
                                {
                                    using (Writer.ElseIf($"null != ({unicodeLookup} = {negativeUnicode}[{chTest} >> 8])"))
                                        Writer.Write($"{test2} = ({match} - {startMatch}) + {unicodeLookup}[{chTest} & 0xFF]");
                                }
                                using (Writer.Else())
                                {
                                    Writer.Write($"{test} += {advance}");
                                    Writer.Write($"break");
                                }

                                if (!IsRightToLeft)
                                {
                                    using (Writer.If($"{test2} > {advance}"))
                                        Writer.Write($"{advance} = {test2}");
                                }
                                else
                                {
                                    using (Writer.If($"{test2} < {advance}"))
                                        Writer.Write($"{advance} = {test2}");
                                }

                                Writer.Write($"{test} += {advance}");
                                Writer.Write($"break");
                            }
                        }
                    }
                }
            }
        }