/// <summary> /// Finds all paths from this stack to the root stack that have the specified length /// and go through the specified link. /// </summary> /// <param name="length">The length of the path.</param> /// <param name="link">A link that must be part of the path; or <see langword="null"/>.</param> /// <returns>A collection of paths; or an empty collection when no paths were found.</returns> public IEnumerable<Path> FindPathsToRoot(int length, Link link) { #region Contract Contract.Requires<ArgumentOutOfRangeException>(length >= 0); #endregion return DoGetAllPathsToRoot(null, link, link == null, length, 0); }
/// <summary> /// Initializes a new instance of the <see cref="Path"/> class. /// </summary> /// <param name="next">The next node in the path; or <see langword="null"/>.</param> /// <param name="link">The associated link; or <see langword="null"/>.</param> /// <param name="frame">The associated stack frame.</param> /// <param name="length"></param> public Path(Path next, Link link, Frame frame, int length) { #region Contract Contract.Requires<ArgumentNullException>(frame != null); Contract.Requires<ArgumentOutOfRangeException>(length >= 0); #endregion this.Next = next; this.Link = link; this.Frame = frame; this.Length = length; this.AncestorCount = next != null ? next.AncestorCount + 1 : 0; this.label = this.Link?.Label; }
/// <summary> /// Determines all paths from this frame to the root frame. /// </summary> /// <param name="parent"></param> /// <param name="targetLink">The link to look for, or <see langword="null"/> to find all paths.</param> /// <param name="seen">Whether <paramref name="targetLink"/> has been seen.</param> /// <param name="arity"></param> /// <param name="length"></param> /// <returns></returns> private IEnumerable<Path> DoGetAllPathsToRoot(Path parent, Link targetLink, bool seen, int arity, int length) { // TODO: Understand! if (arity == 0 && seen) { return new[] { new Path(parent, null, this, length) }; } else if (arity > 0) { List<Path> paths = new List<Path>(); foreach (var link in this.Links.Reverse()) { bool seenIt = seen || (link == targetLink); Path n = new Path(parent, link, this, link.Length); paths.AddRange(link.Parent.DoGetAllPathsToRoot(n, targetLink, seenIt, arity - 1, length + link.Length)); } return paths; } else return Enumerable.Empty<Path>(); }
private void ActorOnActiveStacksOverNewLink(Link nl) { // Since DoLimitedReductions() may add new stacks to `activeStacks` // at the beginning, we start at the end. foreach (var st2 in activeStacks.Reverse()) { if (st2.IsRejected || forActor.Contains(st2) || forActorDelayed.Contains(st2)) continue; // Stacknode will find reduction in regular process. foreach (var action in GetState(st2.State).Actions) { if (!action.Accepts(this.CurrentToken)) continue; foreach (var reduce in action.Items.OfType<ReduceActionItem>()) { if (!IsFollowRestricted(reduce.FollowRestriction)) DoLimitedReductions(st2, reduce.Label, nl); } } } }
/// <param name="st0"></param> /// <param name="nextState"></param> /// <param name="label"></param> /// <param name="kids">A list of trees.</param> /// <param name="path"></param> private void Reducer(Frame st0, StateRef nextState, LabelRef label, IReadOnlyList<IParseNode> kids, Path path) { var production = this.parseTable.Labels[label.Index].Production; Contract.Assert(!production.IsRecover); // t := application of a -> A to kids IParseNode t = ApplyProduction(production, kids, /* TODO */ 0, /* TODO */ 0, /* TODO */ false, /* TODO */ false); Frame st1 = GetActiveFrame(nextState); if (st1 != null) { // A stack with state nextState exists. Check for ambiguities. Link nl = st1.TryGetParentLink(st0); if (nl != null) { // There exists a direct link from st1 to st0. // TODO: Add `t` to the possiblities of the ambiguity node at `tree(nl)` if (production.IsReject) nl.Reject(); // TODO: Can't modify a link. //nl.Label = t; } else { // There is no direct link from st1 to st0. nl = new Link(st0, t, path.Length); st1.Links.Add(nl); if (production.IsReject) nl.Reject(); ActorOnActiveStacksOverNewLink(nl); } } else { // Found no existing stack frame with state nextState. st1 = new Frame(nextState); this.activeStacks.PushFront(st1); this.forActorDelayed.PushFront(st1); var nl = new Link(st0, t, path.Length); st1.Links.Add(nl); if (production.IsReject) nl.Reject(); } }
// TODO: Rename to DoReductions? /// <summary> /// /// </summary> /// <param name="stack"></param> /// <param name="label"></param> /// <param name="link">; or <see langword="null"/>.</param> public void DoLimitedReductions(Frame stack, LabelRef label, Link link) { #region Contract Contract.Requires<ArgumentNullException>(stack != null); Contract.Requires<ArgumentNullException>(label != null); #endregion var production = this.parseTable.Labels[label.Index].Production; if (!RecoverModeOk(stack, production)) return; var paths = stack.FindPathsToRoot(production.Arity, link); ReduceAllPaths(label, paths); }