private void Shifter(Msg item)
        {
            var prevTops = gss.Topmost.ToArray();

            gss.PushLayer();

            foreach (var current in prevTops)
            {
                int?shift;
                if (GetParserActions(current.State, item.Id, out shift, null) && shift.HasValue)
                {
                    var rightSib = gss.FindTopmost(shift.Value);
                    if (rightSib != null)
                    {
                        gss.AddLink(rightSib, current, item);
                    }
                    else
                    {
                        rightSib = gss.AddTopmost(shift.Value);
                        gss.AddLink(rightSib, current, item);
                    }
                }
            }
        }
        public IReceiver <Msg> Next(Msg envelope)
        {
            gss.BeginEdit();

            N.Clear();

            var     front = gss.FrontArray;
            MsgData data  = envelope.FirstData;

            do
            {
                int lookahead = data.Token;

                Actor(lookahead);
                Reducer(lookahead);

                if (accepted)
                {
                    int count = gss.Count;
                    for (int i = 0; i != count; ++i)
                    {
                        var node = front[i];
                        if (IsAccepting(node.State))
                        {
                            producer.Result = node.FirstLink.Label;
                            break;
                        }
                    }
                }

                var termValue = producer.CreateLeaf(envelope, data);
                N[GetNKey(lookahead, gss.CurrentLayer + 1)] = termValue;

                for (int i = 0; i != gss.Count; ++i)
                {
                    var frontNode = front[i];

                    // Plan shift
                    var shift = GetShift(frontNode.State, lookahead);
                    if (shift >= 0)
                    {
                        Q.Enqueue(new PendingShift(frontNode, shift, lookahead));
                    }

                    // Shift and plan reduce
                    var action = GetShiftReduce(frontNode.State, lookahead);
                    if (action.Kind == ParserActionKind.ShiftReduce)
                    {
                        PlanShiftReduce(
                            frontNode,
                            lookahead,
                            termValue,
                            action.ProductionId,
                            action.Size);
                    }
                }

                data = data.Next;
            }while (data != null);

            gss.PushLayer();
            Shifter();

            // Run reducer again to complete
            // shift-reduce and goto-reduce actions.
            Reducer();

#if DIAGNOSTICS
            if (!isVerifier)
            {
                using (var graphView = new GvGraphView("GlrState" + gss.CurrentLayer + ".gv"))
                {
                    gss.WriteGraph(graphView, grammar, stateToPriorToken);
                }
            }
#endif

            if (gss.IsEmpty)
            {
                if (accepted)
                {
                    return(FinalReceiver <Msg> .Instance);
                }

                if (isVerifier)
                {
                    return(null);
                }

                gss.Undo(0); // restore state before the current input token

                {
                    var message = new StringBuilder();
                    message
                    .Append("Unexpected token ")
                    .Append(grammar.SymbolName(envelope.Id))
                    .Append(" in state stacks: {");
                    bool firstStack = true;
                    for (int i = 0; i != gss.Count; ++i)
                    {
                        var node = gss.FrontArray[i];

                        if (firstStack)
                        {
                            firstStack = false;
                        }
                        else
                        {
                            message.Append(", ");
                        }



                        message.Append("[");
                        var  n          = node;
                        bool firstState = true;
                        while (true)
                        {
                            if (firstState)
                            {
                                firstState = false;
                            }
                            else
                            {
                                message.Append(", ");
                            }

                            message.Append(n.State);
                            if (n.State == 0)
                            {
                                break;
                            }

                            n = n.FirstLink.LeftNode;
                        }

                        message.Append("]");
                    }

                    message.Append("}");

                    logging.Write(
                        new LogEntry
                    {
                        Severity  = Severity.Verbose,
                        Location  = envelope.Location,
                        HLocation = envelope.HLocation,
                        Message   = message.ToString()
                    });
                }

                return(RecoverFromError(envelope));
            }

            gss.EndEdit();
            this.priorInput = envelope;
            return(this);
        }