public FirstSets <SYMBOL_ENUM> ComputeFirstSets(ref Dictionary <Production <SYMBOL_ENUM, TREE_NODE>, Dictionary <int, SymbolChunkSet <SYMBOL_ENUM> > > precomputedRhsFirsts)
        {
            initFirstSets();

            while (expandFirstSets())
            {
                ;
            }

            precomputedRhsFirsts = new Dictionary <Production <SYMBOL_ENUM, TREE_NODE>, Dictionary <int, SymbolChunkSet <SYMBOL_ENUM> > >();

            foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.ProductionsWithNoErrorSymbol())
            {
                var rhs_firsts = new Dictionary <int, SymbolChunkSet <SYMBOL_ENUM> >();
                // =, because we could read all symbols
                for (int i = 0; i <= prod.RhsSymbols.Count; ++i)
                {
                    rhs_firsts.Add(i, firstSets.GetFirstsOf(prod.RhsSymbols.Skip(i), terminals, syntaxErrorSymbol, lookaheadWidth));
                }
                precomputedRhsFirsts.Add(prod, rhs_firsts);
            }

            return(firstSets);
        }
        private void bootstrapFromFirstSets(SYMBOL_ENUM symbol)
        {
            SymbolChunkSet <SYMBOL_ENUM> follow_set = followSets[symbol];

            // in all RHS of productions find our symbol
            foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.ProductionsWithNoErrorSymbol())
            {
                for (int i = 0; i < prod.RhsSymbols.Count(); ++i)
                {
                    // we are above our symbol on RHS of the production
                    if (prod.RhsSymbols[i].Equals(symbol))
                    {
                        // get first set of what can happen AFTER our symbol -- this will be follow set by definition
                        SymbolChunkSet <SYMBOL_ENUM> chunk_set
                            = firstSets.GetFirstsOf(prod.RhsSymbols.Skip(i + 1), terminals, syntaxErrorSymbol, lookaheadWidth);

                        {
                            SymbolChunkSet <SYMBOL_ENUM> tmp = new SymbolChunkSet <SYMBOL_ENUM>();

                            // add LHS non-terminal at the end of too short chunks as generator
                            // because what follows LHS also follows given symbol
                            foreach (SymbolChunk <SYMBOL_ENUM> chunk in chunk_set.Chunks)
                            {
                                if (chunk.Count < lookaheadWidth)
                                {
                                    tmp.Add(chunk.Append(prod.LhsNonTerminal));
                                }
                                else
                                {
                                    tmp.Add(chunk);
                                }
                            }

                            chunk_set = tmp;
                        }

                        if (chunk_set.IsEmpty)
                        {
                            chunk_set.Add(SymbolChunk.Create(prod.LhsNonTerminal));
                        }

                        follow_set.Add(chunk_set);
                    }
                }
            }
        }
        private void bootstrapFromFirstSets(SYMBOL_ENUM symbol)
        {
            SymbolChunkSet <SYMBOL_ENUM> current_set = horizonSets[symbol];

            // in all RHS of productions find our symbol
            foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.Entries)
            {
                if (symbol.Equals(prod.LhsNonTerminal) || coverSets[symbol].Contains(SymbolChunk.Create(prod.LhsNonTerminal)))
                {
                    continue;
                }

                for (int i = 0; i < prod.RhsSymbols.Count(); ++i)
                {
                    // we are on our symbol on RHS of the production
                    if (prod.RhsSymbols[i].Equals(symbol))
                    {
                        // get first set of what can happen AFTER our symbol -- this will be our horizon
                        SymbolChunkSet <SYMBOL_ENUM> src_set = firstSets.GetFirstsOf(prod.RhsSymbols.Skip(i + 1), terminals, syntaxErrorSymbol, lookaheadWidth);

                        SymbolChunkSet <SYMBOL_ENUM> chunk_set = new SymbolChunkSet <SYMBOL_ENUM>();
                        // add follow set at the end of too short chunks
                        foreach (SymbolChunk <SYMBOL_ENUM> chunk in src_set.Chunks)
                        {
                            if (chunk.Count < lookaheadWidth)
                            {
                                chunk_set.Add(SymbolChunkSet.MultiConcat(chunk, followSets[prod.LhsNonTerminal], lookaheadWidth));
                            }
                            else
                            {
                                chunk_set.Add(chunk);
                            }
                        }


                        if (chunk_set.IsEmpty)
                        {
                            chunk_set.Add(followSets[prod.LhsNonTerminal]);
                        }

                        current_set.Add(chunk_set);
                    }
                }
            }
        }