Example #1
0
        private bool IsMatchCore(string test)
        {
            Stack <Checkpoint> checkpoints = new Stack <Checkpoint>();

            int currentMatcher = 0;
            int i = 0;

            //See if we can just do a name match
            if (_isNameOnlyMatch)
            {
                i = test.LastIndexOf('/') + 1;
            }

            while (i < test.Length)
            {
                IMatcher matcher = _matchers[currentMatcher];

                //If the matcher has a minimum zero width, isn't the last matcher and produces a checkpoint,
                //  we don't need to actually test for a match at this stage
                //Otherwise, test whether the matcher can consume starting at the current position
                if (currentMatcher < _matchers.Count - 1 && matcher.ProducesCheckpoint && matcher.MinConsume == 0 || matcher.CanConsume(test, i, out i))
                {
                    //If the current matcher isn't that last one and it produces a checkpoint, stash
                    //  the checkpoint info
                    if (currentMatcher < _matchers.Count - 1 && matcher.ProducesCheckpoint)
                    {
                        checkpoints.Push(new Checkpoint(matcher, currentMatcher + 1, i));
                    }

                    ++currentMatcher;

                    if (currentMatcher < _matchers.Count)
                    {
                        continue;
                    }

                    if (matcher.ProducesCheckpoint)
                    {
                        if (i < test.Length)
                        {
                            --currentMatcher;
                        }

                        continue;
                    }
                }

                if (currentMatcher == _matchers.Count && i == test.Length)
                {
                    return(true);
                }

                //If the match failed or we ran out of matchers, try to revert to an earlier checkpoint to re-evaluate
                //If we've got checkpoints left, back up one and see if it's usable
                while (checkpoints.Count > 0)
                {
                    Checkpoint checkpoint = checkpoints.Pop();

                    //If the matcher is usable...
                    //  restore the checkpoint
                    //  advance the string position
                    //  reset the current matcher to the one that followed the checkpoint
                    if (checkpoint.Matcher.CanConsume(test, checkpoint.StringPosition, out i))
                    {
                        checkpoint.StringPosition = i;
                        currentMatcher            = checkpoint.NextMatcherIndex;
                        checkpoints.Push(checkpoint);
                        break;
                    }
                }

                //If we ran out of checkpoints, the match has failed
                if (checkpoints.Count == 0)
                {
                    return(false);
                }
            }

            return(i == test.Length && currentMatcher == _matchers.Count);
        }