diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.MultiIR.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.MultiIR.cs new file mode 100644 index 00000000..c3e3a342 --- /dev/null +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.MultiIR.cs @@ -0,0 +1,75 @@ +// ----------------------------------------------------------------------------- +// file="TextRegexSourceGen.GenClass.MultiIR" +// Project: StgSharp +// Copyright (c) Nitload. +// SPDX-License-Identifier: MIT +// ----------------------------------------------------------------------------- + +using StgSharp.RegularAnalysis.Abstraction; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace StgSharp.RegularAnalysis.Text +{ + internal partial class TextRegexSourceGen + { + + private static void GenerateRegion( + ReadOnlySpan region_ir, + SourceGenContext sc, + in SequenceEmitter main_emitter, + in List> sub_emitter_list + ) + { + int current_region = region_ir[0].Prefix.WorkingRegion; + ReadOnlySpan ir_sp = region_ir; + ReadOnlySpan scan_win; + int index = 0; + do + { + int result; + int count = 0; + scan_win = ir_sp[index..]; + if ((result = TryGenerateFindSeq(scan_win, sc, in main_emitter, + in sub_emitter_list)) > 0) + { + count += result; + } else + if (TryGenerateMatchSeq(scan_win, main_emitter, sc) > 0) + { + count += 1; + } else if (TryGenerateMatchSet(scan_win, main_emitter, sc) > 0) + { + count++; + } else if (TryGenerateFindSeq(scan_win, main_emitter, sc) > 0) + { + count++; + } else { } + index += count; + } while (index < ir_sp.Length); + } + + private static int TryGenerateFindSeq( + ReadOnlySpan scan_win, + SourceGenContext sc, + in SequenceEmitter main_emitter, + in List> sub_emitter_list + ) + { + if (scan_win[0] is not RegexFindSeqIR find) { + return -1; + } + _ = main_emitter.AppendLine() + .AppendLine(@$"//Find sequence:{FormatStringLiteral(find.Pattern)} at any pos") + .AppendLine(@"do") + .AppendLine(@"{"); + return 1; + } + + } +} diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs index 0b4249da..70550560 100644 --- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs @@ -12,8 +12,11 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace StgSharp.RegularAnalysis.Text @@ -31,7 +34,7 @@ namespace StgSharp.RegularAnalysis.Text { SequenceEmitter se = new(); List> sub_match_list = []; - SourceGenContext ng = new(); + SourceGenContext sc = new(); RegexInfo info = source.Info; List ir = source.IRs; @@ -41,25 +44,20 @@ namespace StgSharp.RegularAnalysis.Text SequenceEmitter match_e = new(); int index = 0; - do + int end = FindRrgionEnd(ir_sp, index); + ReadOnlySpan region = ir_sp[0..end]; + + while (true) { - int result; - - int count = int.Min(8, ir_sp.Length - index); - ir_sp.Slice(index, count).CopyTo(scan_win); - if (TryGenerateMatchSeq(scan_win, match_e, ng) > 0) + GenerateRegion(region, sc, match_e, sub_match_list); + if (end >= ir_sp.Length) { - count += 1; - } else if (TryGenerateMatchSet(scan_win, match_e, ng) > 0) - { - count++; - } else if (TryGenerateFindSeq(scan_win, match_e, ng) > 0) - { - count++; - } else { } - index += count; - } while (index < ir.Count); - + break; + } + index = end; + end = FindRrgionEnd(ir_sp, end); + region = ir_sp[index..end]; + } _ = se.AppendLine($@"public override MatchResult Match({ROS_char} text)")// .AppendLine(@"{"); @@ -76,7 +74,7 @@ namespace StgSharp.RegularAnalysis.Text .AppendLine($@"int {offset} = 0;") .AppendLine(); - _ = ng.GenVarDefine(se); + _ = sc.GenVarDefine(se); _ = se.Append(match_e); @@ -91,15 +89,25 @@ namespace StgSharp.RegularAnalysis.Text return se; } - private static string FormatStringLiteral( - string str + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int FindRrgionEnd( + ReadOnlySpan ir_sp, + int current ) { - return SyntaxFactory.Literal(str).Text; + int cur_depth = ir_sp[current].Prefix.WorkingRegion; + int end = ir_sp.Length; + for (; end > 0; end--) + { + if (ir_sp[end].Prefix.WorkingRegion == cur_depth) { + return end; + } + } + return 1; } private static string FormatStringLiteral( - char str + string str ) { return SyntaxFactory.Literal(str).Text; @@ -108,7 +116,7 @@ namespace StgSharp.RegularAnalysis.Text #region sub generator private static int TryGenerateFindSeq( - Span scan_win, + ReadOnlySpan scan_win, SequenceEmitter se, SourceGenContext ng ) @@ -129,7 +137,7 @@ namespace StgSharp.RegularAnalysis.Text } private static int TryGenerateMatchSeq( - Span scan_win, + ReadOnlySpan scan_win, SequenceEmitter se, SourceGenContext ng ) @@ -148,114 +156,8 @@ namespace StgSharp.RegularAnalysis.Text return length; } - private static int TryGenerateFindSet( - Span scan_win, - SequenceEmitter se, - SourceGenContext ng - ) - { - if (scan_win[0] is not RegexFindSetIR seq) { - return -1; - } - string pattern = seq.Charset; - - RegexCharSet[] set_pattern = FigureCharSetType(pattern, out bool accept); - - bool first = seq.IsFirst; - - string remain = ng.CurRemain; - string offset = ng.FindResult; - _ = se.AppendLine($@"// match charset of {pattern}") - .AppendLine($@"{remain} = {orig_text}[{current_ptr}..];") - .AppendLine(); - - _ = se.AppendLine("if("); - RegexCharSet p = set_pattern[0]; - string _case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p); - _ = se.AppendLine($@"if ({_case}||"); - - for (int i = 1; i < set_pattern.Length - 1; i++) - { - p = set_pattern[i]; - _case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p); - if (string.IsNullOrEmpty(_case)) - { - continue; - } - _ = se.AppendLine($@" {_case} ||"); - } - - p = set_pattern[^1]; - _case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p); - _ = se.AppendLine($@"{_case})") - .AppendLine("{") - .AppendLine($@"{current_ptr} += 1;") - .AppendLine("}"); - - return 1; - - - string GenerateAcceptCase( - RegexCharSet c - ) - { - string caller; - switch (c.Type) - { - // Handle single character - case CharSetType.Single: - string literal = FormatStringLiteral(c.Value); - caller = first ? "IndexOfAny" : "LastIndexOfAny"; - return $@"({offset} = {remain}.{caller}(""{literal}"") != -1)"; - - // Handle range of characters - case CharSetType.Range: - caller = first ? "IndexOfAnyInRange" : "LastIndexOfAnyInRange"; - return $@"({offset} = {remain}.{caller}('{FormatStringLiteral(c.Value[0])}', '{FormatStringLiteral(c.Value[1])}') != -1)"; - - // Handle set of characters - case CharSetType.Set: - switch (c.Value) - { - case "s": - caller = first ? "IndexOfAnyWhiteSpace" : "LastIndexOfAnyWhiteSpace"; - return $@"({offset} = {remain}.{caller}() != -1)"; - case "w": - - default: - break; - } - case CharSetType.None: - return string.Empty; - default: - return string.Empty; - } - } - - string GenerateDenyCase( - RegexCharSet c - ) - { - switch (c.Type) - { - // Handle single character - case CharSetType.Single: - - // Handle range of characters - case CharSetType.Range: - - // Handle set of characters - case CharSetType.Set: - case CharSetType.None: - return string.Empty; - default: - return string.Empty; - } - } - } - private static int TryGenerateMatchSet( - Span scan_win, + ReadOnlySpan scan_win, SequenceEmitter se, SourceGenContext ng )