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)); }
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)); }
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)); }