/// <summary> /// Attempts to return a direct link to the specified parent. /// </summary> /// <param name="parent">The parent to look for.</param> /// <returns>The <see cref="Link"/> to the specified parent; /// or <see langword="null"/> when the specified frame is no parent /// of this frame.</returns> public Link TryGetParentLink(Frame parent) { #region Contract Contract.Requires<ArgumentNullException>(parent != null); #endregion return this.Links.FirstOrDefault(l => l.Parent == parent); }
/// <summary> /// Initializes a new instance of the <see cref="ActionState"/> class. /// </summary> /// <param name="stack"></param> /// <param name="state"></param> /// <param name="currentToken"></param> public ActionState(Frame stack, StateRef state, CodePoint currentToken) : this() { #region Contract Contract.Requires<ArgumentNullException>(stack != null); #endregion this.Stack = stack; this.NextState = state; this.CurrentToken = currentToken; }
/// <summary> /// Initializes a new instance of the <see cref="Link"/> class. /// </summary> /// <param name="parent">The parent/destination frame.</param> /// <param name="label">The label of this link.</param> /// <param name="length"></param> public Link(Frame parent, IParseNode label, int length) { #region Contract Contract.Requires<ArgumentNullException>(parent != null); Contract.Requires<ArgumentNullException>(label != null); Contract.Requires<ArgumentOutOfRangeException>(length >= 0); #endregion this.Parent = parent; this.Label = label; this.IsRejected = false; this.Length = length; }
/// <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> /// Gets an active stack frame with the specified state, /// or creates and adds one if there is none. /// </summary> /// <param name="state">The state to look for.</param> /// <returns>A <see cref="Frame"/> with the specified state.</returns> private Frame GetOrCreateActiveFrame(StateRef state) { #region Contract Contract.Ensures(Contract.Result<Frame>() != null); Contract.Ensures(Contract.Result<Frame>().State == state); #endregion var frame = GetActiveFrame(state); if (frame == null) { frame = new Frame(state); this.activeStacks.PushFront(frame); } return frame; }
/// <summary> /// Checks whether the production is a completion production, and if so, checks /// the boundaries for the completion region, the parser location and the cursor /// location, and whether the parser is in completion mode. /// Otherwise, when the production is not a completion production, /// checks whether it is a recover production, or the parser is in fine grained recovery mode. /// </summary> /// <param name="stack"></param> /// <param name="production"></param> /// <returns></returns> private bool RecoverModeOk(Frame stack, ProductionRule production) { if (!production.IsCompletion) return !production.IsRecover || isFineGrainedMode; // TODO: isFineGrainedMode return InCompletionMode(production); }
/// <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); }
/// <summary> /// Reduces the specified stack frame /// </summary> /// <param name="stack"></param> /// <param name="label"></param> public void DoReductions(Frame stack, LabelRef label) { DoLimitedReductions(stack, label, null); }
// TODO: Can currentToken be removed? /// <summary> /// Enqueues the specified stack frame and next state for the shifter. /// </summary> /// <param name="stack">The current stack frame.</param> /// <param name="nextState">The next state.</param> /// <param name="currentToken">The current token.</param> public void EnqueueForShifter(Frame stack, StateRef nextState, CodePoint currentToken) { #region Contract Contract.Requires<ArgumentNullException>(stack != null); Contract.Requires<ArgumentNullException>(nextState != null); #endregion this.forShifter.PushFront(new ActionState(stack, nextState, currentToken)); }
/// <summary> /// Attempts to accept the specified stack frame. /// </summary> /// <param name="stack">The stack frame to accept.</param> /// <returns><see langword="true"/> when the stack frame was accepted; /// otherwise, <see langword="false"/>.</returns> public bool TryAccept(Frame stack) { #region Contract Contract.Requires<ArgumentNullException>(stack != null); #endregion if (stack.IsRejected) return false; this.AcceptingStack = stack; SglrEngine.trace.TraceInformation($"Accepted stack {stack}."); return true; }
/// <summary> /// Executes all actions associated with the current state of the stack frame, /// if the action accepts the current token. /// </summary> /// <param name="frame">The stack frame.</param> private void ExecuteActions(Frame frame) { SglrEngine.trace.TraceInformation("Executing actions for frame {0}.", frame); var state = GetState(frame.State); foreach (var action in state.Actions) { if (!action.Accepts(this.CurrentToken)) continue; foreach (var actionItem in action.Items) { actionItem.Execute(this, frame); } } }