//private static readonly string[] multiwordStrings = Constants.Strings.Where(str => str.Contains("_")).ToArray(); public static Element ParseString(LanguageServer.Location location, string value, Element[] parameters, int depth = 0) { value = value.ToLower(); Stopwatch time = null; if (depth == 0 && Log.LogLevel == LogLevel.Verbose) { Log.Write(LogLevel.Verbose, $"Parsing String ", new ColorMod(value, ConsoleColor.Cyan)); time = new Stopwatch(); time.Start(); } //if (depth == 0) //foreach(string multiword in multiwordStrings) //value = value.Replace(multiword.Replace('_', ' '), multiword); string debug = new string(' ', depth * 4); // Loop through every string to search for. for (int i = 0; i < searchOrder.Length; i++) { string searchString = searchOrder[i]; // Converts string parameters ({0}, {1}, {2}) to regex expressions to get the values. // {#} -> (.+) string regex = Regex.Replace(Escape(searchString) , "({[0-9]})", @"(([a-z_.<>0-9-]+ ?)|(.+))"); // Add the regex expressions start-of-line and end-of-line to ensure that the entire string is parsed. regex = "^" + regex + "$"; // Match var match = Regex.Match(value, regex); if (match.Success) { Log.Write(LogLevel.Verbose, new ColorMod(debug + searchString, ConsoleColor.Gray)); // Create a string element with the found string. V_String str = new V_String(location, searchString); bool valid = true; // Confirms that the arguments were able to successfully parse. List <Element> parsedParameters = new List <Element>(); // The parameters that were successfully parsed. // Iterate through the parameters. for (int g = 1; g < match.Groups.Count; g += 3) { string currentParameterValue = match.Groups[g].Captures[0].Value; // Test if the parameter is a format parameter, for example <0>, <1>, <2>, <3>... Match parameterString = Regex.Match(currentParameterValue, "^<([0-9]+)>$"); if (parameters != null && parameterString.Success) { int index = int.Parse(parameterString.Groups[1].Value); // Throw syntax error if the number of parameters is less than the parameter index being set. if (index >= parameters.Length) { throw SyntaxErrorException.StringParameterCount(index, parameters.Length, location); } Log.Write(LogLevel.Verbose, $"{debug} <param {index}>"); parsedParameters.Add(parameters[index]); } else { // Parse the parameter. If it fails it will return null and the string being checked is probably false. var p = ParseString(location, currentParameterValue, parameters, depth + 1); if (p == null) { Log.Write(LogLevel.Verbose, $"{debug}{searchString} ", new ColorMod("combo fail", ConsoleColor.DarkRed)); valid = false; break; } parsedParameters.Add(p); } } str.ParameterValues = parsedParameters.ToArray(); if (!valid) { continue; } if (depth == 0 && time != null) { Log.Write(LogLevel.Verbose, $"String build ", new ColorMod("completed", ConsoleColor.DarkGreen), " in ", new ColorMod(time.ElapsedMilliseconds.ToString(), ConsoleColor.DarkCyan), " ms."); } return(str); } } if (depth > 0) { return(null); } else { // If the depth is 0, throw a syntax error. throw SyntaxErrorException.StringParseFailed(value, location); } }