private void addClosures(SingleState <SYMBOL_ENUM, TREE_NODE> sourceState, Productions <SYMBOL_ENUM, TREE_NODE> productions, int lookaheadWidth) { if (!sourceState.HasIncomingSymbol) { return; } // find productions for that symbol foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.FilterByLhs(sourceState.IncomingSymbol)) { SingleState <SYMBOL_ENUM, TREE_NODE> existing; // getting "impostor" object just for sake of FAST comparison (no memory allocations) if (items.TryGetValue(SingleState <SYMBOL_ENUM, TREE_NODE> .CreateClosureComparisonStateFrom(prod), out existing)) // [@STATE_EQ] { // switching closure links to existing state existing.AddClosureParent(sourceState); } else { // creating real state object var state = SingleState <SYMBOL_ENUM, TREE_NODE> .CreateClosureStateFrom(InternalId, items.Count, sourceState, prod); items.Add(state); addClosures(state, productions, lookaheadWidth); // recursive call } } }