CanonSharp/CanonSharp.Common/LexicalAnalyzer/NondeterministicFiniteAutomation.cs
2024-07-27 14:56:28 +08:00

77 lines
2.3 KiB
C#

namespace CanonSharp.Common.LexicalAnalyzer;
public class NondeterministicState : IEquatable<NondeterministicState>
{
public Guid Id { get; } = Guid.NewGuid();
public Dictionary<EmptyChar, HashSet<NondeterministicState>> 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<NondeterministicState>? 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<NondeterministicState> CalculateEmptyClosure()
{
HashSet<NondeterministicState> result = [];
Queue<NondeterministicState> queue = [];
queue.Enqueue(this);
while (queue.TryDequeue(out NondeterministicState? state))
{
result.Add(state);
if (!state.Transactions.TryGetValue(EmptyChar.Empty, out HashSet<NondeterministicState>? next))
{
continue;
}
foreach (NondeterministicState s in next.Where(s => !result.Contains(s)))
{
queue.Enqueue(s);
}
}
return result;
}
}
public class NondeterministicStateSet(HashSet<NondeterministicState> states) : IEquatable<NondeterministicStateSet>
{
private readonly HashSet<NondeterministicState> _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<NondeterministicState> finalStates)
{
public NondeterministicState Start { get; } = start;
public HashSet<NondeterministicState> FinalStates { get; } = finalStates;
}