From d0ac02b488ea3be3937dfd3aca2a42b67185640a Mon Sep 17 00:00:00 2001 From: Adam Simon Date: Mon, 1 Apr 2024 14:23:57 +0200 Subject: [PATCH] Compile adapted regex patterns on .NET 7+ only if they don't contain negative lookaround assertions --- src/Acornima/Ast/INode.cs | 3 + src/Acornima/RegExpParseMode.cs | 3 + src/Acornima/Tokenizer.RegExpParser.cs | 21 +- test/Acornima.Tests/Acornima.Tests.csproj | 2 +- .../Generator/Generator.csproj | 3 +- .../Fixtures.RegExp/Generator/Generator.sln | 2 +- .../Fixtures.RegExp/Generator/Program.cs | 2 +- .../Fixtures.RegExp/testcases.template.txt | 228 ++++++++--------- .../Fixtures.RegExp/testcases.txt | 230 +++++++++--------- test/Acornima.Tests/RegExpTests.Fixtures.cs | 9 +- test/Acornima.Tests/RegExpTests.cs | 27 +- 11 files changed, 291 insertions(+), 239 deletions(-) diff --git a/src/Acornima/Ast/INode.cs b/src/Acornima/Ast/INode.cs index 64e4a91..b17bf4e 100644 --- a/src/Acornima/Ast/INode.cs +++ b/src/Acornima/Ast/INode.cs @@ -10,5 +10,8 @@ public interface INode ref readonly Range RangeRef { get; } SourceLocation Location { get; } ref readonly SourceLocation LocationRef { get; } + /// + /// The operation is not guaranteed to be thread-safe. In case concurrent access or update is possible, the necessary synchronization is caller's responsibility. + /// object? UserData { get; } } diff --git a/src/Acornima/RegExpParseMode.cs b/src/Acornima/RegExpParseMode.cs index 99b6cfd..8a23063 100644 --- a/src/Acornima/RegExpParseMode.cs +++ b/src/Acornima/RegExpParseMode.cs @@ -36,6 +36,9 @@ public enum RegExpParseMode /// In case an invalid regular expression is encountered, is thrown.
/// In the case of a valid regular expression for which an equivalent cannot be constructed, either is thrown /// or a is created with the property set to , depending on the option. + /// + /// Please note that adapted patterns containing negative lookaround assertions won't be compiled on .NET 7+ because of a regression of .NET's regex compiler. + /// /// AdaptToCompiled, } diff --git a/src/Acornima/Tokenizer.RegExpParser.cs b/src/Acornima/Tokenizer.RegExpParser.cs index c50cbea..904813f 100644 --- a/src/Acornima/Tokenizer.RegExpParser.cs +++ b/src/Acornima/Tokenizer.RegExpParser.cs @@ -46,6 +46,10 @@ internal partial struct RegExpParser private const int SetRangeNotStarted = int.MaxValue; private const int SetRangeStartedWithCharClass = int.MaxValue - 1; + // Negative lookaround assertions don't work as expected under .NET 7 and .NET 8 when the regex is compiled + // (see also https://github.com/dotnet/runtime/issues/97455). + private static readonly bool s_canCompileNegativeLookaroundAssertions = typeof(Regex).Assembly.GetName().Version?.Major < 7; + internal static RegExpFlags ParseFlags(string value, int startIndex, Tokenizer tokenizer) { var flags = RegExpFlags.None; @@ -175,7 +179,7 @@ public RegExpParseResult Parse() } } - var adaptedPattern = ParseCore(out var capturingGroups, out conversionError); + var adaptedPattern = ParseCore(out var capturingGroups, out conversionError, out var canCompile); if (adaptedPattern is null) { // NOTE: ParseCore should return null @@ -188,7 +192,7 @@ public RegExpParseResult Parse() Debug.Assert(conversionError is null); capturingGroups.TrimExcess(); - var options = FlagsToOptions(_flags, compiled: _tokenizer._options._regExpParseMode == RegExpParseMode.AdaptToCompiled); + var options = FlagsToOptions(_flags, compiled: _tokenizer._options._regExpParseMode == RegExpParseMode.AdaptToCompiled && canCompile); var matchTimeout = _tokenizer._options._regexTimeout; try @@ -202,7 +206,7 @@ public RegExpParseResult Parse() } } - internal string? ParseCore(out ArrayList capturingGroups, out RegExpConversionError? conversionError) + internal string? ParseCore(out ArrayList capturingGroups, out RegExpConversionError? conversionError, out bool canCompile) { _tokenizer.AcquireStringBuilder(out var sb); try @@ -234,9 +238,11 @@ public RegExpParseResult Parse() }; context.SetFollowingQuantifierError(RegExpNothingToRepeat); - return (_flags & RegExpFlags.Unicode) != 0 + var adaptedPattern = (_flags & RegExpFlags.Unicode) != 0 ? ParsePattern(UnicodeMode.Instance, ref context, out conversionError) : ParsePattern(LegacyMode.Instance, ref context, out conversionError); + canCompile = context.CanCompile; + return adaptedPattern; } finally { @@ -514,6 +520,10 @@ private void CheckBracesBalance(out ArrayList capturingGro context.SetFollowingQuantifierError(RegExpNothingToRepeat); break; } + else if (!s_canCompileNegativeLookaroundAssertions && groupType is RegExpGroupType.NegativeLookaheadAssertion or RegExpGroupType.NegativeLookbehindAssertion) + { + context.CanCompile = false; + } sb?.Append(_pattern, i, 1 + ((int)groupType >> 2)); i += (int)groupType >> 2; @@ -1166,6 +1176,7 @@ public ParsePatternContext(StringBuilder? sb, ReadOnlySpan CapturingGroups = capturingGroups; CapturingGroupNames = capturingGroupNames; + CanCompile = true; } public int Index; @@ -1225,6 +1236,8 @@ public void SetFollowingQuantifierError(string message, [CallerArgumentExpressio // * Lone surrogates need special care too. // We use the following list to build the adjusted character set. public ArrayList UnicodeSet; + + public bool CanCompile; } private interface IMode diff --git a/test/Acornima.Tests/Acornima.Tests.csproj b/test/Acornima.Tests/Acornima.Tests.csproj index 5db2d38..7ecdaed 100644 --- a/test/Acornima.Tests/Acornima.Tests.csproj +++ b/test/Acornima.Tests/Acornima.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net6.0;net8.0 $(TargetFrameworks);net462 true ..\..\src\Karambolo.Public.snk diff --git a/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.csproj b/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.csproj index 939aaa7..1403e06 100644 --- a/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.csproj +++ b/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.csproj @@ -4,7 +4,8 @@ Acornima.Tests Exe net8.0 - enable + true + ..\..\..\..\src\Karambolo.Public.snk diff --git a/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.sln b/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.sln index bc59877..897ad80 100644 --- a/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.sln +++ b/test/Acornima.Tests/Fixtures.RegExp/Generator/Generator.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 17.6.33717.318 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generator", "Generator.csproj", "{5FC6B784-BAA9-4BF6-8845-0D762D938816}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acornima.Core", "..\..\..\..\src\Acornima.Core\Acornima.Core.csproj", "{C3607046-115D-45CE-8EA2-580D270DDC08}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acornima.Core", "..\..\..\..\src\Acornima\Acornima.csproj", "{C3607046-115D-45CE-8EA2-580D270DDC08}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/test/Acornima.Tests/Fixtures.RegExp/Generator/Program.cs b/test/Acornima.Tests/Fixtures.RegExp/Generator/Program.cs index 6ddc3ef..1b71b02 100644 --- a/test/Acornima.Tests/Fixtures.RegExp/Generator/Program.cs +++ b/test/Acornima.Tests/Fixtures.RegExp/Generator/Program.cs @@ -74,7 +74,7 @@ static string DecodeStringIfEscaped(string value) => JavaScriptString.IsStringLi var flags = DecodeStringIfEscaped(parts[1]); var regexParser = new Tokenizer.RegExpParser(pattern, flags, tokenizerOptions); - try { adaptedPattern = regexParser.ParseCore(out _, out _) ?? ")inconvertible("; } + try { adaptedPattern = regexParser.ParseCore(out _, out _, out _) ?? ")inconvertible("; } catch (SyntaxErrorException) { adaptedPattern = ")syntax-error("; } var encodedDotnetPattern = JavaScriptString.Encode(adaptedPattern, addDoubleQuotes: false); if (adaptedPattern != encodedDotnetPattern) diff --git a/test/Acornima.Tests/Fixtures.RegExp/testcases.template.txt b/test/Acornima.Tests/Fixtures.RegExp/testcases.template.txt index 433a762..94e6182 100644 --- a/test/Acornima.Tests/Fixtures.RegExp/testcases.template.txt +++ b/test/Acornima.Tests/Fixtures.RegExp/testcases.template.txt @@ -1572,7 +1572,7 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui pijamalı hasta yağız ş \p{1,} u pp \p{Script=Latn} p{Script=Latn} \p{Script=Latn} u p{Script=Latn} !ignore-error-message !skip-validation -\p{General_Category=Currency_Symbol} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{General_Category=Currency_Symbol} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) \P P \P u P @@ -1590,7 +1590,7 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui pijamalı hasta yağız ş \P{1,} u PP \P{Script=Latn} P{Script=Latn} \P{Script=Latn} u P{Script=Latn} !ignore-error-message !skip-validation -\P{General_Category=Currency_Symbol} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\P{General_Category=Currency_Symbol} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) [\p] \p [\p] u \p @@ -1608,7 +1608,7 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui pijamalı hasta yağız ş [\p{1,}] u \p{1,} [\p{Script=Latn}] \p{Script=Latn} [\p{Script=Latn}] u \p{Script=Latn} !ignore-error-message !skip-validation -[\p{General_Category=Currency_Symbol}] u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[\p{General_Category=Currency_Symbol}] u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) [\P] \P [\P] u \P @@ -1626,13 +1626,13 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui pijamalı hasta yağız ş [\P{1,}] u \P{1,} [\P{Script=Latn}] \P{Script=Latn} [\P{Script=Latn}] u \P{Script=Latn} !ignore-error-message !skip-validation -[\P{General_Category=Currency_Symbol}] u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[\P{General_Category=Currency_Symbol}] u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{General_Category=Sc} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{gc=Currency_Symbol} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{gc=Sc} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Currency_Symbol} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Sc} u $€£𑿝¥ a0? !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{General_Category=Sc} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{gc=Currency_Symbol} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{gc=Sc} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Currency_Symbol} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Sc} u $€£𑿝¥ a0? !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) \p{General_Category} u $€£𑿝¥ a0? \p{General_Category=} u $€£𑿝¥ a0? @@ -1646,109 +1646,109 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui pijamalı hasta yağız ş \p{GeneralCategory=Currency_Symbol} u $€£𑿝¥ a0? \p{general_Category=Currency_Symbol} u $€£𑿝¥ a0? -\p{L} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{LC} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Cased_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Lu} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Uppercase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Ll} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Lowercase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Lt} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Titlecase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Lm} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Modifier_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Lo} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Other_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{M} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Combining_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Mn} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Nonspacing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Mc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Spacing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Me} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Enclosing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{N} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Nd} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Decimal_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{digit} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Nl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Letter_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{No} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Other_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{P} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{punct} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Pc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Connector_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Pd} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Dash_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Ps} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Open_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Pe} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Close_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Pi} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Initial_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Pf} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Final_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Po} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Other_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{S} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Sm} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Math_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Sc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Currency_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Sk} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Modifier_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{So} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Other_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{Z} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Zs} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Space_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Zl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Line_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Zp} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Paragraph_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{C} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Other} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Cc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Control} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{cntrl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Cf} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Format} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Cs} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Surrogate} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Co} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Private_Use} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Cn} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\p{Unassigned} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{Ll} ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\P{Ll} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\P{Ll} ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -\p{Ll}* u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\P{Ll}* u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -[\p{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[\p{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[\P{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[\P{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) - -[^\p{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[^\p{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[^\P{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -[^\P{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{L} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{LC} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Cased_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Lu} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Uppercase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Ll} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Lowercase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Lt} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Titlecase_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Lm} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Modifier_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Lo} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Other_Letter} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{M} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Combining_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Mn} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Nonspacing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Mc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Spacing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Me} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Enclosing_Mark} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{N} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Nd} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Decimal_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{digit} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Nl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Letter_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{No} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Other_Number} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{P} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{punct} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Pc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Connector_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Pd} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Dash_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Ps} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Open_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Pe} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Close_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Pi} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Initial_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Pf} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Final_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Po} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Other_Punctuation} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{S} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Sm} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Math_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Sc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Currency_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Sk} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Modifier_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{So} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Other_Symbol} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{Z} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Zs} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Space_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Zl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Line_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Zp} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Paragraph_Separator} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{C} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Other} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Cc} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Control} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{cntrl} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Cf} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Format} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Cs} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Surrogate} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Co} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Private_Use} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Cn} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{Unassigned} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{Ll} ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\P{Ll} u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\P{Ll} ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +\p{Ll}* u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\P{Ll}* u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +[\p{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[\p{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[\P{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[\P{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) + +[^\p{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[^\p{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[^\P{Ll}] u "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +[^\P{Ll}] ui "DϠeⱬDžLjʷჼªఎ͎︁ःඃ҉꙰7᱐ᛮ〩³㉒  \u2028\u2029\u000f­᠎\udf39\uda29_︳-⸺(﹝)⸥«‟»⸡!︓+⟶$؋^꜄¦⎗͹゘" !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) # Character sets (basic cases) @@ -2647,8 +2647,8 @@ c\b u abc \b(?!un)\w+\b i unite one unethical ethics use untie ultimate \b(?!un)\w+\b ui unite one unethical ethics use untie ultimate -\b\w+\b(?!\p{P}) Disconnected, disjointed thoughts in a sentence fragment. !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) -\b\w+\b(?!\p{P}) u Disconnected, disjointed thoughts in a sentence fragment. !skip-on-netframework # (the adapted pattern is correct but makes the Regex ctor hang on .NET Framework) +\b\w+\b(?!\p{P}) Disconnected, disjointed thoughts in a sentence fragment. !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\b\w+\b(?!\p{P}) u Disconnected, disjointed thoughts in a sentence fragment. !skip-before-net8.0 # (the adapted pattern is correct but makes the Regex ctor hang on .NET Framework) (?=)?x xxyx (?=)*x xxyx diff --git a/test/Acornima.Tests/Fixtures.RegExp/testcases.txt b/test/Acornima.Tests/Fixtures.RegExp/testcases.txt index efaa913..643724f 100644 --- a/test/Acornima.Tests/Fixtures.RegExp/testcases.txt +++ b/test/Acornima.Tests/Fixtures.RegExp/testcases.txt @@ -1,4 +1,4 @@ -# Generated from testcases.template.txt at 2024-02-11T21:48:49 +# Generated from testcases.template.txt at 2024-04-01T15:12:42 # This file defines test cases for regular expression conversion testing (see RegExpTests.ExecuteTestCase). # Each uncommented, non-whitespace line specifies a test case in a tab-delimited format, with the following fields: @@ -1574,7 +1574,7 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui PIJAMALı HASTA YAĞıZ Ş \p{1,} u )syntax-error( pp "Invalid property name" \p{Script=Latn} p{Script=Latn} p{Script=Latn} [{"captures":["p{Script=Latn}"],"index":0}] \p{Script=Latn} u )inconvertible( p{Script=Latn} [{"captures":["p"],"index":0},{"captures":["S"],"index":2},{"captures":["c"],"index":3},{"captures":["r"],"index":4},{"captures":["i"],"index":5},{"captures":["p"],"index":6},{"captures":["t"],"index":7},{"captures":["L"],"index":9},{"captures":["a"],"index":10},{"captures":["t"],"index":11},{"captures":["n"],"index":12}] !ignore-error-message !skip-validation -\p{General_Category=Currency_Symbol} u "(?:\ud807[\udfdd-\udfe0]|𞋿|𞲰|[\\x24¢-¥֏؋߾߿৲৳৻૱௹฿៛₠-⃀꠸﷼﹩$¢£¥₩])" $€£𑿝¥ a0? [{"captures":["$"],"index":0},{"captures":["€"],"index":1},{"captures":["£"],"index":2},{"captures":["𑿝"],"index":3},{"captures":["¥"],"index":5}] !skip-on-netframework # (the adapted pattern depends on the Unicode version included in the .NET runtime) +\p{General_Category=Currency_Symbol} u "(?:\ud807[\udfdd-\udfe0]|𞋿|𞲰|[\\x24¢-¥֏؋߾߿৲৳৻૱௹฿៛₠-⃀꠸﷼﹩$¢£¥₩])" $€£𑿝¥ a0? [{"captures":["$"],"index":0},{"captures":["€"],"index":1},{"captures":["£"],"index":2},{"captures":["𑿝"],"index":3},{"captures":["¥"],"index":5}] !skip-before-net8.0 # (the adapted pattern depends on the Unicode version included in the .NET runtime) \P P P [{"captures":["P"],"index":0}] \P u )syntax-error( P "Invalid property name" @@ -1592,7 +1592,7 @@ PIJAMALı HASTA YAĞıZ ŞOFÖRE ÇABUCAK GÜVENDI ui PIJAMALı HASTA YAĞıZ Ş \P{1,} u )syntax-error( PP "Invalid property name" \P{Script=Latn} P{Script=Latn} P{Script=Latn} [{"captures":["P{Script=Latn}"],"index":0}] \P{Script=Latn} u )inconvertible( P{Script=Latn} [{"captures":["{"],"index":1},{"captures":["="],"index":8},{"captures":["}"],"index":13}] !ignore-error-message !skip-validation -\P{General_Category=Currency_Symbol} u "(?:[\ud800-\ud806][\udc00-\udfff]|\ud807[\udc00-\udfdc]|\ud807[\udfe1-\udfff]|[\ud808-\ud837][\udc00-\udfff]|\ud838[\udc00-\udefe]|\ud838[\udf00-\udfff]|[\ud839\ud83a][\udc00-\udfff]|\ud83b[\udc00-\udcaf]|\ud83b[\udcb1-\udfff]|[\ud83c-\udbff][\udc00-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(? TestCases(string relativePath) continue; } -#if NET462_OR_GREATER +#if !NET8_0_OR_GREATER + if (hintArray.Contains("!skip-before-net8.0")) + { + continue; + } +#endif + +#if NETFRAMEWORK if (hintArray.Contains("!skip-on-netframework")) { continue; diff --git a/test/Acornima.Tests/RegExpTests.cs b/test/Acornima.Tests/RegExpTests.cs index b66febf..7d4002e 100644 --- a/test/Acornima.Tests/RegExpTests.cs +++ b/test/Acornima.Tests/RegExpTests.cs @@ -138,8 +138,33 @@ public void ShouldAllowDuplicateGroupNamesInAlternates(string pattern, string fl RegExpParseMode = RegExpParseMode.AdaptToInterpreted, Tolerant = false }); - var actualAdaptedPattern = parser.ParseCore(out _, out _); + var actualAdaptedPattern = parser.ParseCore(out _, out _, out _); Assert.Equal(expectedAdaptedPattern, actualAdaptedPattern); } + + [Theory] + [InlineData(@"(?:x)", false, false)] + [InlineData(@"(?![^\\x28]*\\x29)", false, false)] + [InlineData(@"(?