public Format ParseFormat(string format) { var result = new Format(format); var current = result; Placeholder currentPlaceholder = null; // Store parsing errors until the end: var parsingErrors = new ParsingErrors(result); int nestedDepth = 0; int lastI = 0; int operatorIndex = 0; int selectorIndex = 0; for (int i = 0, length = format.Length; i < length; i++) { var c = format[i]; if (currentPlaceholder == null) { if (c == '{') { // Finish the last text item: if (i != lastI) current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); lastI = i + 1; // See if this brace should be escaped: if (!this.AlternativeEscaping) { var nextI = lastI; if (nextI < length && format[nextI] == '{') { i++; continue; } } // New placeholder: nestedDepth++; currentPlaceholder = new Placeholder(current, i, nestedDepth); current.Items.Add(currentPlaceholder); current.HasNested = true; operatorIndex = i+1; selectorIndex = 0; } else if (c == '}') { // Finish the last text item: if (i != lastI) current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); lastI = i + 1; // See if this brace should be escaped: if (!this.AlternativeEscaping) { var nextI = lastI; if (nextI < length && format[nextI] == '}') { i++; continue; } } // Make sure that this is a nested placeholder before we un-nest it: if (current.parent == null) { parsingErrors.AddIssue(current, "Format string has too many closing braces", i, i + 1); continue; } // End of the placeholder's Format: nestedDepth--; current.endIndex = i; current.parent.endIndex = i + 1; current = current.parent.parent; } else if (this.AlternativeEscaping && c == this.AlternativeEscapeChar) { // See if the next char is a brace that should be escaped: var nextI = i + 1; if (nextI < length && (format[nextI] == '{' || format[nextI] == '}')) { // Finish the last text item: if (i != lastI) current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); lastI = i + 1; i++; continue; } } } else { // Placeholder is NOT null, so that means we're parsing the selectors: if (Operators.IndexOf(c) != -1) { // Add the selector: if (i != lastI) { currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); selectorIndex++; operatorIndex = i; } lastI = i + 1; } else if (c == ':') { // Add the selector: if (i != lastI) currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); else if (operatorIndex != i) { // There are trailing operators. For now, this is an error. parsingErrors.AddIssue(current, "There are trailing operators in the selector", operatorIndex, i); //var issue = "There are trailing operators in the selector"; //ParserError(format, operatorIndex, issue, result); } lastI = i + 1; // Start the format: currentPlaceholder.Format = new Format(currentPlaceholder, i + 1); current = currentPlaceholder.Format; currentPlaceholder = null; } else if (c == '}') { // Add the selector: if (i != lastI) currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); else if (operatorIndex != i) { // There are trailing operators. For now, this is an error. parsingErrors.AddIssue(current, "There are trailing operators in the selector", operatorIndex, i); //ParserError(format, operatorIndex, "There are trailing operators in the selector", result); } lastI = i + 1; // End the placeholder with no format: nestedDepth--; currentPlaceholder.endIndex = i + 1; current = currentPlaceholder.parent; currentPlaceholder = null; } else { // Let's make sure the selector characters are valid: // Make sure it's alphanumeric: if (('0' <= c && c <= '9') || (AlphanumericSelectors && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')) || (AllowedSelectorChars.IndexOf(c) != -1)) { } else { // Invalid character in the selector. parsingErrors.AddIssue(current, "Invalid character in the selector", i, i + 1); //ParserError(format, i, "Invalid character in the selector", result); } } } } // finish the last text item: if (lastI != format.Length) current.Items.Add(new LiteralText(current, lastI) { endIndex = format.Length }); // Check that the format is finished: if (current.parent != null || currentPlaceholder != null) { //ParserError(format, format.Length, "Format string is missing a closing brace", result); parsingErrors.AddIssue(current, "Format string is missing a closing brace", format.Length, format.Length); current.endIndex = format.Length; while (current.parent != null) { current = current.parent.parent; current.endIndex = format.Length; } } // Check if there were any parsing errors: if (parsingErrors.HasIssues && ErrorAction == Core.ErrorAction.ThrowError) throw parsingErrors; return result; }
public Format ParseFormat(string format) { var result = new Format(format); var current = result; Placeholder currentPlaceholder = null; // Store parsing errors until the end: var parsingErrors = new ParsingErrors(result); int nestedDepth = 0; int lastI = 0; int operatorIndex = 0; int selectorIndex = 0; for (int i = 0, length = format.Length; i < length; i++) { var c = format[i]; if (currentPlaceholder == null) { if (c == '{') { // Finish the last text item: if (i != lastI) { current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); } lastI = i + 1; // See if this brace should be escaped: if (!this.AlternativeEscaping) { var nextI = lastI; if (nextI < length && format[nextI] == '{') { i++; continue; } } // New placeholder: nestedDepth++; currentPlaceholder = new Placeholder(current, i, nestedDepth); current.Items.Add(currentPlaceholder); current.HasNested = true; operatorIndex = i + 1; selectorIndex = 0; } else if (c == '}') { // Finish the last text item: if (i != lastI) { current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); } lastI = i + 1; // See if this brace should be escaped: if (!this.AlternativeEscaping) { var nextI = lastI; if (nextI < length && format[nextI] == '}') { i++; continue; } } // Make sure that this is a nested placeholder before we un-nest it: if (current.parent == null) { parsingErrors.AddIssue(current, "Format string has too many closing braces", i, i + 1); continue; } // End of the placeholder's Format: nestedDepth--; current.endIndex = i; current.parent.endIndex = i + 1; current = current.parent.parent; } else if (this.AlternativeEscaping && c == this.AlternativeEscapeChar) { // See if the next char is a brace that should be escaped: var nextI = i + 1; if (nextI < length && (format[nextI] == '{' || format[nextI] == '}')) { // Finish the last text item: if (i != lastI) { current.Items.Add(new LiteralText(current, lastI) { endIndex = i }); } lastI = i + 1; i++; continue; } } } else { // Placeholder is NOT null, so that means we're parsing the selectors: if (Operators.IndexOf(c) != -1) { // Add the selector: if (i != lastI) { currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); selectorIndex++; operatorIndex = i; } lastI = i + 1; } else if (c == ':') { // Add the selector: if (i != lastI) { currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); } else if (operatorIndex != i) { // There are trailing operators. For now, this is an error. parsingErrors.AddIssue(current, "There are trailing operators in the selector", operatorIndex, i); //var issue = "There are trailing operators in the selector"; //ParserError(format, operatorIndex, issue, result); } lastI = i + 1; // Start the format: currentPlaceholder.Format = new Format(currentPlaceholder, i + 1); current = currentPlaceholder.Format; currentPlaceholder = null; } else if (c == '}') { // Add the selector: if (i != lastI) { currentPlaceholder.Selectors.Add(new Selector(format, lastI, i, operatorIndex, selectorIndex)); } else if (operatorIndex != i) { // There are trailing operators. For now, this is an error. parsingErrors.AddIssue(current, "There are trailing operators in the selector", operatorIndex, i); //ParserError(format, operatorIndex, "There are trailing operators in the selector", result); } lastI = i + 1; // End the placeholder with no format: nestedDepth--; currentPlaceholder.endIndex = i + 1; current = currentPlaceholder.parent; currentPlaceholder = null; } else { // Let's make sure the selector characters are valid: // Make sure it's alphanumeric: if (('0' <= c && c <= '9') || (AlphanumericSelectors && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')) || (AllowedSelectorChars.IndexOf(c) != -1)) { } else { // Invalid character in the selector. parsingErrors.AddIssue(current, "Invalid character in the selector", i, i + 1); //ParserError(format, i, "Invalid character in the selector", result); } } } } // finish the last text item: if (lastI != format.Length) { current.Items.Add(new LiteralText(current, lastI) { endIndex = format.Length }); } // Check that the format is finished: if (current.parent != null || currentPlaceholder != null) { //ParserError(format, format.Length, "Format string is missing a closing brace", result); parsingErrors.AddIssue(current, "Format string is missing a closing brace", format.Length, format.Length); current.endIndex = format.Length; while (current.parent != null) { current = current.parent.parent; current.endIndex = format.Length; } } // Check if there were any parsing errors: if (parsingErrors.HasIssues && ErrorAction == ErrorAction.ThrowError) { throw parsingErrors; } return(result); }