private void ReadLiteral(GlobPatternReader reader, char[] terminators) { var text = reader.ReadUntilAny(terminators); if (text.Length == 0) { return; } builder.Append(Regex.Escape(text)); }
private bool TryReadEscapeCode(GlobPatternReader reader, out string escaped) { escaped = ""; var firstCharacter = reader.ReadOne(); if (firstCharacter == null) { return(false); } escaped = firstCharacter.ToString(); return(true); }
public string Compile(string globPattern) { builder.Clear(); builder.Append("^"); var reader = new GlobPatternReader(globPattern); do { ReadLiteral(reader, BeginWildcardChars); if (reader.IsEndOfPattern) { break; } TryReadWildcard(reader); }while (!reader.IsEndOfPattern); builder.Append("$"); return(builder.ToString()); }
public IEnumerable <Token> Tokenise(ParseContext context) { var reader = new GlobPatternReader(context.Pattern); do { var start = reader.Position; var text = ReadLiteral(reader, beginSpecialChars); if (text.Length > 0) { yield return(Token.Literal(text, start, reader.Position)); } if (reader.IsEndOfPattern) { break; } yield return(TryReadSpecial(context, reader)); }while (!reader.IsEndOfPattern); }
private void TryReadWildcard(GlobPatternReader reader) { var start = reader.Position; if (reader.TryRead("/**/")) { builder.Append("/(.+/)?"); return; } if (reader.TryRead("/**")) { builder.Append("(/.+)?"); return; } if (reader.TryRead('/')) { builder.Append("/"); return; } if (reader.TryRead("**/")) { builder.Append("(.+/)?"); return; } if (reader.TryRead('*')) { builder.Append("[^/]*"); return; } if (reader.TryRead('?')) { builder.Append("[^/]"); return; } if (reader.TryRead('[')) { var range = reader.ReadUntilAny(WildcardChars); if (!reader.TryRead(']')) { throw reader.IsEndOfPattern ? new GlobFormatException($"Range at position {start} is not closed: {reader.GetSnippet(start, range.Length + 1)}", reader.Pattern, start) : new GlobFormatException($"Range at position {start} contains an invalid character: {reader.GetSnippet(5)}", reader.Pattern, start); } if (range.Length == 0) { throw new GlobFormatException($"Range at position {start} is empty: {reader.GetSnippet(start, 10)}", reader.Pattern, start); } var m = RxRange.Match(range); if (range[0] == '!') { if (range.Length == 1) { throw new GlobFormatException($"Range at position {start} is empty: {reader.GetSnippet(start, 10)}", reader.Pattern, start); } } if (!m.Success) { throw new GlobFormatException($"Range at position {start} is not valid: {reader.GetSnippet(start, range.Length + 2)}", reader.Pattern, start); } builder.Append('['); if (range[0] == '!') { builder.Append('^'); } builder.Append(Regex.Escape(m.Groups[1].Value)); builder.Append(']'); return; } throw new GlobFormatException($"Unable to parse wildcard expression at position {start}: {reader.GetSnippet(start, 10)}", reader.Pattern, start); }
private Token TryReadSpecial(ParseContext context, GlobPatternReader reader) { var start = reader.Position; if (reader.TryRead(SegmentSeparator)) { return(Token.Separator(start)); } if (reader.TryRead(EscapePrefix)) { if (!TryReadEscapeCode(reader, out var escaped)) { throw context.CreateError($"Invalid escape code: {reader.GetSnippet(start, reader.Position)}", start); } return(Token.Literal(escaped, start, reader.Position)); } if (reader.TryRead('*')) { if (reader.TryRead('*')) { return(Token.MatchAnyRecursive(start, reader.Position)); } return(Token.MatchAny(start, reader.Position)); } if (reader.TryRead('?')) { return(Token.MatchSingle(start, reader.Position)); } if (reader.TryRead('[')) { var range = reader.ReadUntilAny(wildcardChars); if (!reader.TryRead(']')) { throw reader.IsEndOfPattern ? context.CreateError($"Range at position {start} is not closed: {reader.GetSnippet(start, range.Length + 1)}", start) : context.CreateError($"Range at position {start} contains an invalid character: {reader.GetSnippet(5)}", start); } if (range.Length == 0) { throw context.CreateError($"Range at position {start} is empty: {reader.GetSnippet(start, 10)}", start); } var m = rxRange.Match(range); if (range[0] == '!') { if (range.Length == 1) { throw context.CreateError($"Range at position {start} is empty: {reader.GetSnippet(start, 10)}", start); } } if (!m.Success) { throw context.CreateError($"Range at position {start} is not valid: {reader.GetSnippet(start, range.Length + 2)}", start); } var rangeCharacters = m.Groups[1].Value; if (range[0] == '!') { return(Token.MatchRangeInverted(rangeCharacters, start, reader.Position)); } return(Token.MatchRange(rangeCharacters, start, reader.Position)); } if (reader.TryRead('{')) { var variableName = reader.ReadUntilAny(wildcardChars); if (!reader.TryRead('}')) { throw reader.IsEndOfPattern ? context.CreateError($"Variable reference at position {start} is not closed: {reader.GetSnippet(start, variableName.Length + 1)}", start) : context.CreateError($"Variable reference at position {start} contains an invalid character: {reader.GetSnippet(5)}", start); } return(Token.MatchVariable(variableName, start, reader.Position)); } throw context.CreateError($"Unable to parse wildcard expression at position {start}: {reader.GetSnippet(start, 10)}", start); }
private string ReadLiteral(GlobPatternReader reader, char[] terminators) { return(reader.ReadUntilAny(terminators)); }