public bool Iterate(Interpreter ii, RepeaterBlueprint bp) { if (Finished) { ii.PopRepeater(); return(false); } // Queue the next iteration on the current state ii.CurrentState.AddPreBlueprint(bp); // Push separator if applicable if (!IsLast && _attribs.Separator != null && _attribs.Separator.Any()) { var sepState = Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.Separator, ii, ii.CurrentState.Output); // Make sure that the repeater is not available to the separator pattern sepState.AddPreBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Pop)); sepState.AddPostBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Push)); ii.PushState(sepState); } // Push postfix if applicable if (_attribs.After != null && _attribs.After.Any()) { ii.PushState(Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.After, ii, ii.CurrentState.Output)); } // Push next item var itemState = Interpreter.State.CreateDerivedDistinct(ii.CurrentState.Reader.Source, _items[_attribs.Sync != null ? _attribs.Sync.NextItem(_items.Length) : ii.RNG.Next(_items.Length)], ii, ii.CurrentState.Output); // Add a blueprint that iterates the repeater just before reading the item. This makes sure that tags like [first] can run before this happens. itemState.AddPostBlueprint(new FunctionBlueprint(ii, _ => { Next(); return(false); })); ii.PushState(itemState); // Push prefix if applicable if (_attribs.Before != null && _attribs.Before.Any()) { ii.PushState(Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.Before, ii, ii.CurrentState.Output)); } return(true); }
public bool Iterate(Interpreter ii, RepeaterBlueprint bp) { while (ii.CurrentRepeater != null && ii.CurrentRepeater.Finished) { ii.PopRepeater(); } if (Finished) { return(false); } // Queue the next iteration on the current state ii.CurrentState.AddPreBlueprint(bp); // Push separator if applicable if (!IsLast && _attribs.Separator != null && _attribs.Separator.Any()) { var sepState = Interpreter.State.CreateSub( ii.CurrentState.Reader.Source, _attribs.Separator, ii, ii.CurrentState.Output); // Make sure that the repeater is not available to the separator pattern sepState.AddPreBlueprint(new DelegateBlueprint(ii, _ => { _allowStats = false; return(false); })); sepState.AddPostBlueprint(new DelegateBlueprint(ii, _ => { _allowStats = true; return(false); })); ii.PushState(sepState); } Interpreter.State afterState = null; // Push postfix if applicable if (_attribs.After != null && _attribs.After.Any()) { ii.PushState(afterState = Interpreter.State.CreateSub( ii.CurrentState.Reader.Source, _attribs.After, ii, ii.CurrentState.Output)); } // Push next item var itemState = Interpreter.State.CreateSub(ii.CurrentState.Reader.Source, _attribs.Sync != null ? _block.Items[_attribs.Sync.NextItem(_block.Items.Length)].Item2 : _block.Items.PickWeighted(ii.RNG, _block.WeightTotal, item => item.Item1).Item2, ii, ii.CurrentState.Output); // Apply the Next() call to the last state in the repeater iteration (afterState ?? itemState).AddPostBlueprint(new DelegateBlueprint(ii, _ => { Next(); return(false); })); ii.PushState(itemState); // Push prefix if applicable if (_attribs.Before != null && _attribs.Before.Any()) { ii.PushState(Interpreter.State.CreateSub( ii.CurrentState.Reader.Source, _attribs.Before, ii, ii.CurrentState.Output)); } return(true); }