示例#1
0
        private IEnumerable <ParseStep> Backtrack(IRegexEngine engine, State initialState, Stack <SavedState> savedStates)
        {
            var savedState = savedStates.Pop();

            engine.State = savedState.State;
            yield return(ParseStep.Backtrack(this, initialState, engine.State));

            yield return(ParseStep.Pass(this, savedState.MatchedText, initialState, engine.State));

            yield return(ParseStep.Break(this));
        }
示例#2
0
        protected override IEnumerable <ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText)
        {
            for (int i = Min; Max == null || i <= Max; i++)
            {
                // We're lazy - we've already matched what was required of us, so declare that we're done.
                yield return(ParseStep.StateSaved(this, initialState, string.Format("Saving state - index {0}", engine.State.Index)));

                yield return(ParseStep.Pass(this, matchedText.ToString(), initialState, engine.State));

                yield return(ParseStep.Break(this));

                // However, if we make it to here, it indicates that we need to match more, in order to (attempt to) get the overall regex to match.
                // According to the parlance of regex people smarter than me, this is a backtrack, even though it's forward.
                yield return(ParseStep.Backtrack(this, initialState, engine.State));

                var childSuccess = false;

                foreach (var result in Child.Parse(engine))
                {
                    if (result.Type == ParseStepType.Break && ReferenceEquals(Child, result.Node))
                    {
                        break;
                    }

                    yield return(result);

                    if (ReferenceEquals(Child, result.Node))
                    {
                        if (result.Type == ParseStepType.Pass)
                        {
                            matchedText.Append(result.MatchedText);
                            childSuccess = true;
                        }
                    }
                }

                if (!childSuccess)
                {
                    break;
                }
            }

            // If we ever make it outside the loop, it means either we were asked to backtrack and our child didn't pass,
            // or, we were asked to backtrack more than the Max allowed matches
            yield return(ParseStep.Fail(this, initialState, engine.State, "Exceeded max allowled quantities"));

            yield return(ParseStep.Break(this));
        }
示例#3
0
        internal override IEnumerable <ParseStep> Parse(IRegexEngine engine)
        {
            yield return(ParseStep.BeginParse(this, engine.State));

            var initialState = engine.State;

            var choiceIndex = 0;

            foreach (var choice in Choices)
            {
                var matchedText  = "";
                var choicePassed = false;

                foreach (var result in choice.Parse(engine))
                {
                    if (ReferenceEquals(choice, result.Node) && result.Type == ParseStepType.Break)
                    {
                        break;
                    }

                    yield return(result);

                    if (ReferenceEquals(choice, result.Node))
                    {
                        if (result.Type == ParseStepType.Pass)
                        {
                            matchedText  = result.MatchedText;
                            choicePassed = true;

                            if (choiceIndex < Choices.Count - 1)
                            {
                                // Only save state if we're not the last choice...
                                yield return(ParseStep.StateSaved(this, initialState, string.Format("Saving state - index {0}", engine.State.Index)));
                            }
                        }
                    }
                }

                if (choicePassed)
                {
                    yield return(ParseStep.Pass(this, matchedText, initialState, engine.State));

                    yield return(ParseStep.Break(this)); // TODO: lazy quantifiers might act in a similar manner as alternation here...

                    yield return(ParseStep.Backtrack(this, initialState, engine.State));
                }
                else
                {
                    if (engine.State.Index != initialState.Index)
                    {
                        yield return(ParseStep.ResetIndex(this, initialState, engine.State));

                        engine.State = initialState;
                    }
                }

                choiceIndex++;
            }

            yield return(ParseStep.Fail(this, initialState, engine.State));

            yield return(ParseStep.Break(this));
        }