namespace CanonSharp.Common.LexicalAnalyzer; public abstract class RegularExpression { public abstract NondeterministicFiniteAutomation Convert2Nfa(); /// /// 匹配空字符串 /// public static RegularExpression Empty => new EmptyExpression(); /// /// 匹配单个字符 /// c /// /// /// public static RegularExpression Single(char c) => new SymbolExpression(c); /// /// left|right /// /// /// /// public static RegularExpression Alternate(RegularExpression left, RegularExpression right) => new AlternationExpression(left, right); /// /// left-right /// /// /// /// public static RegularExpression Concatenate(RegularExpression first, RegularExpression second) => new ConcatenationExpression(first, second); /// /// inner* /// /// /// public static RegularExpression Kleene(RegularExpression inner) => new KleeneExpression(inner); /// /// value /// /// /// public static RegularExpression String(string value) => new StringExpression(value); public static RegularExpression CharSetOf(string value) => new CharSetExpression(value.ToCharArray()); public static RegularExpression CharSetOf(Func predicate) => new CharSetExpression(Iterate(char.MinValue, char.MaxValue).Where(predicate).ToArray()); /// /// [a-b] /// /// /// /// public static RegularExpression Range(char a, char b) => new CharSetExpression(Iterate(a, b).ToArray()); private static IEnumerable Iterate(char a, char b) { for (char c = a; c <= b; c++) { if (c == char.MaxValue) { yield break; } yield return c; } } } public class EmptyExpression : RegularExpression { public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicState final = new(); NondeterministicState start = new(); start.AddTransaction(EmptyChar.Empty, final); return new NondeterministicFiniteAutomation(start, [final]); } } public class SymbolExpression(char symbol) : RegularExpression { public char Symbol { get; } = symbol; public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicState final = new(); NondeterministicState start = new(); start.AddTransaction(new EmptyChar(Symbol), final); return new NondeterministicFiniteAutomation(start, [final]); } } public class AlternationExpression(RegularExpression left, RegularExpression right) : RegularExpression { public RegularExpression Left { get; } = left; public RegularExpression Right { get; } = right; public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicFiniteAutomation left = Left.Convert2Nfa(); NondeterministicFiniteAutomation right = Right.Convert2Nfa(); NondeterministicState final = new(); foreach (NondeterministicState state in left.FinalStates.Concat(right.FinalStates)) { state.AddTransaction(EmptyChar.Empty, final); } NondeterministicState start = new(); start.AddTransaction(EmptyChar.Empty, left.Start); start.AddTransaction(EmptyChar.Empty, right.Start); return new NondeterministicFiniteAutomation(start, [final]); } } public class ConcatenationExpression(RegularExpression first, RegularExpression second) : RegularExpression { public RegularExpression First { get; } = first; public RegularExpression Second { get; } = second; public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicFiniteAutomation first = First.Convert2Nfa(); NondeterministicFiniteAutomation second = Second.Convert2Nfa(); foreach (NondeterministicState state in first.FinalStates) { state.AddTransaction(EmptyChar.Empty, second.Start); } return new NondeterministicFiniteAutomation(first.Start, second.FinalStates); } } public class KleeneExpression(RegularExpression inner) : RegularExpression { public RegularExpression Inner { get; } = inner; public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicFiniteAutomation inner = Inner.Convert2Nfa(); NondeterministicState final = new(); final.AddTransaction(EmptyChar.Empty, inner.Start); foreach (NondeterministicState state in inner.FinalStates) { state.AddTransaction(EmptyChar.Empty, final); } return new NondeterministicFiniteAutomation(final, [final]); } } public class CharSetExpression : RegularExpression { public char[] Set { get; } public CharSetExpression(Span set) { if (set.Length == 0) { throw new InvalidOperationException(); } Set = set.ToArray(); } public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicState start = new(); NondeterministicState final = new(); foreach (char c in Set) { start.AddTransaction(new EmptyChar(c), final); } return new NondeterministicFiniteAutomation(start, [final]); } } public class StringExpression : RegularExpression { public string Word { get; } public StringExpression(string word) { if (string.IsNullOrEmpty(word)) { throw new InvalidOperationException(); } Word = word; } public override NondeterministicFiniteAutomation Convert2Nfa() { NondeterministicState start = new(); NondeterministicState final = Word.Aggregate(start, (state, c) => { NondeterministicState next = new(); state.AddTransaction(new EmptyChar(c), next); return next; }); return new NondeterministicFiniteAutomation(start, [final]); } }