namespace CanonSharp.Common.LexicalAnalyzer; public class NondeterministicState : IEquatable { public Guid Id { get; } = Guid.NewGuid(); public Dictionary> Transactions { get; } = []; public bool Equals(NondeterministicState? other) => other is not null && Id.Equals(other.Id); public void AddTransaction(EmptyChar c, NondeterministicState state) { if (Transactions.TryGetValue(c, out HashSet? states)) { states.Add(state); } else { Transactions.Add(c, [state]); } } public override bool Equals(object? obj) => obj is NondeterministicState other && Equals(other); public override int GetHashCode() => Id.GetHashCode(); public HashSet CalculateEmptyClosure() { HashSet result = []; Queue queue = []; queue.Enqueue(this); while (queue.TryDequeue(out NondeterministicState? state)) { result.Add(state); if (!state.Transactions.TryGetValue(EmptyChar.Empty, out HashSet? next)) { continue; } foreach (NondeterministicState s in next.Where(s => !result.Contains(s))) { queue.Enqueue(s); } } return result; } } public class NondeterministicStateSet(HashSet states) : IEquatable { private readonly HashSet _states = states; public bool Equals(NondeterministicStateSet? other) { if (other is null) { return false; } return _states.Count == other._states.Count && _states.All(s => other._states.Contains(s)); } public override bool Equals(object? obj) => obj is NondeterministicStateSet other && Equals(other); public override int GetHashCode() => _states.Aggregate(0, (current, state) => current ^ state.GetHashCode()); } public class NondeterministicFiniteAutomation(NondeterministicState start, HashSet finalStates) { public NondeterministicState Start { get; } = start; public HashSet FinalStates { get; } = finalStates; }