/// <summary> /// Parse the specified format string. /// </summary> /// <param name='format'> /// The format string. /// </param> public FormatStringParseResult Parse (string format) { if (format == null) throw new ArgumentNullException ("format"); var result = new FormatStringParseResult(); // Format string syntax: http://msdn.microsoft.com/en-us/library/txafckwd.aspx int textStart = 0; var length = format.Length; for (int i = 0; i < length; i++) { // Get fixed text GetText (format, ref i); if (i < format.Length && format [i] == '{') { int formatItemStart = i; int index; int? alignment = null; string argumentFormat = null; var textSegmentErrors = new List<IFormatStringError>(GetErrors()); // Try to parse the parts of the format item ++i; index = ParseIndex (format, ref i); CheckForMissingEndBrace (format, i, length); alignment = ParseAlignment (format, ref i, length); CheckForMissingEndBrace (format, i, length); argumentFormat = ParseSubFormatString (format, ref i, length); CheckForMissingEndBrace (format, i, length); // Check what we parsed if (i == formatItemStart + 1 && (i == length || (i < length && format [i] != '}'))) { // There were no format item after all, this was just an // unescaped left brace SetErrors(textSegmentErrors); AddError (new DefaultFormatStringError { Message = "Unescaped '{'", StartLocation = formatItemStart, EndLocation = formatItemStart + 1, OriginalText = "{", SuggestedReplacementText = "{{" }); continue; } else if (formatItemStart - textStart > 0) { // We have parsed a format item, end the text segment var textSegment = new TextSegment (UnEscape (format.Substring (textStart, formatItemStart - textStart))); textSegment.Errors = textSegmentErrors; result.Segments.Add (textSegment); } // Unclosed format items in fixed text gets advances i one step too far if (i < length && format [i] != '}') --i; // i may actually point outside of format if there is a syntactical error // if that happens, we want the last position var endLocation = Math.Min (length, i + 1); result.Segments.Add (new FormatItem (index, alignment, argumentFormat) { StartLocation = formatItemStart, EndLocation = endLocation, Errors = GetErrors () }); ClearErrors (); // The next potential text segment starts after this format item textStart = i + 1; } } // Handle remaining text if (textStart < length) { var textSegment = new TextSegment (UnEscape (format.Substring (textStart)), textStart); textSegment.Errors = GetErrors(); result.Segments.Add (textSegment); } return result; }
/// <summary> /// Parse the specified format string. /// </summary> /// <param name='format'> /// The format string. /// </param> public FormatStringParseResult Parse(string format) { if (format == null) { throw new ArgumentNullException("format"); } var result = new FormatStringParseResult(); // Format string syntax: http://msdn.microsoft.com/en-us/library/txafckwd.aspx int textStart = 0; var length = format.Length; for (int i = 0; i < length; i++) { // Get fixed text GetText(format, ref i); if (i < format.Length && format [i] == '{') { int formatItemStart = i; int index; int? alignment = null; string argumentFormat = null; var textSegmentErrors = new List <IFormatStringError>(GetErrors()); // Try to parse the parts of the format item ++i; index = ParseIndex(format, ref i); CheckForMissingEndBrace(format, i, length); alignment = ParseAlignment(format, ref i, length); CheckForMissingEndBrace(format, i, length); argumentFormat = ParseSubFormatString(format, ref i, length); CheckForMissingEndBrace(format, i, length); // Check what we parsed if (i == formatItemStart + 1 && (i == length || (i < length && format [i] != '}'))) { // There were no format item after all, this was just an // unescaped left brace SetErrors(textSegmentErrors); AddError(new DefaultFormatStringError { Message = "Unescaped '{'", StartLocation = formatItemStart, EndLocation = formatItemStart + 1, OriginalText = "{", SuggestedReplacementText = "{{" }); continue; } else if (formatItemStart - textStart > 0) { // We have parsed a format item, end the text segment var textSegment = new TextSegment(UnEscape(format.Substring(textStart, formatItemStart - textStart))); textSegment.Errors = textSegmentErrors; result.Segments.Add(textSegment); } // Unclosed format items in fixed text gets advances i one step too far if (i < length && format [i] != '}') { --i; } // i may actually point outside of format if there is a syntactical error // if that happens, we want the last position var endLocation = Math.Min(length, i + 1); result.Segments.Add(new FormatItem(index, alignment, argumentFormat) { StartLocation = formatItemStart, EndLocation = endLocation, Errors = GetErrors() }); ClearErrors(); // The next potential text segment starts after this format item textStart = i + 1; } } // Handle remaining text if (textStart < length) { var textSegment = new TextSegment(UnEscape(format.Substring(textStart)), textStart); textSegment.Errors = GetErrors(); result.Segments.Add(textSegment); } return(result); }