internal override sealed IEnumerable<ParseStep> Parse(IRegexEngine engine) { yield return ParseStep.BeginParse(this, engine.State); var initialState = engine.State; var matchedText = new StringBuilder(); foreach (var parseStep in ParseRequired(engine, matchedText, initialState)) { yield return parseStep; } // If min equals max, we're done. if (Min == Max) { yield return ParseStep.Pass(this, matchedText.ToString(), initialState, engine.State); yield return ParseStep.Break(this); yield break; } foreach (var specific in ParseSpecific(engine, initialState, matchedText)) { if (ReferenceEquals(specific.Node, this) && specific.Type == ParseStepType.Break) { yield return ParseStep.Break(this); } else { yield return specific; } } }
public void ViewManagerCreateView() { #region Mock intialization DynamicMock useCase = new DynamicMock(typeof(IUseCase)); DynamicMock engine = new DynamicMock(typeof(IRegexEngine)); DynamicMock view = new DynamicMock(typeof(IRegexView)); IRegexView viewMockInstance = (IRegexView)view.MockInstance; IUseCase useCaseMockInstance = (IUseCase)useCase.MockInstance; IRegexEngine engineMockInstance = (IRegexEngine)engine.MockInstance; #endregion useCase.ExpectAndReturn("CreateNewView", viewMockInstance); useCase.ExpectAndReturn("CreateNewEngine", engineMockInstance); engine.Expect("AttachView", withSameObjectAs(viewMockInstance)); view.Expect("Init", withSameObjectAs(engineMockInstance)); ViewManager factory = new ViewManager(); IRegexView newView = factory.CreateView(useCaseMockInstance); useCase.Verify(); engine.Verify(); view.Verify(); Assert.AreSame(newView, viewMockInstance, "Returned view is not the same instance as expected"); }
/// <summary> /// Parse the required quantities - we must match at least the minimum. /// </summary> private IEnumerable <ParseStep> ParseRequired(IRegexEngine engine, StringBuilder matchedText, State initialState) { for (int i = 0; i < Min; i++) { 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); } else if (result.Type == ParseStepType.Fail) { yield return(ParseStep.Fail( this, initialState, engine.State, string.Format("Greedy quantifier was required to match at least {0} times, but matched {1} times", Min, i))); yield return(ParseStep.Break(this)); } } } } }
internal override IEnumerable <ParseStep> Parse(IRegexEngine engine) { yield return(ParseStep.BeginParse(this, engine.State)); if (engine.State.Index >= engine.Input.Length) { yield return(ParseStep.Fail(this, engine.State, engine.State)); yield return(ParseStep.Break(this)); yield break; } if (Matches(engine.Input[engine.State.Index])) { var match = engine.Input.Substring(engine.State.Index, 1); var initialState = engine.State; engine.State = engine.State.Advance(); yield return(ParseStep.Pass(this, match, initialState, engine.State)); yield return(ParseStep.AdvanceIndex(this, engine.State)); yield return(ParseStep.Break(this)); } else { yield return(ParseStep.Fail(this, engine.State, engine.State)); yield return(ParseStep.Break(this)); } }
/// <summary> /// Parse the required quantities - we must match at least the minimum. /// </summary> private IEnumerable<ParseStep> ParseRequired(IRegexEngine engine, StringBuilder matchedText, State initialState) { for (int i = 0; i < Min; i++) { 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); } else if (result.Type == ParseStepType.Fail) { yield return ParseStep.Fail( this, initialState, engine.State, string.Format("Greedy quantifier was required to match at least {0} times, but matched {1} times", Min, i)); yield return ParseStep.Break(this); } } } } }
internal override sealed IEnumerable <ParseStep> Parse(IRegexEngine engine) { yield return(ParseStep.BeginParse(this, engine.State)); var initialState = engine.State; var matchedText = new StringBuilder(); foreach (var parseStep in ParseRequired(engine, matchedText, initialState)) { yield return(parseStep); } // If min equals max, we're done. if (Min == Max) { yield return(ParseStep.Pass(this, matchedText.ToString(), initialState, engine.State)); yield return(ParseStep.Break(this)); yield break; } foreach (var specific in ParseSpecific(engine, initialState, matchedText)) { if (ReferenceEquals(specific.Node, this) && specific.Type == ParseStepType.Break) { yield return(ParseStep.Break(this)); } else { yield return(specific); } } }
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) { engine.State = initialState; yield return ParseStep.ResetIndex(this, initialState); } } choiceIndex++; } yield return ParseStep.Fail(this, initialState, engine.State); yield return ParseStep.Break(this); }
protected override IEnumerable<ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState) { var matchedText = engine.Input.Substring(initialState.Index, engine.State.Index - initialState.Index); engine.AddCapture(Number, initialState.Index, matchedText); yield return ParseStep.Capture(this, matchedText, Number, initialState, engine.State); yield return ParseStep.Pass(this, matchedText, initialState, engine.State); yield return ParseStep.Break(this); }
protected override IEnumerable <ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState) { var matchedText = engine.Input.Substring(initialState.Index, engine.State.Index - initialState.Index); yield return(ParseStep.Pass(this, matchedText, initialState, engine.State)); yield return(ParseStep.Break(this)); }
public IRegexEngine GetRegexEngine() { if (regexEngine == null) { regexEngine = new MSRegexCompiledEngine(); } return(regexEngine); }
void SetEngineOption(IRegexEngine engine) { var cbxitem = cbxEngine.Items.Cast <ComboBoxItem>( ).Single(i => i.Tag.ToString( ) == engine.Id); cbxEngine.SelectedItem = cbxitem; UpdateOptions(engine); }
public IRegexView CreateView(IUseCase useCaseInstance) { IRegexView newView = useCaseInstance.CreateNewView(); IRegexEngine engine = useCaseInstance.CreateNewEngine(); engine.AttachView(newView); newView.Init(engine); return(newView); }
protected override IEnumerable <ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance) { yield return(ParseStep.Fail(this, initialState, currentState)); if (!skipAdvance) { engine.State = initialState.Advance(); yield return(ParseStep.AdvanceIndex(this, engine.State)); } }
protected override IEnumerable<ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance) { yield return ParseStep.Fail(this, initialState, currentState); if (!skipAdvance) { engine.State = engine.State.Advance(); yield return ParseStep.AdvanceIndex(this, engine.State); } }
// -------------------- private void LoadTabData(TabData tabData) { Debug.Assert(!IsInChange); IsInChange = true; try { IRegexEngine engine = RegexEngines.SingleOrDefault(n => n.Id == tabData.ActiveRegexEngineId); if (engine == null) { engine = DefaultRegexEngine; } CurrentRegexEngine = engine; SetEngineOption(engine); // set options of active and inactive engines foreach (var eng in RegexEngines) { string[] options = null; if (tabData.AllRegexOptions?.TryGetValue(eng.Id, out options) == true) { eng.ImportOptions(options); } } cbShowFirstOnly.IsChecked = tabData.ShowFirstMatchOnly; cbShowSucceededGroupsOnly.IsChecked = tabData.ShowSucceededGroupsOnly; cbShowCaptures.IsChecked = tabData.ShowCaptures; cbShowWhitespaces.IsChecked = tabData.ShowWhiteSpaces; foreach (var item in cbxEol.Items.Cast <ComboBoxItem>( )) { item.IsSelected = (string)item.Tag == tabData.Eol; } if (cbxEol.SelectedItem == null) { ((ComboBoxItem)cbxEol.Items[0]).IsSelected = true; } ucPattern.ShowWhiteSpaces(tabData.ShowWhiteSpaces); ucText.ShowWhiteSpaces(tabData.ShowWhiteSpaces); ucPattern.SetFocus( ); ucPattern.SetRegexOptions(CurrentRegexEngine, tabData.Eol); ucPattern.SetText(tabData.Pattern); ucText.SetText(tabData.Text); } finally { IsInChange = false; } }
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)); }
internal override IEnumerable <ParseStep> Parse(IRegexEngine engine) { yield return(ParseStep.BeginParse(this, engine.State)); var initialState = engine.State; var capture = engine.GetCaptures(Number).FirstOrDefault(); if (capture == null || string.IsNullOrEmpty(capture.Value)) { yield return(ParseStep.Fail(this, initialState, engine.State, "No backreference value found")); yield return(ParseStep.Break(this)); } else { var literals = capture.Value.Select((c, i) => new CharacterLiteral(c, _ignoreCase, capture.Index + i, new string(new[] { c }))); foreach (var literal in literals) { var success = false; foreach (var result in literal.Parse(engine)) { if (result.Type == ParseStepType.Break) { break; } if (result.Type == ParseStepType.Pass) { success = true; } } if (!success) { yield return(ParseStep.Fail(this, initialState, engine.State)); yield return(ParseStep.Break(this)); yield break; } } yield return(ParseStep.Pass(this, capture.Value, initialState, engine.State)); yield return(ParseStep.Break(this)); } }
internal override sealed IEnumerable <ParseStep> Parse(IRegexEngine engine) { yield return(ParseStep.BeginParse(this, engine.State)); if (Matches(engine.State)) { yield return(ParseStep.Pass(this, "", engine.State, engine.State)); } else { yield return(ParseStep.Fail(this, engine.State, engine.State)); } yield return(ParseStep.Break(this)); }
internal override sealed IEnumerable<ParseStep> Parse(IRegexEngine engine) { yield return ParseStep.BeginParse(this, engine.State); if (Matches(engine.State)) { yield return ParseStep.Pass(this, "", engine.State, engine.State); } else { yield return ParseStep.Fail(this, engine.State, 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)); }
public void SetRegexOptions(IRegexEngine engine, string eol) { StopAll( ); lock (this) { mRegexEngine = engine; mEol = eol; } if (IsLoaded) { RecolouringLoop.SendWaitAndExecute( ); HighlightingLoop.SendWaitAndExecute( ); } }
private void cbxEngine_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!IsFullyLoaded) { return; } if (IsInChange) { return; } CurrentRegexEngine = RegexEngines.Single(n => n.Id == ((ComboBoxItem)e.AddedItems[0]).Tag.ToString( )); UpdateOptions(CurrentRegexEngine); HandleOptionsChange(preferImmediateReaction: true); }
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); }
void UpdateOptions(IRegexEngine engine) { pnlRegexOptions.Children.Clear( ); pnlRegexOptions.Children.Add(engine.GetOptionsControl( )); RegexEngineCapabilityEnum caps = engine.Capabilities; bool captures_supported = !caps.HasFlag(RegexEngineCapabilityEnum.NoCaptures); // showing unchecked checkbox when disabled cbShowCaptures.IsEnabled = captures_supported; cbShowCaptures.Visibility = captures_supported ? Visibility.Visible : Visibility.Collapsed; cbShowCapturesDisabledUnchecked.Visibility = !captures_supported ? Visibility.Visible : Visibility.Collapsed; // inelegant, but works string capture_note = engine.NoteForCaptures; runShowCapturesNote.Text = !string.IsNullOrWhiteSpace(capture_note) ? " (" + capture_note + ")" : string.Empty; }
internal override IEnumerable<ParseStep> Parse(IRegexEngine engine) { yield return ParseStep.BeginParse(this, engine.State); var initialState = engine.State; var capture = engine.GetCaptures(Number).FirstOrDefault(); if (capture == null || string.IsNullOrEmpty(capture.Value)) { yield return ParseStep.Fail(this, initialState, engine.State, "No backreference value found"); yield return ParseStep.Break(this); } else { var literals = capture.Value.Select((c, i) => new CharacterLiteral(c, _ignoreCase, capture.Index + i, new string(new[] { c }))); foreach (var literal in literals) { var success = false; foreach (var result in literal.Parse(engine)) { if (result.Type == ParseStepType.Break) { break; } if (result.Type == ParseStepType.Pass) { success = true; } } if (!success) { yield return ParseStep.Fail(this, initialState, engine.State); yield return ParseStep.Break(this); yield break; } } yield return ParseStep.Pass(this, capture.Value, initialState, engine.State); yield return ParseStep.Break(this); } }
private void Engine_OptionsChanged(IRegexEngine sender, RegexEngineOptionsChangedArgs args) { if (!IsFullyLoaded) { return; } if (IsInChange) { return; } if (object.ReferenceEquals(sender, CurrentRegexEngine)) { HandleOptionsChange(preferImmediateReaction: args?.PreferImmediateReaction == true); } else { // inactive engine; ignore } }
protected override IEnumerable<ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState) { var matchedText = engine.Input.Substring(initialState.Index, engine.State.Index - initialState.Index); IList<IList<ParenCapture>> captureSet = new List<IList<ParenCapture>>(); foreach (CapturingParens capturingParen in Children.FindBy(node => node is CapturingParens)) { var captures = engine.GetCaptures(capturingParen.Number); captureSet.Add(new ReadOnlyCollection<ParenCapture>(captures.ToList())); engine.PopCapture(capturingParen.Number); } yield return ParseStep.Match(this, initialState, matchedText, new ReadOnlyCollection<IList<ParenCapture>>(captureSet)); if (initialState.Index == engine.State.Index) { // If we had a successful match, and the engine didn't move, we need to move it ourselves now. engine.State = engine.State.Advance(); yield return ParseStep.AdvanceIndex(this, engine.State); } yield return ParseStep.BeginParse(this, engine.State); }
private void UserControl_Loaded(object sender, RoutedEventArgs e) { if (IsFullyLoaded) { return; } CurrentRegexEngine = RegexEngines.Single(n => n.Id == "DotNetRegex"); // default SetEngineOption(CurrentRegexEngine); ucPattern.SetFocus( ); IsFullyLoaded = true; Debug.Assert(!IsInChange); if (IsVisible) { if (InitialTabData != null) { var tab_data = InitialTabData; InitialTabData = null; StopAll( ); LoadTabData(tab_data); RestartAll( ); } else { ucPattern.SetRegexOptions(CurrentRegexEngine, GetEolOption( )); StopAll( ); RestartAll( ); } } }
protected override IEnumerable <ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState) { var matchedText = engine.Input.Substring(initialState.Index, engine.State.Index - initialState.Index); IList <IList <ParenCapture> > captureSet = new List <IList <ParenCapture> >(); foreach (CapturingParens capturingParen in Children.FindBy(node => node is CapturingParens)) { var captures = engine.GetCaptures(capturingParen.Number); captureSet.Add(new ReadOnlyCollection <ParenCapture>(captures.ToList())); engine.PopCapture(capturingParen.Number); } yield return(ParseStep.Match(this, initialState, matchedText, new ReadOnlyCollection <IList <ParenCapture> >(captureSet))); if (initialState.Index == engine.State.Index) { // If we had a successful match, and the engine didn't move, we need to move it ourselves now. engine.State = engine.State.Advance(); yield return(ParseStep.AdvanceIndex(this, engine.State)); } yield return(ParseStep.BeginParse(this, engine.State)); }
protected override IEnumerable<ParseStep> GetEndOfStringSteps(IRegexEngine engine) { yield return ParseStep.EndOfString(this, engine.State); }
public void SetRegexEngine(IRegexEngine regexEng) { regexEngine = regexEng ?? throw new ArgumentNullException(nameof(regexEng)); }
protected override int GetModifier(IRegexEngine outerEngine) { return 0; }
protected abstract IEnumerable<ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance);
protected abstract int GetModifier(IRegexEngine outerEngine);
protected override int GetModifier(IRegexEngine outerEngine) { return outerEngine.State.Index; }
internal override IEnumerable<ParseStep> Parse(IRegexEngine outerEngine) { var engine = new RegexEngine.RegexEngineInternal(GetEngineInput(outerEngine)); foreach (var capture in outerEngine.GetAllDefinedCaptures().SelectMany(kvp => kvp.Value)) { engine.AddCapture(capture.Number, capture.Index, capture.Value); } var modifier = GetModifier(outerEngine); bool match = false; yield return ParseStep.StartLookaround(this, engine.State).WithSkipAdvanceOnFail(ShouldSkipAdvance); foreach (var result in _regex.Parse(engine)) { // Don't report the results of the non-reporting start of string element. if (ReferenceEquals(result.Node, _nonReportingNode)) { continue; } if (ReferenceEquals(result.Node, _regex)) { if (result.Type == ParseStepType.Match) { match = true; break; } if (result.Type == ParseStepType.Fail) { continue; } if (result.Type == ParseStepType.Break) { break; } } if (result.Type != ParseStepType.Break && engine.State.Index <= engine.Input.Length) { yield return result .ConvertToOuterContext(outerEngine.Input, modifier, this, n => ReferenceEquals(n, _regex), message => message.Replace(_regex.NodeType, NodeType)) .AsLookaround() .WithSkipAdvanceOnFail(ShouldSkipAdvance); } } if (match) { if (!Negative) { // TODO: we need to forward any captures from the look-around to the outer engine. yield return ParseStep.Pass(this, "", outerEngine.State, engine.State.Plus(modifier)).WithSkipAdvanceOnFail(ShouldSkipAdvance); } else { yield return ParseStep.Fail(this, outerEngine.State, engine.State.Plus(modifier)).WithSkipAdvanceOnFail(ShouldSkipAdvance); } } else { if (!Negative) { yield return ParseStep.Fail(this, outerEngine.State, engine.State.Plus(modifier)).WithSkipAdvanceOnFail(ShouldSkipAdvance); } else { // TODO: we need to forward any captures from the look-around to the outer engine. yield return ParseStep.Pass(this, "", outerEngine.State, engine.State.Plus(modifier)).WithSkipAdvanceOnFail(ShouldSkipAdvance); } } yield return ParseStep.EndLookaround(this).WithSkipAdvanceOnFail(ShouldSkipAdvance); yield return ParseStep.Break(this).WithSkipAdvanceOnFail(ShouldSkipAdvance); }
internal override IEnumerable<ParseStep> Parse(IRegexEngine engine) { yield return ParseStep.BeginParse(this, engine.State); var savedStates = new Stack<SavedState>(); SavedState savedState = null; // Attempt the regex at every location in the input, starting at the beginning and going until just past the last position. while (engine.State.Index <= engine.Input.Length) { var initialState = engine.State; var matchSuccess = true; State failedState = null; var skipAdvanceOnFail = false; // For this location in the input, try every child node. for (var item = savedState == null ? Children.First : savedState.Item; item != null;) { var node = item.Value; var nodeResultEnumerator = savedState == null ? node.Parse(engine).GetEnumerator() : savedState.Enumerator; savedState = null; var nodeSuccess = false; // Get all the reported results from this child node. while (nodeResultEnumerator.MoveNext()) { var result = nodeResultEnumerator.Current; if (result.Type == ParseStepType.StateSaved) { // If decendent said it's saved its state - we need to do the same. var state = new SavedState(nodeResultEnumerator, item, result.CurrentState); engine.AddSavedState(state); savedStates.Push(state); } if (ReferenceEquals(node, result.Node)) // We only pay attention to our children's results { if (result.Type == ParseStepType.Pass) { // If our child told us it was successful, note it. nodeSuccess = true; } else if (result.Type == ParseStepType.Break) { // If our child told us to break, do so. (this indicates that the child was done, regardless of success or failure break; } else if (result.Type == ParseStepType.Fail) { failedState = result.CurrentState; skipAdvanceOnFail = result.SkipAdvanceOnFail; } } // Pass our children's results up. yield return result; } if (!nodeSuccess) { if (savedStates.Count > 0) { // If our child told us that it backtracked, begin backtracking. savedState = savedStates.Pop(); foreach (var capture in savedState.PopCaptures(engine)) { yield return ParseStep.CaptureDiscarded(savedState.Item.Value, capture.Value, capture.Number); } item = savedState.Item; } else { // If we're here, we either ran out of saved states, or didn't have any to begin with. Our current // node had no way of passing, so we'll fail at this index location in the input string. matchSuccess = false; break; } } else { item = item.Next; } } if (matchSuccess) { // Yay! We've matched the whole group! // However, we want to know if we're yielding an actual 'Match' - if we are, we need to clear our saved states. bool isMatch = false; foreach (var successStep in GetSuccessParseStep(engine, initialState)) { if (successStep.Type == ParseStepType.Match) { isMatch = true; } yield return successStep; } if (isMatch) { savedStates.Clear(); } // ...but if we're here, our enumerator has been started up again, indicating that we're backtracking. Oblige. if (savedStates.Count > 0) { // If our child told us that it backtracked, begin backtracking. savedState = savedStates.Pop(); foreach (var capture in savedState.PopCaptures(engine)) { yield return ParseStep.CaptureDiscarded(savedState.Item.Value, capture.Value, capture.Number); } engine.State = savedState.CurrentState; } } else { // We failed at this index location. Advance the engine and start all over again. Debug.Assert(failedState != null); foreach (var failStep in GetFailParseSteps(engine, initialState, failedState, skipAdvanceOnFail)) { yield return failStep; } } } // We always get here, regardless of success or failure. foreach (var endOfStringStep in GetEndOfStringSteps(engine)) { yield return endOfStringStep; } }
public IEnumerable<ParenCapture> PopCaptures(IRegexEngine engine) { var captures = _captures.ToArray(); return captures.Where(capture => engine.PopCapture(capture.Number)); }
protected abstract IEnumerable<ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState);
protected override IEnumerable<ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText) { // At this point, we know we'll match. Attempt to match everything else, until we hit max, a non-match, or the end of the string. // We need to save states as we go, in case we're asked to backtrack. var savedStates = new Stack<SavedState>(); int matchedQuantity = Min; for (; Max == null || matchedQuantity < Max; matchedQuantity++) { // If the last state we saved was at the end of the string, there's no point in going any further... if (savedStates.Count > 0 && savedStates.Peek().State.Index >= engine.Input.Length) { // Should we ever get here??? savedStates.Pop(); break; } if (engine.State.Index < engine.Input.Length) { // We're not at the end of the string, so save state before attempting a match - since we're greedy, we leave breadcrumbs before doing anything. savedStates.Push(new SavedState(engine.State, matchedText.ToString())); yield return ParseStep.StateSaved(this, engine.State, string.Format("Saving state - index {0}", engine.State.Index)); } else { // It looks like we're at the end of the string - which means we're done. Time to report as such. yield return ParseStep.EndOfString(this, engine.State); yield return ParseStep.Pass(this, matchedText.ToString(), initialState, engine.State); yield return ParseStep.Break(this); break; } var endOfMatch = false; // TODO: I think that we're going to need to use an enumerator here so we can initiate backtracking in our child and its descendants. 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); } else if (result.Type == ParseStepType.Fail) { endOfMatch = true; foreach (var backtrackStep in Backtrack(engine, initialState, savedStates)) { yield return backtrackStep; } break; } } } if (endOfMatch) { break; } } if (matchedQuantity >= Max) { // We've reached the maximum allowed quantity of repetitions, time to break; yield return ParseStep.Pass(this, matchedText.ToString(), initialState, engine.State); yield return ParseStep.Break(this); } // If we get here, it means that we're backtracking while (savedStates.Count > 0) { foreach (var backtrackStep in Backtrack(engine, initialState, savedStates)) { yield return backtrackStep; } } // If we get here, we ran out of saved states to backtrack to - report failure. engine.State = initialState; yield return ParseStep.Fail(this, initialState, engine.State, "No backtrack is available"); yield return ParseStep.Break(this); }
internal abstract IEnumerable <ParseStep> Parse(IRegexEngine engine);
protected override string GetEngineInput(IRegexEngine outerEngine) { return(outerEngine.Input.Substring(0, outerEngine.State.Index)); }
/// <summary> /// Parse the "non-required" quantities in the manner unique to the specific quantifier. /// </summary> protected abstract IEnumerable <ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText);
protected override int GetModifier(IRegexEngine outerEngine) { return(0); }
protected override string GetEngineInput(IRegexEngine outerEngine) { return outerEngine.Input.Substring(0, outerEngine.State.Index); }
public virtual void Init(IRegexEngine controller) { }
void IRegexView.Init(IRegexEngine engine) { Engine = engine; }
protected override IEnumerable <ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance) { yield return(ParseStep.Fail(this, initialState, currentState)); yield return(ParseStep.Break(this)); }
internal override IEnumerable <ParseStep> Parse(IRegexEngine engine) { throw new NotSupportedException(); }
protected override IEnumerable <ParseStep> GetEndOfStringSteps(IRegexEngine engine) { yield return(ParseStep.EndOfString(this, engine.State)); yield return(ParseStep.Break(this)); }
protected override IEnumerable<ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance) { yield return ParseStep.Fail(this, initialState, currentState); yield return ParseStep.Break(this); }
/// <summary> /// SetRegexEngine. /// </summary> /// <param name="regexEngine">Regex.</param> public void SetRegexEngine(IRegexEngine regexEngine) { this.regexEngine = regexEngine ?? throw new ArgumentNullException(nameof(regexEngine)); }
/// <summary> /// Parse the "non-required" quantities in the manner unique to the specific quantifier. /// </summary> protected abstract IEnumerable<ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText);
protected override IEnumerable <ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText) { throw new NotImplementedException(); }
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); }
internal override IEnumerable<ParseStep> Parse(IRegexEngine engine) { throw new NotImplementedException(); }
protected abstract string GetEngineInput(IRegexEngine outerEngine);
internal abstract IEnumerable<ParseStep> Parse(IRegexEngine engine);
protected override IEnumerable<ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText) { throw new NotImplementedException(); }
protected abstract IEnumerable<ParseStep> GetEndOfStringSteps(IRegexEngine engine);