private IRegexFSMTransition <T> GenerateNFATransitionFromRegexPreviousMatch(
            RegexPreviousMatch <T> previousMatch,
            IRegexNFA <T> nfa,
            IRegexNFAState <T> state
            )
        {
            var predicateTransition = new RegexFSMPredicateTransition <T>((sender, args) =>
            {
                if (args.FirstOrDefault() is IRegexFSM <T> fsm)
                {
                    var lastMatch = fsm.Matches?.LastOrDefault();
                    if (lastMatch == null)
                    {
                        // 没有上一个匹配。
                        return(true);
                    }
                    else
                    {
                        // 状态机当前索引与上一个匹配的结尾索引相邻。
                        return(fsm.Index == lastMatch.Index + lastMatch.Length);
                    }
                }
                else
                {
                    return(false);
                }
            });

            nfa.AttachTransition(state, predicateTransition);

            return(predicateTransition);
        }
        private IRegexFSMTransition <T> GenerateNFATransitionFromRegexZeroLengthObject(
            RegexZeroLengthObject <T> zeroLength,
            IRegexNFA <T> nfa,
            IRegexNFAState <T> state
            )
        {
            const string PROGRESS_SERVICE_KEY = "PROGRESS_SERVICE";
            const string PROGRESS_KEY         = "TIMEPOINT";

            IRegexNFAState <T> nextState = state;

            RegexFSMPredicateTransition <T> predicateTransition;

            predicateTransition = new RegexFSMPredicateTransition <T>((sender, args) =>
            {
                if (args.FirstOrDefault() is IRegexFSM <T> fsm)
                {
                    var progressService = fsm.GetService <RegexFSM <T> .ProgressService>();
                    var progress        = progressService.GetProgress();
                    fsm.UserData[PROGRESS_SERVICE_KEY] = progressService;
                    fsm.UserData[PROGRESS_KEY]         = progress;

                    return(true);
                }
                return(false);
            });
            nfa.AttachTransition(nextState, predicateTransition);
            nextState = this.contextInfo.ActivateRegexNFAState();
            nfa.SetTarget(predicateTransition, nextState);

            var transition = this.GenerateNFATransitionFromRegexObject(zeroLength.InnerRegex, nfa, nextState);

            nextState = this.contextInfo.ActivateRegexNFAState();
            nfa.SetTarget(transition, nextState);

            predicateTransition = new RegexFSMPredicateTransition <T>((sender, args) =>
            {
                if (args.FirstOrDefault() is IRegexFSM <T> fsm)
                {
                    var progressService = (RegexFSM <T> .ProgressService)fsm.UserData[PROGRESS_SERVICE_KEY];
                    var progress        = (RegexFSM <T> .ProgressService.Progress)fsm.UserData[PROGRESS_KEY];
                    progressService.SetProgress(progress);

                    return(true);
                }
                return(false);
            });

            return(predicateTransition);
        }
        private IRegexFSMTransition <T> GenerateNFATransitionFromRegexEndBorder(
            RegexEndBorder <T> endBorder,
            IRegexNFA <T> nfa,
            IRegexNFAState <T> state
            )
        {
            var predicateTransition = new RegexFSMPredicateTransition <T>((sender, args) =>
                                                                          (args.FirstOrDefault() is IRegexFSM <T> fsm) &&
                                                                          fsm.Index == fsm.Inputs.Count()
                                                                          );

            nfa.AttachTransition(state, predicateTransition);

            return(predicateTransition);
        }
        protected virtual IRegexFSMTransition <T> GenerateNFATransitionFromRegexGroupReference(
            RegexGroupReference <T> groupReference,
            IRegexNFA <T> nfa,
            IRegexNFAState <T> state
            )
        {
            RegexGroup <T> group;

            if (groupReference.IsDetermined)
            {
                group = groupReference.Group;
            }
            else
            {
                IRegexFSMEpsilonTransition <T> epsilonTransition = this.contextInfo.ActivateRegexFSMEpsilonTransition();

                var groups = this.regexGroups.Where(_group => _group.ID == groupReference.GroupID).ToArray();
                switch (groups.Length)
                {
                case 0:
                    //throw new InvalidOperationException("未找到引用的正则组。");
                    epsilonTransition = this.contextInfo.ActivateRegexFSMEpsilonTransition();
                    nfa.AttachTransition(state, epsilonTransition);
                    return(epsilonTransition);

                case 1:
                    group = groups[0];
                    break;

                default:
                    group = new RegexGroup <T>(
                        groups.Select(_group => _group.InnerRegex).UnionMany()
                        );
                    break;
                    //throw new InvalidOperationException("找到多个重复 ID 的正则组。");
                    //epsilonTransition = this.contextInfo.ActivateRegexNFAEpsilonTransition();
                    //nfa.AttachTransition(state, epsilonTransition);
                    //return epsilonTransition;
                }
            }

            IRegexNFAState <T> nextState = state;

            var lastCaptureReferenceTransition = new RegexFSMLastCaptureReferenceTransition <T>(group, group.ID, (sender, readerSource, handler, args) =>
            {
                if (args.FirstOrDefault() is IRegexFSM <T> fsm)
                {
                    if (fsm.TryGetLastCapture(sender.IDToken, sender.ID, out int start, out int length))
                    {
                        var progressService = fsm.GetService <RegexFSM <T> .ProgressService>();
                        var progress        = progressService.GetProgress();

                        foreach (var t in fsm.Inputs.Skip(start).Take(length))
                        {
                            if (!(readerSource.HasNext() && EqualityComparer <T> .Default.Equals(readerSource.Read(), t)))
                            {
                                progressService.SetProgress(progress);
                                return(false);
                            }
                        }

                        return(true);
                    }
                }