add more rules for ir opt, fix wrong process to dot
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StgSharp.RegularAnalysis
|
||||||
|
{
|
||||||
|
internal class SourceGenerate
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,26 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||||
|
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\StgSharp.Common\StgSharp.Common.csproj" />
|
<ProjectReference Include="..\StgSharp.Common\StgSharp.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="$(OutputPath)$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
|
<None Include="$(OutputPath)$(AssemblyName).pdb" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" Condition="Exists('$(OutputPath)$(AssemblyName).pdb')" />
|
||||||
|
<None Include="$(OutputPath)StgSharp.Common.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" Condition="Exists('$(OutputPath)StgSharp.Common.dll')" />
|
||||||
|
<None Include="$(OutputPath)StgSharp.Common.pdb" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" Condition="Exists('$(OutputPath)StgSharp.Common.pdb')" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
+19
-9
@@ -1,6 +1,6 @@
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="CharSetEmitter"
|
// file="RegexAnalyzerBackEnd.CharSetEmitter"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload. All rights reserved.
|
||||||
@@ -44,7 +44,7 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal record struct CharSet(
|
internal record struct RegexCharSet(
|
||||||
string value,
|
string value,
|
||||||
CharSetType t,
|
CharSetType t,
|
||||||
bool accept
|
bool accept
|
||||||
@@ -57,12 +57,17 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
public string Value { get; set; } = value;
|
public string Value { get; set; } = value;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return $"{{value:{value}, type:{Type}, accept:{IsAcceptable}}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CharSetEmitter
|
}
|
||||||
|
|
||||||
|
internal static partial class RegexAnalyzerBackEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
public static CharSet[] FigureCharSetType(
|
public static RegexCharSet[] FigureCharSetType(
|
||||||
ReadOnlySpan<char> source
|
ReadOnlySpan<char> source
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -76,19 +81,24 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
ReadOnlySpan<char> seq = source.Slice(idx, source.Length - idx - 1);
|
ReadOnlySpan<char> seq = source.Slice(idx, source.Length - idx - 1);
|
||||||
if (seq.IndexOf('-') == -1)
|
if (seq.IndexOf('-') == -1)
|
||||||
{
|
{
|
||||||
return [new CharSet(seq.ToString(), CharSetType.Single, accept)];
|
return [new RegexCharSet(seq.ToString(), CharSetType.Single, accept)];
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
List<CharSet> list = [];
|
List<RegexCharSet> list = [];
|
||||||
for (int i = 0; i < seq.Length && seq.Length > 0; )
|
for (; seq.Length > 0; )
|
||||||
{
|
{
|
||||||
int pos = seq.IndexOf('-');
|
int pos = seq.IndexOf('-');
|
||||||
|
if (pos == -1)
|
||||||
|
{
|
||||||
|
RegexCharSet single = new(seq.ToString(), CharSetType.Single, accept);
|
||||||
|
list.Add(single);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
if (pos > 1) {
|
if (pos > 1) {
|
||||||
list.Add(new(seq[0..(pos - 1)].ToString(), CharSetType.Single, accept));
|
list.Add(new(seq[0..(pos - 1)].ToString(), CharSetType.Single, accept));
|
||||||
}
|
}
|
||||||
list.Add(new($"{seq[pos - 1]}{seq[pos + 1]}", CharSetType.Range, accept));
|
list.Add(new($"{seq[pos - 1]}{seq[pos + 1]}", CharSetType.Range, accept));
|
||||||
i = pos + 2;
|
seq = seq[(pos + 2)..];
|
||||||
seq = seq[i..];
|
|
||||||
}
|
}
|
||||||
return [.. list];
|
return [.. list];
|
||||||
}
|
}
|
||||||
+6
-10
@@ -1,6 +1,6 @@
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="RegexInterpreter.SourceGenerate"
|
// file="RegexAnalyzerBackEnd"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload. All rights reserved.
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
//
|
//
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -33,19 +34,14 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace StgSharp.RegularAnalysis.Text
|
namespace StgSharp.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
public partial class RegexAnalyzer
|
internal static partial class RegexAnalyzerBackEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static string GetSourceCode(
|
internal static string GenerateSource(
|
||||||
IEnumerable<RegexIR> irs
|
List<RegexIR> ir
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
return string.Empty;
|
||||||
foreach (RegexIR ir in irs)
|
|
||||||
{
|
|
||||||
// ScanAndMarkIROptimization(ir);
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -35,7 +35,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace StgSharp.RegularAnalysis.Text
|
namespace StgSharp.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
public partial class RegexAnalyzer
|
public partial class RegexAnalyzerFrontEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
private static AbstractSyntaxTree<RegexAstNode, RegexElementLabel> GenerateAST(
|
private static AbstractSyntaxTree<RegexAstNode, RegexElementLabel> GenerateAST(
|
||||||
+1
-1
@@ -39,7 +39,7 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace StgSharp.RegularAnalysis.Text
|
namespace StgSharp.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
public partial class RegexAnalyzer
|
public partial class RegexAnalyzerFrontEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
private static RegexAstNode FlattenAlt(
|
private static RegexAstNode FlattenAlt(
|
||||||
+1
-1
@@ -40,7 +40,7 @@ using System.Xml;
|
|||||||
|
|
||||||
namespace StgSharp.RegularAnalysis.Text
|
namespace StgSharp.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
public partial class RegexAnalyzer
|
public partial class RegexAnalyzerFrontEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static List<RegexIR> GenerateIR(
|
internal static List<RegexIR> GenerateIR(
|
||||||
+99
-8
@@ -1,6 +1,6 @@
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="RegexAnalyzer.IROptimize"
|
// file="RegexAnalyzerFrontEnd.IROptimize"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload. All rights reserved.
|
||||||
@@ -37,7 +37,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace StgSharp.RegularAnalysis.Text
|
namespace StgSharp.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
public partial class RegexAnalyzer
|
public partial class RegexAnalyzerFrontEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static void ScanAndOptimizeIR(
|
internal static void ScanAndOptimizeIR(
|
||||||
@@ -50,7 +50,10 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
List<RegexIR> opt_ir = new(origin_ir.Count);
|
List<RegexIR> opt_ir = new(origin_ir.Count);
|
||||||
RegexIR[] opt_window = new RegexIR[8];
|
RegexIR[] opt_window = new RegexIR[8];
|
||||||
Span<RegexIR> opt_win_sp = opt_window;
|
Span<RegexIR> opt_win_sp = opt_window;
|
||||||
opt_cycle:
|
int result;
|
||||||
|
|
||||||
|
// phase 0: common opt
|
||||||
|
phase_zero:
|
||||||
opt_count = 0;
|
opt_count = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
Span<RegexIR> origin_span = CollectionsMarshal.AsSpan(origin_ir);
|
Span<RegexIR> origin_span = CollectionsMarshal.AsSpan(origin_ir);
|
||||||
@@ -62,7 +65,6 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
opt_win_sp.Clear();
|
opt_win_sp.Clear();
|
||||||
origin_span[index..last].CopyTo(opt_win_sp);
|
origin_span[index..last].CopyTo(opt_win_sp);
|
||||||
|
|
||||||
int result;
|
|
||||||
if ((result = TryExpandPlus(opt_win_sp, opt_ir)) >= 0)
|
if ((result = TryExpandPlus(opt_win_sp, opt_ir)) >= 0)
|
||||||
{
|
{
|
||||||
process_count++;
|
process_count++;
|
||||||
@@ -130,12 +132,14 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
}
|
}
|
||||||
(origin_ir, opt_ir) = (opt_ir, origin_ir);
|
(origin_ir, opt_ir) = (opt_ir, origin_ir);
|
||||||
opt_ir.Clear();
|
opt_ir.Clear();
|
||||||
goto opt_cycle;
|
goto phase_zero;
|
||||||
}
|
}
|
||||||
/**/
|
|
||||||
|
// phase 1: dot star replace
|
||||||
(origin_ir, opt_ir) = (opt_ir, origin_ir);
|
(origin_ir, opt_ir) = (opt_ir, origin_ir);
|
||||||
opt_ir.Clear();
|
opt_ir.Clear();
|
||||||
index = 0;
|
index = 0;
|
||||||
|
opt_count = 0;
|
||||||
origin_span = CollectionsMarshal.AsSpan(origin_ir);
|
origin_span = CollectionsMarshal.AsSpan(origin_ir);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -150,8 +154,10 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
process_count += count + 1;
|
process_count += count + 1;
|
||||||
Span<RegexIR> opt_block = origin_span.Slice(index, count + 1);
|
Span<RegexIR> opt_block = origin_span.Slice(index, count + 1);
|
||||||
opt_ir.AddRange(opt_block);
|
opt_ir.AddRange(opt_block);
|
||||||
} else if (TryReplaceDotStar(opt_win_sp, opt_ir) >= 0)
|
} else
|
||||||
|
if (TryReplaceDotStar(opt_win_sp, opt_ir) >= 0)
|
||||||
{
|
{
|
||||||
|
opt_count++;
|
||||||
process_count++;
|
process_count++;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@@ -161,7 +167,53 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
index += process_count;
|
index += process_count;
|
||||||
} while (index < origin_ir.Count);
|
} while (index < origin_ir.Count);
|
||||||
/**/
|
if (opt_count == 0)
|
||||||
|
{
|
||||||
|
optIR = opt_ir;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phase 2: find-1 merge and try-find-1 rotate
|
||||||
|
do
|
||||||
|
{
|
||||||
|
(origin_ir, opt_ir) = (opt_ir, origin_ir);
|
||||||
|
opt_ir.Clear();
|
||||||
|
opt_count = 0;
|
||||||
|
index = 0;
|
||||||
|
origin_span = CollectionsMarshal.AsSpan(origin_ir);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int process_count = 0;
|
||||||
|
int last = int.Min(origin_span.Length, index + 8);
|
||||||
|
opt_win_sp.Clear();
|
||||||
|
origin_span[index..last].CopyTo(opt_win_sp);
|
||||||
|
|
||||||
|
if (opt_win_sp[0] is IRegexComplex { IsFullyOptimized: true, CommandCount: > 0 } skip)
|
||||||
|
{
|
||||||
|
int count = skip.CommandCount;
|
||||||
|
process_count += count + 1;
|
||||||
|
Span<RegexIR> opt_block = origin_span.Slice(index, count + 1);
|
||||||
|
opt_ir.AddRange(opt_block);
|
||||||
|
} else if (TyrMergeFindRestTwice(opt_win_sp, opt_ir) == 0)
|
||||||
|
{
|
||||||
|
process_count += 2;
|
||||||
|
opt_count++;
|
||||||
|
} else if ((result = TyrMergeFindRestTry(opt_win_sp, opt_ir)) >= 0)
|
||||||
|
{
|
||||||
|
Span<RegexIR> opt_block = origin_span.Slice(index + 2, result);
|
||||||
|
opt_ir.AddRange(opt_block);
|
||||||
|
process_count += 2;
|
||||||
|
process_count += result;
|
||||||
|
opt_count++;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
opt_ir.Add(opt_win_sp[0]);
|
||||||
|
process_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += process_count;
|
||||||
|
} while (index < origin_ir.Count);
|
||||||
|
} while (opt_count > 0);
|
||||||
optIR = opt_ir;
|
optIR = opt_ir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +337,45 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region merge find and try-find
|
||||||
|
|
||||||
|
private static int TyrMergeFindRestTwice(
|
||||||
|
Span<RegexIR> window,
|
||||||
|
List<RegexIR> opt
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (window[0] is not RegexFindComplexIR { CommandCount: -1 } find_1 ||
|
||||||
|
window[1] is not RegexFindComplexIR find_2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
RegexFindComplexIR find_try = new(find_1.IsNearest && find_2.IsNearest, find_2.CommandCount)
|
||||||
|
{
|
||||||
|
IsFullyOptimized = true
|
||||||
|
};
|
||||||
|
opt.Add(find_try);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int TyrMergeFindRestTry(
|
||||||
|
Span<RegexIR> window,
|
||||||
|
List<RegexIR> opt
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (window[0] is not RegexFindComplexIR { CommandCount: -1 } _find ||
|
||||||
|
window[1] is not RegexTryIR _try) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
RegexFindComplexIR find_try = new(_find.IsNearest, _try.CommandCount)
|
||||||
|
{
|
||||||
|
IsFullyOptimized = true
|
||||||
|
};
|
||||||
|
opt.Add(find_try);
|
||||||
|
return find_try.CommandCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region expand once
|
#region expand once
|
||||||
|
|
||||||
private static void TryExpandComplex(
|
private static void TryExpandComplex(
|
||||||
+1
-1
@@ -67,7 +67,7 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static partial class RegexAnalyzer
|
public static partial class RegexAnalyzerFrontEnd
|
||||||
{
|
{
|
||||||
|
|
||||||
public static TextRegexSource Analyze(
|
public static TextRegexSource Analyze(
|
||||||
@@ -87,12 +87,12 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
public bool IsFullyOptimized { get; set; }
|
public bool IsFullyOptimized { get; set; }
|
||||||
|
|
||||||
|
public bool IsNearest { get; } = nearest;
|
||||||
|
|
||||||
public int CommandCount { get; set; } = count;
|
public int CommandCount { get; set; } = count;
|
||||||
|
|
||||||
internal override RegexIRCommand Command => RegexIRCommand.Find_Complex;
|
internal override RegexIRCommand Command => RegexIRCommand.Find_Complex;
|
||||||
|
|
||||||
private bool IsNearest { get; } = nearest;
|
|
||||||
|
|
||||||
internal override string AsCommand(
|
internal override string AsCommand(
|
||||||
int lineNum
|
int lineNum
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
Console.WriteLine("returns empty");
|
|
||||||
return Token<RegexElementLabel>.Empty;
|
return Token<RegexElementLabel>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
|
|
||||||
public RegexTokenReader() { }
|
public RegexTokenReader() { }
|
||||||
|
|
||||||
public RegexTokenReader(string source)
|
public RegexTokenReader(
|
||||||
|
string source
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_source = source;
|
_source = source;
|
||||||
}
|
}
|
||||||
@@ -65,9 +67,11 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
{
|
{
|
||||||
string value = _source[(pos + 1)..(pos + 3)];
|
string value = _source[(pos + 1)..(pos + 3)];
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (uint.TryParse(value, out uint code) && Rune.TryCreate(code, out Rune result))
|
if (uint.TryParse(value, out uint code) &&
|
||||||
|
Rune.TryCreate(code, out Rune result))
|
||||||
{
|
{
|
||||||
return new Token<RegexElementLabel>(result.ToString(), 0, pos, RegexElementLabel.UNIT);
|
return new Token<RegexElementLabel>(result.ToString(), 0, pos,
|
||||||
|
RegexElementLabel.UNIT);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
throw new InvalidCastException($"Failed to convert {value} to a valid ascii code point.");
|
throw new InvalidCastException($"Failed to convert {value} to a valid ascii code point.");
|
||||||
@@ -76,9 +80,11 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
{
|
{
|
||||||
string value = _source[(pos + 1)..(pos + 5)];
|
string value = _source[(pos + 1)..(pos + 5)];
|
||||||
pos += 6;
|
pos += 6;
|
||||||
if (uint.TryParse(value, out uint code) && Rune.TryCreate(code, out Rune result))
|
if (uint.TryParse(value, out uint code) &&
|
||||||
|
Rune.TryCreate(code, out Rune result))
|
||||||
{
|
{
|
||||||
return new Token<RegexElementLabel>(result.ToString(), 0, pos, RegexElementLabel.UNIT);
|
return new Token<RegexElementLabel>(result.ToString(), 0, pos,
|
||||||
|
RegexElementLabel.UNIT);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
throw new InvalidCastException($"Failed to convert {value} to a valid unicode code point.");
|
throw new InvalidCastException($"Failed to convert {value} to a valid unicode code point.");
|
||||||
@@ -99,6 +105,10 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Unclosed Unicode property escape sequence.");
|
throw new InvalidOperationException("Unclosed Unicode property escape sequence.");
|
||||||
|
} else if (_source[pos + 1] == '.')
|
||||||
|
{
|
||||||
|
position = pos + 2;
|
||||||
|
return new Token<RegexElementLabel>(".", 0, pos, RegexElementLabel.UNIT);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
position = pos + 2;
|
position = pos + 2;
|
||||||
@@ -112,21 +122,24 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
{
|
{
|
||||||
int length = (i - pos - 1);
|
int length = (i - pos - 1);
|
||||||
position = i + 1;
|
position = i + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(i + 1)], 0, position,
|
return new Token<RegexElementLabel>(_source[(pos)..(i + 1)], 0,
|
||||||
|
position,
|
||||||
RegexElementLabel.UNIT_SET);
|
RegexElementLabel.UNIT_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Unclosed character set");
|
throw new InvalidOperationException("Unclosed character set");
|
||||||
case '|':
|
case '|':
|
||||||
position = pos + 1;
|
position = pos + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos, RegexElementLabel.ALT);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||||
|
RegexElementLabel.ALT);
|
||||||
case '(':
|
case '(':
|
||||||
|
|
||||||
// very comlex here
|
// very comlex here
|
||||||
return ReadGroupBeginToken();
|
return ReadGroupBeginToken();
|
||||||
case ')':
|
case ')':
|
||||||
position = pos + 1;
|
position = pos + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos, RegexElementLabel.GROUP_END);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||||
|
RegexElementLabel.GROUP_END);
|
||||||
case '{':
|
case '{':
|
||||||
for (int i = pos + 1; i < _source.Length; i++)
|
for (int i = pos + 1; i < _source.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -141,20 +154,26 @@ namespace StgSharp.RegularAnalysis.Text
|
|||||||
case '*' or '+':
|
case '*' or '+':
|
||||||
int count = pos + 1 >= _source.Length ? 1 : (_source[pos + 1] == '?' ? 2 : 1);
|
int count = pos + 1 >= _source.Length ? 1 : (_source[pos + 1] == '?' ? 2 : 1);
|
||||||
position = pos + count;
|
position = pos + count;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + count)], 0, pos, RegexElementLabel.COUNT);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + count)], 0, pos,
|
||||||
|
RegexElementLabel.COUNT);
|
||||||
case '?':
|
case '?':
|
||||||
position = pos + 1;
|
position = pos + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos, RegexElementLabel.COUNT);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||||
|
RegexElementLabel.COUNT);
|
||||||
case '.':
|
case '.':
|
||||||
position = pos + 1;
|
position = pos + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos, RegexElementLabel.UNIT);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||||
|
RegexElementLabel.UNIT_SET);
|
||||||
default:
|
default:
|
||||||
position = pos + 1;
|
position = pos + 1;
|
||||||
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos, RegexElementLabel.UNIT);
|
return new Token<RegexElementLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||||
|
RegexElementLabel.UNIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryReadToken(out Token<RegexElementLabel> t)
|
public bool TryReadToken(
|
||||||
|
out Token<RegexElementLabel> t
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (IsEmpty)
|
if (IsEmpty)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,19 +40,21 @@ namespace StgSharp
|
|||||||
{
|
{
|
||||||
|
|
||||||
private static string[] regexSource = [
|
private static string[] regexSource = [
|
||||||
|
@"[.]*",
|
||||||
|
/*
|
||||||
@"http|https|ftp|ftps",
|
@"http|https|ftp|ftps",
|
||||||
@"abc[0-9]x|abc[0-9]y|abd[0-9]x|abd[0-9]y|xyz",
|
@"abc[0-9]x|abc[0-9]y|abd[0-9]x|abd[0-9]y|xyz",
|
||||||
@"get_name|get_value|get_type|set_name|set_value|set_type",
|
@"get_name|get_value|get_type|set_name|set_value|set_type",
|
||||||
@"helix|hello|help|hero|hers|her",
|
@"helix|hello|help|hero|hers|her",
|
||||||
@"a*.[abc]*(abcd|a(bc)c)+(?<name>abc{11,13})"
|
@"a*.[abc]*(abcd|a(bc)c)+(?<name>.*)234"
|
||||||
|
/**/
|
||||||
];
|
];
|
||||||
|
|
||||||
public static void Run()
|
public static void Run()
|
||||||
{
|
{
|
||||||
foreach (string regex in regexSource)
|
foreach (string regex in regexSource)
|
||||||
{
|
{
|
||||||
TextRegexSource interpreterSource = RegexAnalyzer.Analyze(regex);
|
TextRegexSource interpreterSource = RegexAnalyzerFrontEnd.Analyze(regex);
|
||||||
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree = interpreterSource.Ast;
|
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree = interpreterSource.Ast;
|
||||||
Console.WriteLine($"result of \"{regex}\"");
|
Console.WriteLine($"result of \"{regex}\"");
|
||||||
TreeEnumerator<RegexAstNode, RegexElementLabel> enumerator = new(tree);
|
TreeEnumerator<RegexAstNode, RegexElementLabel> enumerator = new(tree);
|
||||||
|
|||||||
Reference in New Issue
Block a user