/// <summary>
        /// The constructor transfers all normalized data from the <see cref="IGrammarData" /> to the table generator, but does not yet compute any table-related data
        /// </summary>
        /// <param name="data">The data describing the grammar</param>
        public LalrTableGenerator(IGrammarData data) : base()
        {
            this.symbols = data.Symbols.ToDictionary();
            this.Unknown = this.AssertTerminal(data.Unknown, nameof(this.Unknown));
            this.Eof     = this.AssertTerminal(SymbolId.Eof, nameof(this.Eof));
            this.Init    = this.AssertNonterminal(data.Init, nameof(this.Init));
            this.Start   = this.AssertNonterminal(data.Start, nameof(this.Start));
            var productionKeys          = new HashSet <ProductionKey>();
            var productionRules         = new List <ProductionRule>();
            var productionRulesBySymbol = new Dictionary <SymbolId, List <ProductionRule> >();
            var addProduction           = new Action <SymbolId, SymbolIdSequence>((productionSymbolId, ruleSymbolIds) => {
                if (productionKeys.Add(new ProductionKey(productionSymbolId, ruleSymbolIds)))
                {
                    var productionRule = new ProductionRule(productionRules.Count, productionSymbolId, ruleSymbolIds);
                    productionRules.Add(productionRule);
                    if (!productionRulesBySymbol.TryGetValue(productionSymbolId, out var productions))
                    {
                        productions = new List <ProductionRule>();
                        productionRulesBySymbol.Add(productionSymbolId, productions);
                    }
                    productions.Add(productionRule);
                }
            });

            addProduction(this.Init, new SymbolIdSequence(this.Start.Yield()));
            foreach (var production in data.Productions.Where(p => p.Value != null))
            {
                addProduction(production.Key, production.Value);
            }
            this.ProductionRules         = productionRules;
            this.ProductionRulesBySymbol = productionRulesBySymbol.ToDictionary(p => p.Key, p => (IReadOnlyCollection <ProductionRule>)p.Value);
        }
 protected SemanticParserGrammar(IGrammarData grammarData)
 {
     this.ParserStateMachine = grammarData.ParserStateMachine.Compile();
     this.LexerStateMachine  = grammarData.LexerStateMachine.Compile();
     this.ResolveSymbol      = grammarData.Symbols.CreateGetter();
     this.SymbolsByName      = grammarData.SymbolsByName;
     this.terminalFlags      = grammarData.TerminalFlags;
 }