예제 #1
0
        public IReceiver <Msg> Next(Msg envelope)
        {
            stateStack.BeginEdit();

            int     id   = envelope.Id;
            MsgData data = envelope.FirstData;

START:
            ParserAction action = LookaheadAction(id);

            switch (action.Kind)
            {
            case ParserActionKind.Fail:
                if (isVerifier)
                {
                    return(null);
                }

                // ReportUnexpectedToken(msg, stateStack.PeekTag());
                return(RecoverFromError(envelope));

            case ParserActionKind.Resolve:
                id = action.RolvedToken;
                while (true)
                {
                    if (data.Token == id)
                    {
                        // Successfully resolved to a particular token
                        goto START;
                    }

                    data = data.Next;
                    if (data == null)
                    {
                        // Desired token was not present in Msg
                        goto case ParserActionKind.Fail;
                    }
                }

            case ParserActionKind.Fork:
            case ParserActionKind.Conflict:
                logging.Write(
                    new LogEntry
                {
                    Severity  = Severity.Error,
                    Location  = envelope.Location,
                    HLocation = envelope.HLocation,
                    Message   = "Hit parser conflict on token " + grammar.SymbolName(envelope.Id)
                });
                return(null);

            case ParserActionKind.Shift:
            {
                stateStack.Push(action.State, producer.CreateLeaf(envelope, data));
                break;
            }

            case ParserActionKind.ShiftReduce:
            {
                TNode value = producer.CreateLeaf(envelope, data);
                do
                {
                    stateStack.Push(-1, value);
                    this.currentRule = grammar.Productions[action.ProductionId];
                    stateStack.Start = stateStack.Count - currentRule.PatternTokens.Length;
                    value            = producer.CreateBranch(
                        currentRule,
                        stateStack.PeekTail(currentRule.PatternTokens.Length),
                        (IStackLookback <TNode>)stateStack);
                    stateStack.Pop(currentRule.PatternTokens.Length);
                    action = ParserAction.Decode(actionTable(stateStack.PeekTag(), currentRule.OutcomeToken));
                }while (action.Kind == ParserActionKind.ShiftReduce);

                if (action.Kind == ParserActionKind.Fail)
                {
                    return(null);
                }

                Debug.Assert(action.Kind == ParserActionKind.Shift);
                stateStack.Push(action.State, value);
                break;
            }

            case ParserActionKind.Accept:
                producer.Result = stateStack.Peek();
                return(FinalReceiver <Msg> .Instance);

            default:
                throw new InvalidOperationException("Internal error: Unsupported parser action");
            }

            stateStack.EndEdit();
            this.priorInput = envelope;
            return(this);
        }
예제 #2
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);
                            }
                        }
                    }
                }
            }
        }