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); }
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); } } } } } }