public Dfa.DfaTable BuildDfa() { Nfa.Nfa nfa = nfaWorker.Compile(); // -- from here build DFA out of NFA List <DfaNode> done = new List <DfaNode>(); List <Link> to_add = (new[] { new Link(null, 0, new DfaNode(nfa.StartNode)) }).ToList(); while (to_add.Any()) { // build closures for incoming nodes to_add.Select(it => it.Target).ForEach(it => it.BuildClosure()); List <Link> new_links = new List <Link>(); foreach (Link link in to_add) { // check if we already have that DFA node DfaNode existing = done.SingleOrDefault(it => it.SameNfaCore(link.Target)); if (existing == null) { done.Add(link.Target); if (link.Source != null) { link.Source.ConnectTo(link.Edge, link.Target); } new_links.AddRange(link.Target.ComputeLinks()); } else { link.Source.ConnectTo(link.Edge, existing); } } to_add = new_links; } done.ZipWithIndex().ForEach(it => it.Item1.Index = it.Item2); var dfa = new Dfa.DfaTable(done.Count); foreach (DfaNode node in done) { dfa.SetAccepting(node.Index, node.AcceptingValues); node.CreateTransitions(dfa); } return(dfa); }