/// <summary>
        /// Compute the collection of Lr states by recursively applying productions from root state until no new states are added.
        /// </summary>
        private void CreateLrItemsAndStates()
        {
            var rootProduction = Grammar.Productions[0];
            var rootItem       = LrItems.GetOrAdd(rootProduction, 0, 1);
            var rootState      = LrStates.GetOrAdd(ComputeClosure(new SortedSet <LrItem> {
                rootItem
            }));

            var open = new Queue <LrState>();

            open.Enqueue(rootState);

            while (open.Count > 0)
            {
                var state           = open.Dequeue();
                var gotos           = new LrState[Grammar.Tokens.Length];
                var gotoPrecedences = new ushort?[Grammar.Tokens.Length];
                foreach (var token in Enumerable.Range(0, Grammar.Tokens.Length))
                {
                    bool   bAdded;
                    ushort?precedence;
                    var    gotoState = GotoLr(state, token, out bAdded, out precedence);
                    gotos[token]           = gotoState;
                    gotoPrecedences[token] = precedence;
                    if (bAdded)
                    {
                        open.Enqueue(gotoState);
                    }
                }
                state.Gotos           = gotos;
                state.GotoPrecedences = gotoPrecedences;
            }
        }
        /// <summary>
        /// Given the set of items in state, calculate for each token the closed set of items that can result from processing said token.
        /// </summary>
        /// <param name="state">The staring state.</param>
        /// <param name="token">The token to process.</param>
        /// <param name="bAdded">Return true if new state was added.</param>
        /// <param name="precedence">Return the precedence of the goto.</param>
        /// <returns>Returns the resulting LrState or null of unable to process the specified token on any of the state items.</returns>
        private LrState GotoLr(LrState state, int token, out bool bAdded, out ushort?precedence)
        {
            ushort?prec        = null;
            var    targetItems = new SortedSet <LrItem>();

            foreach (var item in state.Items)
            {
                if (item.CanIncrement && (item.NextToken == token))
                {
                    var newItem = LrItems.GetOrAdd(item.Production, item.ProductionProgress + 1, item.LookAheadSymbol);
                    targetItems.Add(newItem);
                    if (!prec.HasValue)
                    {
                        prec = item.Production.Precedence;
                    }
                    else if (item.Production.Precedence > prec)
                    {
                        prec = item.Production.Precedence;
                    }
                }
            }
            if (targetItems.Count == 0)
            {
                bAdded     = false;
                precedence = null;
                return(null);
            }
            var targetItemsWithClosure = ComputeClosure(targetItems);
            var targetState            = LrStates.GetOrAdd(targetItemsWithClosure, out bAdded);

            precedence = prec;
            return(targetState);
        }