private Msg InvokeReduceAction(GssReducePath path, Msg currentItem)
        {
            var rule = path.Rule;
            // TODO: Fix inconsistency? Size of "modified reduction" path can be shorter.
            var args = new Msg[rule.Parts.Length];
            var node = path.First;
            int i    = 0;
            var loc  = Loc.Unknown;

            if (node == null)
            {
                loc = new Loc(currentItem.Location.FilePath, currentItem.Location.Position, 0);
            }
            else
            {
                do
                {
                    var item = node.Link.Item;
                    args[i] = item;
                    loc    += item.Location;

                    node = node.Next;
                    ++i;
                }while (node != null);
            }

            var value = grammarAction(rule, args, 0, context, path.LeftmostStateNode);

            return(new Msg(rule.Left, value, loc));
        }
        private void ReduceViaPath(GssReducePath path, Msg item)
        {
            int          N       = path.Rule.Left;
            GssStateNode leftSib = path.LeftmostStateNode;
            State        k       = leftSib.State;

            // TODO: Apply 'Duplicate' to all path semantic values
            Msg newItem  = InvokeReduceAction(path, item);
            int newState = NonTermGoTo(k, N);
            var rightSib = gss.FindTopmost(newState);

            if (rightSib != null)
            {
                var link = gss.GetLink(rightSib, leftSib);
                if (link != null)
                {
                    link.Item = MergeValues(newState, link.Item, newItem);
                }
                else
                {
                    link = gss.AddLink(rightSib, leftSib, newItem);
                    EnqueueLimitedReductions(item.Id, link);
                }
            }
            else
            {
                rightSib = gss.AddTopmost(newState);
                var link = gss.AddLink(rightSib, leftSib, newItem);
                EnqueueLimitedReductions(item.Id, link);
            }
        }
Beispiel #3
0
        public void Enqueue(GssLink <T> rightLink, Production rule, int size)
        {
            Debug.Assert(rightLink != null);

            int tail = size == 0 ? 0 : 1;

            GssReducePath <T> .GetAll(
                rightLink.LeftNode,
                size - tail,
                tail,
                rule,
                rightLink,
                InternalEnqueue);
        }
Beispiel #4
0
        private bool GoesBefore(GssReducePath <T> x, GssReducePath <T> y)
        {
            int diff = x.LeftNode.Layer - y.LeftNode.Layer;

            if (diff > 0)
            {
                return(true);
            }
            else if (diff < 0)
            {
                return(false);
            }

            return(tokenComplexity[x.Rule.OutcomeToken] < tokenComplexity[y.Rule.OutcomeToken]);
        }
Beispiel #5
0
        private void InternalEnqueue(GssReducePath <T> path)
        {
            int index = paths.Count;
            var node  = paths.First;

            while (node != null)
            {
                if (GoesBefore(path, node.Value))
                {
                    paths.AddBefore(node, path);
                    return;
                }

                node = node.Next;
            }

            paths.AddLast(path);
        }
Beispiel #6
0
        public void Enqueue(GssNode <T> rightNode, Production rule, int size)
        {
            if (size == 0)
            {
                GssReducePath <T> .GetAll(rightNode, 0, 0, rule, null, InternalEnqueue);
            }
            else
            {
                var link = rightNode.FirstLink;

                while (link != null)
                {
                    Enqueue(link, rule, size);

                    link = link.NextLink;
                }
            }
        }
        public GssReducePath <T> Dequeue()
        {
            if (pendingPaths.Count == 0)
            {
                var r    = reductions.Dequeue();
                var size = r.Size;

                int tail = (r.Size != 0 && r.RightLink != null) ? 1 : 0;
                GssReducePath <T> .GetAll(
                    r.RightNode,
                    size - tail,
                    tail,
                    r.Rule,
                    r.RightLink,
                    pendingPaths.Enqueue);
            }

            return(pendingPaths.Dequeue());
        }
Beispiel #8
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);
                            }
                        }
                    }
                }
            }
        }