private RoutePatternParameter ParseParameter(string routeParameter) { // See: #475 - these tests don't pass the 'whole' text. var templatePart = InlineRouteParameterParser.ParseRouteParameter(string.Empty, routeParameter); return(templatePart); }
private static bool ParseParameter(TemplateParserContext context, List <RoutePatternPart> parts) { Debug.Assert(context.Current == OpenBrace); context.Mark(); context.MoveNext(); while (true) { if (context.Current == OpenBrace) { // This is an open brace inside of a parameter, it has to be escaped if (context.MoveNext()) { if (context.Current != OpenBrace) { // If we see something like "{p1:regex(^\d{3", we will come here. context.Error = Resources.TemplateRoute_UnescapedBrace; return(false); } } else { // This is a dangling open-brace, which is not allowed // Example: "{p1:regex(^\d{" context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } else if (context.Current == CloseBrace) { // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.MoveNext()) { // This is the end of the string -and we have a valid parameter break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name } else { // This is the end of the parameter break; } } if (!context.MoveNext()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } var text = context.Capture(); if (text == "{}") { context.Error = Resources.FormatTemplateRoute_InvalidParameterName(string.Empty); return(false); } var inside = text.Substring(1, text.Length - 2); var decoded = inside.Replace("}}", "}").Replace("{{", "{"); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(text, decoded); // See #475 - this is here because InlineRouteParameterParser can't return errors if (decoded.StartsWith("*") && decoded.EndsWith("?")) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return(false); } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return(false); } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { parts.Add(templatePart); return(true); } else { return(false); } }