예제 #1
0
        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);
        }
예제 #2
0
        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);
        }