namespace CanonSharp.Common.LexicalAnalyzer; public class DeterministicState : IEquatable { public Guid Id { get; } = Guid.NewGuid(); public Dictionary Transaction { get; } = []; public bool Equals(DeterministicState? other) => other is not null && Id.Equals(other.Id); public override bool Equals(object? obj) => obj is DeterministicState other && Equals(other); public override int GetHashCode() => Id.GetHashCode(); } public class DeterministicFiniteAutomation { public DeterministicState Start { get; } public HashSet FinalStates { get; } private DeterministicFiniteAutomation(DeterministicState start, HashSet finalStates) { Start = start; FinalStates = finalStates; } private record Pair(HashSet States, DeterministicState State); public static DeterministicFiniteAutomation Create(NondeterministicFiniteAutomation nfa) { Dictionary map = []; HashSet visited = []; Queue queue = []; HashSet finalStates = []; HashSet startClosure = nfa.Start.CalculateEmptyClosure(); DeterministicState start = new(); map.Add(new NondeterministicStateSet(startClosure), start); queue.Enqueue(new Pair(startClosure, start)); while (queue.TryDequeue(out Pair? pair)) { if (pair.States.Any(s => nfa.FinalStates.Contains(s))) { finalStates.Add(pair.State); } Dictionary> next = []; foreach (NondeterministicState state in pair.States) { foreach (KeyValuePair> transaction in state.Transactions.Where(p => !p.Key.IsEmpty)) { HashSet closure = []; foreach (NondeterministicState s in transaction.Value) { closure.UnionWith(s.CalculateEmptyClosure()); } if (next.TryGetValue(transaction.Key.Char, out HashSet? n)) { n.UnionWith(closure); } next.Add(transaction.Key.Char, closure); } } foreach (KeyValuePair> transaction in next) { NondeterministicStateSet set = new(transaction.Value); if (!map.TryGetValue(set, out DeterministicState? nextState)) { nextState = new DeterministicState(); map.Add(set, nextState); } pair.State.Transaction.Add(transaction.Key, nextState); if (visited.Add(nextState)) { queue.Enqueue(new Pair(transaction.Value, nextState)); } } } return new DeterministicFiniteAutomation(start, finalStates); } }