public FirstSetTable GetFirstSets(BNF bnf)
        {
            FirstSetTable sets = new FirstSetTable();

            foreach (var production in bnf)
            {
                GetSymbolFirstSet(production.Key, bnf, sets);
            }
            return(sets);
        }
 HashSet <string> GetSymbolFirstSet(string symbol, BNF bnf, FirstSetTable firstSets)
 {
     if (firstSets.SymbolSets.ContainsKey(symbol))
     {
         return(firstSets.SymbolSets[symbol]);
     }
     else
     {
         if (IsTerminal(symbol, bnf))
         {
             HashSet <string> set = new HashSet <string>()
             {
                 symbol
             };
             firstSets.SymbolSets.Add(symbol, set);
             return(set);
         }
         else
         {
             HashSet <string> set = new HashSet <string>();
             var expansions       = bnf[symbol];
             for (int index = 0; index < expansions.Count; index++)
             {
                 var expansionSet = GetExpansionFirstSet(symbol, index, bnf, firstSets);
                 if (expansions[index].Count == 1 && expansions[index][0] == _emptySymbol)
                 {
                     set.Add(_emptySymbol);
                 }
                 else
                 {
                     set.UnionWith(expansionSet);
                 }
             }
             firstSets.SymbolSets.Add(symbol, set);
             return(set);
         }
     }
 }
 HashSet <string> GetExpansionFirstSet(string production, int expansionIndex, BNF bnf, FirstSetTable firstSets)
 {
     if (firstSets.ExpansionSets.ContainsKey((production, expansionIndex)))
     {
         return(firstSets.ExpansionSets[(production, expansionIndex)]);
     }