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