protected IEnumerable <TInst> Advance <TInst>(Annotation <TOffset> ann, NullableValue <TOffset>[,] registers, TData output, VariableBindings varBindings, Arc <TData, TOffset> arc, ICollection <FstResult <TData, TOffset> > curResults, int[] priorities, Func <State <TData, TOffset>, Annotation <TOffset>, NullableValue <TOffset> [, ], VariableBindings, bool, TInst> instFactory) { Annotation <TOffset> nextAnn = ann.GetNextDepthFirst(_dir, (cur, next) => !cur.Span.Overlaps(next.Span) && _filter(next)); TOffset nextOffset = nextAnn == _data.Annotations.GetEnd(_dir) ? _data.Annotations.GetLast(_dir, _filter).Span.GetEnd(_dir) : nextAnn.Span.GetStart(_dir); TOffset end = ann.Span.GetEnd(_dir); var newRegisters = (NullableValue <TOffset> [, ])registers.Clone(); ExecuteCommands(newRegisters, arc.Commands, new NullableValue <TOffset>(nextOffset), new NullableValue <TOffset>(end)); CheckAccepting(nextAnn, newRegisters, output, varBindings, arc, curResults, priorities); if (nextAnn != _data.Annotations.GetEnd(_dir)) { var anns = new List <Annotation <TOffset> >(); bool cloneOutputs = false; for (Annotation <TOffset> curAnn = nextAnn; curAnn != _data.Annotations.GetEnd(_dir) && curAnn.Span.GetStart(_dir).Equals(nextOffset); curAnn = curAnn.GetNextDepthFirst(_dir, _filter)) { if (curAnn.Optional) { foreach (TInst ni in Advance(curAnn, registers, output, varBindings, arc, curResults, priorities, instFactory)) { yield return(ni); cloneOutputs = true; } } anns.Add(curAnn); } bool cloneRegisters = false; foreach (Annotation <TOffset> curAnn in anns) { yield return(instFactory(arc.Target, curAnn, cloneRegisters ? (NullableValue <TOffset> [, ])newRegisters.Clone() : newRegisters, cloneOutputs ? varBindings.DeepClone() : varBindings, cloneOutputs)); cloneOutputs = true; cloneRegisters = true; } } else { yield return(instFactory(arc.Target, nextAnn, newRegisters, varBindings, false)); } }
protected IEnumerable <TInst> Initialize(ref int annIndex, Register <TOffset>[,] registers, IList <TagMapCommand> cmds, ISet <int> initAnns) { var insts = new List <TInst>(); TOffset offset = _annotations[annIndex].Span.GetStart(_fst.Direction); if (_startAnchor) { for (int i = annIndex; i < _annotations.Count && _annotations[i].Span.GetStart(_fst.Direction).Equals(offset); i++) { if (_annotations[i].Optional) { int nextIndex = GetNextNonoverlappingAnnotationIndex(i); if (nextIndex != _annotations.Count) { insts.AddRange(Initialize(ref nextIndex, (Register <TOffset> [, ])registers.Clone(), cmds, initAnns)); } } } } ExecuteCommands(registers, cmds, new Register <TOffset>(offset, true), new Register <TOffset>()); for (; annIndex < _annotations.Count && _annotations[annIndex].Span.GetStart(_fst.Direction).Equals(offset); annIndex++) { if (!initAnns.Contains(annIndex)) { TInst inst = GetCachedInstance(); inst.State = _fst.StartState; inst.AnnotationIndex = annIndex; Array.Copy(registers, inst.Registers, registers.Length); if (!_fst.IgnoreVariables) { inst.VariableBindings = _varBindings != null?_varBindings.DeepClone() : new VariableBindings(); } insts.Add(inst); initAnns.Add(annIndex); } } return(insts); }
private void CheckAccepting(Annotation <TOffset> ann, NullableValue <TOffset>[,] registers, TData output, VariableBindings varBindings, Arc <TData, TOffset> arc, ICollection <FstResult <TData, TOffset> > curResults, int[] priorities) { if (arc.Target.IsAccepting && (!_endAnchor || ann == _data.Annotations.GetEnd(_dir))) { var matchRegisters = (NullableValue <TOffset> [, ])registers.Clone(); ExecuteCommands(matchRegisters, arc.Target.Finishers, new NullableValue <TOffset>(), new NullableValue <TOffset>()); if (arc.Target.AcceptInfos.Count > 0) { foreach (AcceptInfo <TData, TOffset> acceptInfo in arc.Target.AcceptInfos) { var candidate = new FstResult <TData, TOffset>(acceptInfo.ID, matchRegisters, output.DeepClone(), varBindings.DeepClone(), acceptInfo.Priority, arc.Target.IsLazy, ann, priorities); if (acceptInfo.Acceptable == null || acceptInfo.Acceptable(_data, candidate)) { curResults.Add(candidate); } } } else { curResults.Add(new FstResult <TData, TOffset>(null, matchRegisters, output.DeepClone(), varBindings.DeepClone(), -1, arc.Target.IsLazy, ann, priorities)); } } }
protected IEnumerable <TInst> Advance(TInst inst, VariableBindings varBindings, Arc <TData, TOffset> arc, ICollection <FstResult <TData, TOffset> > curResults, bool optional = false) { if (inst.Priorities != null) { inst.Priorities.Add(arc.Priority); } int nextIndex = GetNextNonoverlappingAnnotationIndex(inst.AnnotationIndex); TOffset nextOffset; bool nextStart; if (nextIndex < _annotations.Count) { nextOffset = _annotations[nextIndex].Span.GetStart(_fst.Direction); nextStart = true; } else { nextOffset = _data.Annotations.GetLast(_fst.Direction, _fst.Filter).Span.GetEnd(_fst.Direction); nextStart = false; } TOffset end = _annotations[inst.AnnotationIndex].Span.GetEnd(_fst.Direction); if (nextIndex < _annotations.Count) { var anns = new List <int>(); bool cloneOutputs = false; for (int i = nextIndex; i < _annotations.Count && _annotations[i].Span.GetStart(_fst.Direction).Equals(nextOffset); i++) { if (_annotations[i].Optional) { TInst ti = CopyInstance(inst); ti.AnnotationIndex = i; foreach (TInst ni in Advance(ti, varBindings, arc, curResults, true)) { yield return(ni); cloneOutputs = true; } } anns.Add(i); } ExecuteCommands(inst.Registers, arc.Commands, new Register <TOffset>(nextOffset, nextStart), new Register <TOffset>(end, false)); if (!optional || _endAnchor) { CheckAccepting(nextIndex, inst.Registers, inst.Output, varBindings, arc, curResults, inst.Priorities); } inst.State = arc.Target; bool first = true; foreach (int curIndex in anns) { TInst ni = first ? inst : CopyInstance(inst); ni.AnnotationIndex = curIndex; if (varBindings != null) { inst.VariableBindings = cloneOutputs ? varBindings.DeepClone() : varBindings; } yield return(ni); cloneOutputs = true; first = false; } } else { ExecuteCommands(inst.Registers, arc.Commands, new Register <TOffset>(nextOffset, nextStart), new Register <TOffset>(end, false)); CheckAccepting(nextIndex, inst.Registers, inst.Output, varBindings, arc, curResults, inst.Priorities); inst.State = arc.Target; inst.AnnotationIndex = nextIndex; inst.VariableBindings = varBindings; yield return(inst); } }
private void CheckAccepting(int annIndex, Register <TOffset>[,] registers, TData output, VariableBindings varBindings, Arc <TData, TOffset> arc, ICollection <FstResult <TData, TOffset> > curResults, IList <int> priorities) { if (arc.Target.IsAccepting && (!_endAnchor || annIndex == _annotations.Count)) { Annotation <TOffset> ann = annIndex < _annotations.Count ? _annotations[annIndex] : _data.Annotations.GetEnd(_fst.Direction); var matchRegisters = (Register <TOffset> [, ])registers.Clone(); ExecuteCommands(matchRegisters, arc.Target.Finishers, new Register <TOffset>(), new Register <TOffset>()); if (arc.Target.AcceptInfos.Count > 0) { foreach (AcceptInfo <TData, TOffset> acceptInfo in arc.Target.AcceptInfos) { TData resOutput = output; var cloneable = resOutput as IDeepCloneable <TData>; if (cloneable != null) { resOutput = cloneable.DeepClone(); } var candidate = new FstResult <TData, TOffset>(_fst.RegistersEqualityComparer, acceptInfo.ID, matchRegisters, resOutput, varBindings == null ? null : varBindings.DeepClone(), acceptInfo.Priority, arc.Target.IsLazy, ann, priorities == null ? null : priorities.ToArray(), curResults.Count); if (acceptInfo.Acceptable == null || acceptInfo.Acceptable(_data, candidate)) { curResults.Add(candidate); } } } else { TData resOutput = output; var cloneable = resOutput as IDeepCloneable <TData>; if (cloneable != null) { resOutput = cloneable.DeepClone(); } curResults.Add(new FstResult <TData, TOffset>(_fst.RegistersEqualityComparer, null, matchRegisters, resOutput, varBindings == null ? null : varBindings.DeepClone(), -1, arc.Target.IsLazy, ann, priorities == null ? null : priorities.ToArray(), curResults.Count)); } } }