public ParsedMatch <T>?TryMatch(StringPart stringPart)
        {
            var index = stringPart.Target.IndexOf(_needle, stringPart.StartIndex, stringPart.Length, _comparison);

            if (index >= 0)
            {
                var stringPartMatch = stringPart.Slice(index, _needle.Length);
                return(new ParsedMatch <T>(stringPartMatch, _transform(stringPartMatch)));
            }

            return(null);
        }
        public ParsedMatch <T>?TryMatch(StringPart stringPart)
        {
            var index = stringPart.Target.IndexOf(_needle, stringPart.StartIndex, stringPart.Length, _comparison);

            if (index < 0)
            {
                return(null);
            }

            var stringPartMatch = stringPart.Slice(index, _needle.Length);
            var value           = _transform(stringPartMatch);

            return(value is not null
                ? new ParsedMatch <T>(stringPartMatch, value)
                : null);
        }
Beispiel #3
0
        public static IEnumerable <ParsedMatch <T> > MatchAll <T>(this IMatcher <T> matcher,
                                                                  StringPart stringPart, Func <StringPart, T> transformFallback)
        {
            // Loop through segments divided by individual matches
            var currentIndex = stringPart.StartIndex;

            while (currentIndex < stringPart.EndIndex)
            {
                // Find a match within this segment
                var match = matcher.TryMatch(stringPart.Slice(currentIndex, stringPart.EndIndex - currentIndex));

                // If there's no match - break
                if (match is null)
                {
                    break;
                }

                // If this match doesn't start immediately at current index - transform and yield fallback first
                if (match.StringPart.StartIndex > currentIndex)
                {
                    var fallbackPart = stringPart.Slice(currentIndex, match.StringPart.StartIndex - currentIndex);
                    yield return(new ParsedMatch <T>(fallbackPart, transformFallback(fallbackPart)));
                }

                // Yield match
                yield return(match);

                // Shift current index to the end of the match
                currentIndex = match.StringPart.StartIndex + match.StringPart.Length;
            }

            // If EOL wasn't reached - transform and yield remaining part as fallback
            if (currentIndex < stringPart.EndIndex)
            {
                var fallbackPart = stringPart.Slice(currentIndex);
                yield return(new ParsedMatch <T>(fallbackPart, transformFallback(fallbackPart)));
            }
        }
Beispiel #4
0
        public ParsedMatch <T>?TryMatch(StringPart stringPart)
        {
            var match = _regex.Match(stringPart.Target, stringPart.StartIndex, stringPart.Length);

            if (!match.Success)
            {
                return(null);
            }

            // Overload regex.Match(string, int, int) doesn't take the whole string into account,
            // it effectively functions as a match check on a substring.
            // Which is super weird because regex.Match(string, int) takes the whole input in context.
            // So in order to properly account for ^/$ regex tokens, we need to make sure that
            // the expression also matches on the bigger part of the input.
            if (!_regex.IsMatch(stringPart.Target.Substring(0, stringPart.EndIndex), stringPart.StartIndex))
            {
                return(null);
            }

            var stringPartMatch = stringPart.Slice(match.Index, match.Length);

            return(new ParsedMatch <T>(stringPartMatch, _transform(stringPartMatch, match)));
        }