public static RoutePattern Parse(string pattern) { if (pattern == null) { throw new ArgumentNullException(nameof(pattern)); } var trimmedPattern = TrimPrefix(pattern); var context = new TemplateParserContext(trimmedPattern); var segments = new List <RoutePatternPathSegment>(); while (context.MoveNext()) { var i = context.Index; if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new RoutePatternException(pattern, Resources.TemplateRoute_CannotHaveConsecutiveSeparators); } if (!ParseSegment(context, segments)) { throw new RoutePatternException(pattern, context.Error); } // A successful parse should always result in us being at the end or at a separator. Debug.Assert(context.AtEnd() || context.Current == Separator); if (context.Index <= i) { throw new InvalidProgramException("Infinite loop in the parser. This is a bug."); } } if (IsAllValid(context, segments)) { var builder = RoutePatternBuilder.Create(pattern); for (var i = 0; i < segments.Count; i++) { builder.PathSegments.Add(segments[i]); } return(builder.Build()); } else { throw new RoutePatternException(pattern, context.Error); } }
private static bool ParseSegment(TemplateParserContext context, List <RoutePatternPathSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var parts = new List <RoutePatternPart>(); while (true) { var i = context.Index; if (context.Current == OpenBrace) { if (!context.MoveNext()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, parts)) { return(false); } } else { // This is a parameter context.Back(); if (!ParseParameter(context, parts)) { return(false); } } } else { if (!ParseLiteral(context, parts)) { return(false); } } if (context.Current == Separator || context.AtEnd()) { // We've reached the end of the segment break; } if (context.Index <= i) { throw new InvalidProgramException("Infinite loop in the parser. This is a bug."); } } if (IsSegmentValid(context, parts)) { segments.Add(new RoutePatternPathSegment(null, parts.ToArray())); return(true); } else { return(false); } }