예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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");
        }
예제 #3
0
        /// <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));
                        }
                    }
                }
            }
        }
예제 #4
0
        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));
            }
        }
예제 #5
0
        /// <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);
                        }
                    }
                }
            }
        }
예제 #6
0
        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);
                }
            }
        }
예제 #7
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)
                    {
                        engine.State = initialState;
                        yield return ParseStep.ResetIndex(this, initialState);
                    }
                }

                choiceIndex++;
            }

            yield return ParseStep.Fail(this, initialState, engine.State);
            yield return ParseStep.Break(this);
        }
예제 #8
0
 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);
 }
예제 #9
0
        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));
        }
예제 #10
0
 public IRegexEngine GetRegexEngine()
 {
     if (regexEngine == null)
     {
         regexEngine = new MSRegexCompiledEngine();
     }
     return(regexEngine);
 }
예제 #11
0
        void SetEngineOption(IRegexEngine engine)
        {
            var cbxitem = cbxEngine.Items.Cast <ComboBoxItem>( ).Single(i => i.Tag.ToString( ) == engine.Id);

            cbxEngine.SelectedItem = cbxitem;

            UpdateOptions(engine);
        }
예제 #12
0
        public IRegexView CreateView(IUseCase useCaseInstance)
        {
            IRegexView   newView = useCaseInstance.CreateNewView();
            IRegexEngine engine  = useCaseInstance.CreateNewEngine();

            engine.AttachView(newView);
            newView.Init(engine);

            return(newView);
        }
예제 #13
0
        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));
            }
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        // --------------------


        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;
            }
        }
예제 #16
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));
        }
예제 #17
0
        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));
            }
        }
예제 #18
0
        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));
        }
예제 #19
0
        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);
        }
예제 #20
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));
        }
예제 #21
0
        public void SetRegexOptions(IRegexEngine engine, string eol)
        {
            StopAll( );

            lock (this)
            {
                mRegexEngine = engine;
                mEol         = eol;
            }

            if (IsLoaded)
            {
                RecolouringLoop.SendWaitAndExecute( );
                HighlightingLoop.SendWaitAndExecute( );
            }
        }
예제 #22
0
        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);
        }
예제 #23
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);
        }
예제 #24
0
        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;
        }
예제 #25
0
        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);
            }
        }
예제 #26
0
        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
            }
        }
예제 #27
0
        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);
        }
예제 #28
0
        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( );
                }
            }
        }
예제 #29
0
        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));
        }
예제 #30
0
 protected override IEnumerable<ParseStep> GetEndOfStringSteps(IRegexEngine engine)
 {
     yield return ParseStep.EndOfString(this, engine.State);
 }
예제 #31
0
 public void SetRegexEngine(IRegexEngine regexEng)
 {
     regexEngine = regexEng ?? throw new ArgumentNullException(nameof(regexEng));
 }
예제 #32
0
 protected override int GetModifier(IRegexEngine outerEngine)
 {
     return 0;
 }
예제 #33
0
 protected abstract IEnumerable<ParseStep> GetFailParseSteps(IRegexEngine engine, State initialState, State currentState, bool skipAdvance);
예제 #34
0
 protected abstract int GetModifier(IRegexEngine outerEngine);
예제 #35
0
 protected override int GetModifier(IRegexEngine outerEngine)
 {
     return outerEngine.State.Index;
 }
예제 #36
0
        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);
        }
예제 #37
0
        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;
            }
        }
예제 #38
0
 public IEnumerable<ParenCapture> PopCaptures(IRegexEngine engine)
 {
     var captures = _captures.ToArray();
     return captures.Where(capture => engine.PopCapture(capture.Number));
 }
예제 #39
0
 protected abstract IEnumerable<ParseStep> GetSuccessParseStep(IRegexEngine engine, State initialState);
예제 #40
0
        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);
        }
예제 #41
0
 internal abstract IEnumerable <ParseStep> Parse(IRegexEngine engine);
예제 #42
0
 protected override string GetEngineInput(IRegexEngine outerEngine)
 {
     return(outerEngine.Input.Substring(0, outerEngine.State.Index));
 }
예제 #43
0
 /// <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);
예제 #44
0
 protected override int GetModifier(IRegexEngine outerEngine)
 {
     return(0);
 }
예제 #45
0
 protected override string GetEngineInput(IRegexEngine outerEngine)
 {
     return outerEngine.Input.Substring(0, outerEngine.State.Index);
 }
 public virtual void Init(IRegexEngine controller)
 {
 }
예제 #47
0
 void IRegexView.Init(IRegexEngine engine)
 {
     Engine = engine;
 }
예제 #48
0
        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));
        }
예제 #49
0
 internal override IEnumerable <ParseStep> Parse(IRegexEngine engine)
 {
     throw new NotSupportedException();
 }
예제 #50
0
        protected override IEnumerable <ParseStep> GetEndOfStringSteps(IRegexEngine engine)
        {
            yield return(ParseStep.EndOfString(this, engine.State));

            yield return(ParseStep.Break(this));
        }
예제 #51
0
 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));
 }
예제 #53
0
 /// <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);
예제 #54
0
 protected override IEnumerable <ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText)
 {
     throw new NotImplementedException();
 }
예제 #55
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);
 }
예제 #56
0
 internal override IEnumerable<ParseStep> Parse(IRegexEngine engine)
 {
     throw new NotImplementedException();
 }
예제 #57
0
 protected abstract string GetEngineInput(IRegexEngine outerEngine);
예제 #58
0
 internal abstract IEnumerable<ParseStep> Parse(IRegexEngine engine);
예제 #59
0
 protected override IEnumerable<ParseStep> ParseSpecific(IRegexEngine engine, State initialState, StringBuilder matchedText)
 {
     throw new NotImplementedException();
 }
예제 #60
0
 protected abstract IEnumerable<ParseStep> GetEndOfStringSteps(IRegexEngine engine);