Exemplo n.º 1
0
        private void Reducer(int lookahead = -1)
        {
            while (!R.IsEmpty)
            {
                GssReducePath <T> path = R.Dequeue();

                int X = path.Rule.OutcomeToken;
                int m = path.Size;

                GssNode <T> u = path.LeftNode;
                State       k = u.State;
                T           z;
                if (m == 0)
                {
                    z = producer.GetDefault(X, (IStackLookback <T>)u);
                }
                else
                {
                    path.CopyDataTo(nodeBuffer);
                    T Λ = producer.CreateBranch(
                        path.Rule,
                        new ArraySlice <T>(nodeBuffer, 0, path.Size),
                        lookback: path.LeftNode);

                    int c = u.Layer;
                    T   currentValue;
                    var Nkey = GetNKey(X, c);
                    if (N.TryGetValue(Nkey, out currentValue))
                    {
                        z = producer.Merge(currentValue, Λ, (IStackLookback <T>)u);
                    }
                    else
                    {
                        z = Λ;
                    }

                    N[Nkey] = z;
                }

                State l;

                var action = ParserAction.Decode(transition(k, X));
                switch (action.Kind)
                {
                case ParserActionKind.Shift:
                    l = action.State;
                    break;

                case ParserActionKind.ShiftReduce:     // Goto-Reduce action
                    PlanShiftReduce(
                        u,
                        X,
                        z,
                        action.ProductionId,
                        action.Size);
                    continue;

                default:
                    throw new InvalidOperationException(
                              "Internal error: Non-term action should be shift or shift-reduce, but got "
                              + Enum.GetName(typeof(ParserActionKind), action.Kind));
                }

                bool stateAlreadyExists = gss.GetFrontNode(l, lookahead) != null;

                // Goto on non-term produced by rule.
                var newLink = gss.Push(u, l, z, lookahead);

                if (lookahead < 0)
                {
                    continue;
                }

                if (stateAlreadyExists)
                {
                    if (newLink != null && m != 0)
                    {
                        GetReductions(l, lookahead);
                        for (int i = 0; i != pendingReductionsCount; ++i)
                        {
                            var red = pendingReductions[i];
                            if (red.Size != 0)
                            {
                                R.Enqueue(newLink, red.Rule, red.Size);
                            }
                        }
                    }
                }
                else
                {
                    var w = gss.GetFrontNode(l, lookahead);

                    GetReductions(l, lookahead);
                    //foreach (var red in reductions)
                    for (int i = 0; i != pendingReductionsCount; ++i)
                    {
                        var red = pendingReductions[i];
                        if (red.Size == 0)
                        {
                            R.Enqueue(w, red.Rule, 0);
                        }
                    }

                    if (m != 0)
                    {
                        for (int i = 0; i != pendingReductionsCount; ++i)
                        {
                            var red = pendingReductions[i];
                            if (red.Size != 0)
                            {
                                R.Enqueue(newLink, red.Rule, red.Size);
                            }
                        }
                    }
                }
            }
        }